Compare commits

..
103 Commits
Author SHA1 Message Date
Markus Fisch b554e7f47c Advance version number to 1.3.8 2019-02-19 22:04:38 +01:00
Markus Fisch 1085b63d25 Correct a spelling mistake in README 2019-02-14 19:55:16 +01:00
Markus Fisch ac900ec855 Remove pre-built libraries and use gradle instead
Because F-Droid won't accept apps that contain pre-built libraries
that aren't fetched from a white-listed Maven repository, see
https://github.com/markusfisch/BinaryEye/issues/1
2019-02-14 19:46:26 +01:00
Markus Fisch 8f68e66047 Update Kotlin version 2019-01-21 10:04:07 +01:00
Markus Fisch faf300db3e Advance version number to 1.3.7 2019-01-18 18:40:36 +01:00
Markus Fisch 2fbdd03225 Normalize URL scheme for resolveActivity()
Because Intent.resolveActivity() fails to resolve URLs
with uppercase schemes. Uri.normalizeScheme() will make
the scheme lowercase.
2019-01-18 18:28:08 +01:00
Markus Fisch 9f825f9d5d Update build tools and gradle wrapper 2019-01-18 18:27:50 +01:00
Markus Fisch 5ff1904148 Update build tools and Kotlin versions 2018-11-21 17:33:14 +01:00
Markus Fisch 16e80ff80e Update camera view library
setTapToFocus() is now available in the library.
2018-10-26 21:31:24 +02:00
Markus Fisch 1dcd1845a7 Update build tools and gradle wrapper 2018-10-09 10:00:33 +02:00
Markus Fisch 955f507023 Update tools version 2018-10-04 22:28:40 +02:00
Markus Fisch 47a3224b27 Advance version number to 1.3.6 2018-10-04 21:12:26 +02:00
Markus Fisch d2bf09d321 Update camera view library 2018-10-04 21:00:56 +02:00
Markus Fisch deee39b367 Use property access syntax to get scene modes 2018-10-04 20:57:59 +02:00
Markus Fisch 4829433725 Revert "Pick camera mode with kotlin's first syntax"
`first` throws if there is no such element so it can't
be used to pick an item that can be there.

This reverts commit 9efd43e496.
2018-10-04 14:54:26 +02:00
Felizia BernutzandMarkus Fisch 9efd43e496 Pick camera mode with kotlin's first syntax
Makes the code a little bit shorter and more kotlin like.
2018-10-04 09:51:41 +02:00
Felizia BernutzandMarkus Fisch 5bd904ba4f Handle no supported scene modes (#5)
Handle nullable result of getSupportedSceneModes()

Only search for SCENE_MODE_BARCODE if there are any supported scene
modes. This extra check prevents triggering onCameraError() when there
are no supported scene modes, which would result in an unusable
application.
2018-09-22 10:23:49 +02:00
Markus Fisch 3244f0775f Advance version number to 1.3.5 2018-08-08 18:48:06 +02:00
Markus Fisch f4d625a048 Fix some minor style issues 2018-08-08 18:29:34 +02:00
Markus Fisch c838486ca1 Apply Kotlin Coding Conventions
Functions that don't fit on a single line should use
the following syntax:

https://kotlinlang.org/docs/reference/coding-conventions.html#function-formatting
2018-07-29 23:37:02 +02:00
Markus Fisch d4a9ea1a4b Fix directory name of german resources
Because `values-de-DE` results in:
> Error: Invalid resource directory name
2018-07-29 23:35:55 +02:00
Markus Fisch 4123905853 Add german translation for encode button
Remove `app_name` because that's in `donottranslate.xml`.

And convert spaces to tabs.
2018-07-29 23:29:53 +02:00
Markus FischandGitHub 720811bf3b Add German translation
Merge pull request #4 from ialokim/german
2018-07-29 23:27:50 +02:00
Markus FischandGitHub 375fb4aa46 Fix Share intent handling
Merge pull request #3 from ialokim/encode-indent
2018-07-29 23:26:42 +02:00
Ialokim aa4b79d13d added German translation 2018-07-29 19:43:53 +02:00
Ialokim 1e9c303646 handle Intent.SEND correctly, directly opening EncodeFragment 2018-07-29 19:20:37 +02:00
Markus Fisch d3ab28f2b3 Update Kotlin version 2018-07-29 15:44:54 +02:00
Markus Fisch 7b67778a29 Return scan result for ZXing' SCAN intents
Of course, handling ZXing' SCAN intents makes only
sense when the app is returning the scanned data.

And that's why responding to IMAGE_CAPTURE does not
make sense at all. Removed that.
2018-07-29 15:40:47 +02:00
Markus Fisch d2c8ef719b Respond to IMAGE_CAPTURE and ZXing' SCAN intents
So a user can pick Binary Eye in the share menu.
2018-07-29 13:32:24 +02:00
Markus Fisch 7bed192300 Update build tools and target SDK 2018-07-05 21:32:03 +02:00
Markus Fisch 331f65f3a4 Advance version number to 1.3.4 2018-06-02 13:17:14 +02:00
Markus Fisch e17c732b6a Decrease RenderScript Target API to 18
Because it's recommended to "set this value to the lowest
API level able to provide all the functionality" (see
https://developer.android.com/guide/topics/renderscript/compute).

Targeting (RenderScript!) API 24 seems to make Google Play
not transfer the support libraries to devices running Nougat
or higher. If you're installing the (release) APK manually
everything works just fine. Install the APK with Google Play
and the app will crash.
2018-06-02 13:05:10 +02:00
Markus Fisch 2e60b2b997 Add hint to EditText for decoded content
Just to make lint happy.
2018-06-02 12:38:12 +02:00
Markus Fisch 70d9b8b99a Fix launcher foreground for adaptive icons 2018-06-02 12:34:02 +02:00
Markus Fisch d0cc7e0a68 Advance version number to 1.3.3 2018-06-01 14:05:37 +02:00
Markus Fisch 264e7ad098 Downsample to 3/4 only 2018-05-31 20:16:00 +02:00
Markus Fisch 8c33e9bd57 Add automated test for YUV processor 2018-05-29 21:00:26 +02:00
Markus Fisch a8fd37e4e4 Run setFocusArea() for ACTION_UP events only 2018-05-29 20:58:32 +02:00
Markus Fisch 17f11ea2de Improved RenderScript processing 2018-05-29 20:58:14 +02:00
Markus Fisch f6a582e4f7 Include aar of CameraView library
Because you simply cannot rely on JitPack.
2018-05-29 19:47:28 +02:00
Markus Fisch 6e645a567a Use XML drawable for launcher background
Much smaller.
2018-05-27 21:35:22 +02:00
Markus Fisch e87dc35372 Downsample camera frame to soften artifacts
Because ZXing has problems recognizing barcodes when there
are screen artifacts in the image. Makes it hard to scan a
QR code from a screen.
2018-05-27 21:29:35 +02:00
Markus Fisch 75f4f3eadc Use property access syntax 2018-05-27 21:23:39 +02:00
Markus Fisch 64e1d722d5 Route raw YUV data to ZXing
And don't convert it into a Bitmap just to read the
pixels back from it.
2018-05-20 15:31:40 +02:00
Markus Fisch 05a206384c Add a comment explaining that !! operator 2018-05-20 14:48:21 +02:00
Markus Fisch 04790e2b57 Rename YuvToGray to Preprocessor
This class does more than just converting from
YUV to gray so this is a better name.
2018-05-20 13:45:38 +02:00
Markus Fisch aa3c4a17e9 Rename function files to use camel humps
According to the Kotlin Coding Conventions
(https://kotlinlang.org/docs/reference/coding-conventions.html)
files that contain only top-level declarations should also
use camel humps with an uppercase first letter.
2018-05-20 13:33:03 +02:00
Markus Fisch 5968ae01eb Add adaptive icon for Android 8+ 2018-05-14 21:06:01 +02:00
Markus Fisch 57500b7700 Decrease default zoom to 10% 2018-05-09 22:50:47 +02:00
Markus Fisch 4e17a21e5f Update camera library and use orientation listener
To handle landscape to landscape rotations.
2018-05-07 20:12:51 +02:00
Markus Fisch 605dc51d50 Update Kotlin version 2018-05-06 14:45:43 +02:00
Markus Fisch b17d29ba28 Increase size of logo on splash screen 2018-04-30 11:01:54 +02:00
Markus Fisch 9afc7fcc62 Update Kotlin and tools version 2018-04-28 11:54:11 +02:00
Markus Fisch d5543d0c39 Update gradle plugin and tools version 2018-04-15 15:37:25 +02:00
Markus Fisch 96fea1f343 Start decoding only when preview has started 2018-03-03 18:33:32 +01:00
Markus Fisch bc4d9f7148 Update to latest CameraView 2018-03-03 18:32:56 +01:00
Markus Fisch 4abacf030b Include CameraView library over jitpack
Also update to CameraView 1.4.0 and use 'implementation'
instead of 'compile' because Gradle 4 says so.
2018-03-01 14:34:45 +01:00
Markus Fisch 279c988464 Apply Kotlin Coding Conventions
From:
https://kotlinlang.org/docs/reference/coding-conventions.html
2018-02-27 14:22:41 +01:00
Markus Fisch a6449b50e9 Update build tools and Kotlin version 2018-02-27 10:44:16 +01:00
Markus Fisch b4e6449dac Decrease default magnification to 20% 2018-02-27 10:38:54 +01:00
Markus Fisch c3dfadd9e6 Move Java static class into Kotlin function file
All methods of SystemBarMetrics can be static so it's
better to get rid of that empty container class.
2017-12-18 21:37:49 +01:00
Markus Fisch bad5225024 Clean up supported screen settings
According to the docs, `resizeable` is deprecated and
`smallScreens`, `normalScreens`, `anyDensity` are true
by default.
2017-12-16 13:31:56 +01:00
Markus Fisch aa9b4927b0 Update to latest CameraView 2017-12-10 18:06:45 +01:00
Markus Fisch 69d12910cd Remove Travis CI integration
Apparently, at least for Android builds, Travis CI just doesn't
cut the mustard.

After updating the SDK version to 27, Travis CI *always* fails
to build the project because the android-27 license is not accepted.
I've done everything https://docs.travis-ci.com/user/languages/android/
told me to but still, it won't build.

So I've got enough of Travis CI and that's it. If that thing can't
build a standard Android project, it's simply not useful to me.
2017-12-09 12:44:57 +01:00
Markus Fisch ee0f7c4529 Advance version number to 1.3.2 2017-12-08 22:28:41 +01:00
Markus Fisch 1b296ff83e Update to latest CameraView 2017-12-08 22:26:26 +01:00
Markus Fisch 1a635af7b7 Update to gradle 4 2017-12-08 22:07:05 +01:00
Markus Fisch 568530d470 Use safe calls instead of explicit null checks
Do it the Kotlin way.
2017-12-07 22:01:24 +01:00
Markus Fisch 6248b46fc8 Advance version number to 1.3.1 2017-11-13 21:10:10 +01:00
Markus Fisch 3083d2b625 Change primary colors
Was rejected because the launcher icon was too close to
another app with almost the same primary colors.
2017-11-13 21:03:37 +01:00
Markus Fisch e02420d446 Advance version number to 1.3.0 2017-11-12 21:43:55 +01:00
Markus Fisch e63fe0d601 Save chosen zoom level permanently 2017-11-12 21:42:54 +01:00
Markus Fisch 0803fdcac8 Check Intent.getStringExtra() for null before use 2017-11-12 21:36:05 +01:00
Markus Fisch e64dd2e972 Update to latest Kotlin version 2017-11-12 21:20:38 +01:00
Markus Fisch 418edd34a5 Support tap to focus
Focus that exact spot a user taps on. Helps getting a clear
image on some devices. After 3 seconds the app will return
to the best possible auto focus.
2017-11-12 21:14:51 +01:00
Markus Fisch af2a1dc940 Update CameraView library to latest version 2017-11-12 21:14:27 +01:00
Markus Fisch e0c420c29f Update ZXing to latest version 3.3.2 2017-11-11 14:11:50 +01:00
Markus Fisch 0ba41ca863 Advanced version number to 1.2.0 2017-11-04 22:52:27 +01:00
Markus Fisch ed1826679e Link CI badge with corresponding Travis page 2017-11-04 22:38:07 +01:00
Markus Fisch bd75b5b71d Updated to latest version of CameraView 2017-11-04 22:37:24 +01:00
Markus Fisch bbdf724bbb Update CameraView library to lastest version
Fixes two formal issues some static analyzers will complain
about.
2017-10-28 18:21:06 +02:00
Markus Fisch 0ace08c8b4 Add SonarQube rule to Makefile
To run SonarQube before committing.
2017-10-28 18:07:39 +02:00
Markus Fisch 41164c31f1 Add SonarQube integration again
Reading through the docs it became clear that the secure
token is repository specific so that was the mistake.
2017-10-28 17:54:03 +02:00
Markus Fisch 9f3288e7a8 Revert "Add SonarQube integration"
Somehow SonarQube always says not authorized but the token
is valid and works in another project. May be that SonarQube
cloud allows only one project per organization ...

This reverts commit 26a19a9657.
2017-10-27 09:27:26 +02:00
Markus Fisch a61fc63fa6 Add a Build Passing icon to the README 2017-10-26 23:06:54 +02:00
Markus Fisch 26a19a9657 Add SonarQube integration 2017-10-26 23:05:31 +02:00
Markus Fisch a0d157551a Add Travis CI 2017-10-26 22:59:46 +02:00
Markus Fisch 53fe8b3689 Save zoom level over orientation changes 2017-10-26 22:49:24 +02:00
Markus Fisch 0da9e34e55 Set a default zoom of 1/3 2017-10-26 21:53:12 +02:00
Markus Fisch db276372b7 Enable back arrow for MainActivity first fragments
MainActivity is a subsequent activity and has always a back
arrow now.
2017-10-26 21:52:52 +02:00
Markus Fisch c148635c26 Set a modest wallpaper as window background 2017-10-26 21:50:11 +02:00
Markus Fisch 5c99309125 Call onCameraError() when Camera.open() fails too
And remove the Camera argument from onCameraError() as it
wouldn't make sense when Camera.open() fails.
2017-10-24 22:33:46 +02:00
Markus Fisch 2443eb066a Call Thread.interrupt() after InterruptedException
Explicitly try to interrupt the thread after an
InterruptedException.
2017-10-24 21:57:42 +02:00
Markus Fisch d7281266e4 Add missing permission checking to camera activity
Somehow I forgot to check for the camera permission.
I should pick a device running Marshmallow for testing by now.
2017-10-24 21:54:54 +02:00
Markus Fisch e8c676ab8c Remove marker source graphic
No longer needed.
2017-10-20 21:26:02 +02:00
Markus Fisch 6c1353596d Use a dedicated camera activity
By removing the camera fragment everything gets much
simpler.
2017-10-20 21:18:55 +02:00
Markus Fisch ff14130c91 Put a thin horizontal line over scan camera
Makes it easy to align a barcode with the camera.
2017-10-20 21:18:39 +02:00
Markus Fisch e0147df76c Put flash action into fab
Swap flash with create action.

Originally I put the flash action in the toolbar
because not all devices have a flash. But it makes
more sense to have the flash beside the zoom slider.
2017-10-20 21:18:19 +02:00
Markus Fisch cbc2b6b8db Remove the locking markers
While the animation is nice, they're not very helpful
for actually scanning a barcode. A simple line is
probably a better to choice.
2017-10-20 21:17:59 +02:00
Markus Fisch bc727ab45f Add a zoom slider 2017-10-20 21:17:41 +02:00
Markus Fisch 9e8153e8f6 Update CameraView to 1.1.0
Handle camera errors when getting or setting parameters.
2017-10-18 22:58:36 +02:00
Markus Fisch b9a5687c5a Advanced version number to 1.1.1 2017-09-03 12:35:35 +02:00
Markus Fisch cbc0ff435f Invert every second frame
Forgot to invert every second frame to also read inverted
barcodes while simplifying image processing.
2017-09-03 12:26:49 +02:00
94 changed files with 3127 additions and 1505 deletions
+44 -1
View File
@@ -1,7 +1,50 @@
# Change Log
## 1.3.8
* Qualify for F-Droid
## 1.3.7
* Normalize URL schemes
## 1.3.6
* Fix handling of camera scene modes
## 1.3.5
* Add german translation
* Fix handling of data intents
* Respond to ZXing' SCAN intents
## 1.3.4
* Fix pre-processing for Android 7+
* Fix adaptive icons for Android 8+
## 1.3.3
* Improved pre-processing
* Added adaptive icon for Android 8+
* Decrease default magnification to 10%
## 1.3.2
* Fixed crash when going back very fast
## 1.3.1
* Changed primary color
## 1.3.0
* Support tap to focus
* Save chose zoom level permanently
* Update ZXing to latest version (3.3.2)
## 1.2.0
* Added a camera zoom slider
* Added an unobtrusive wallpaper background
* Replaced lock marks with just a horizontal line
* Put toggling torch mode into Floating Action Button
## 1.1.1
* Brought back inverting every second frame
## 1.1.0
* Create barcodes now too
* Create barcodes
* Streamlined video pre-processing
* Decoded content is editable now
* Fixed position of lock marks on tablets
+7 -1
View File
@@ -1,5 +1,5 @@
PACKAGE = de.markusfisch.android.binaryeye
APK = app/build/outputs/apk/app-debug.apk
APK = app/build/outputs/apk/debug/app-debug.apk
all: debug install start
@@ -16,9 +16,15 @@ release: lint
lint:
./gradlew lintDebug
sonarqube:
./gradlew sonarqube
infer: clean
infer -- ./gradlew assembleDebug
test:
./gradlew cAT
install:
adb $(TARGET) install -r $(APK)
+1 -1
View File
@@ -11,7 +11,7 @@ a barcode.
<a href="https://play.google.com/store/apps/details?id=de.markusfisch.android.binaryeye"><img alt="Get it on Google Play" src="https://play.google.com/intl/en_us/badges/images/apps/en-play-badge.png" height="45px"/></a>
And it's written in [Kotlin][kotlin] because I've wanted to explore that a
And it's written in [Kotlin][kotlin] because I wanted to explore that a
bit more.
[play]: https://play.google.com/store/search?q=barcode%20scanner&c=apps
+24 -8
View File
@@ -14,11 +14,19 @@ android {
minSdkVersion 9
targetSdkVersion sdk_version
versionCode 3
versionName '1.1.0'
versionCode 14
versionName '1.3.8'
renderscriptTargetApi 24
// it's recommended to set this value to the lowest API level
// able to provide all the functionality
renderscriptTargetApi 18
renderscriptSupportModeEnabled true
testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
}
sourceSets {
androidTest.java.srcDirs += 'src/androidTest/kotlin'
}
buildTypes {
@@ -44,9 +52,17 @@ android {
}
dependencies {
compile fileTree(dir: 'libs', include: '*')
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
compile "com.android.support:appcompat-v7:$support_version"
compile "com.android.support:design:$support_version"
compile project(':cameraview')
androidTestImplementation ('com.android.support.test:runner:1.0.2') {
exclude module: 'support-annotations'
}
androidTestImplementation ('com.android.support.test:rules:1.0.2') {
exclude module: 'support-annotations'
}
testImplementation 'junit:junit:4.12'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "com.android.support:appcompat-v7:$support_version"
implementation "com.android.support:design:$support_version"
implementation 'com.google.zxing:core:3.3.3'
implementation 'com.github.markusfisch:CameraView:1.8.1'
}
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,52 @@
package de.markusfisch.android.binaryeye
import android.support.test.InstrumentationRegistry
import android.support.test.runner.AndroidJUnit4
import de.markusfisch.android.binaryeye.rs.Preprocessor
import de.markusfisch.android.binaryeye.zxing.Zxing
import org.junit.Test
import org.junit.runner.RunWith
import java.util.regex.Pattern
@RunWith(AndroidJUnit4::class)
class PreprocessorTest {
@Test
fun processSamples() {
val zxing = Zxing()
val assets = InstrumentationRegistry.getInstrumentation()
.context.assets
val pattern = Pattern.compile(
"[0-9]+-([0-9]+)x([0-9]+)-([0-9]+)deg.yuv"
)
for (file in assets.list("yuv")) {
val m = pattern.matcher(file)
if (!m.find() || m.groupCount() < 3) {
continue
}
val frameWidth = m.group(1).toInt()
val frameHeight = m.group(2).toInt()
val frameOrientation = m.group(3).toInt()
val frameData = assets.open("yuv/$file").readBytes()
val preprocessor = Preprocessor(
InstrumentationRegistry.getTargetContext(),
frameWidth,
frameHeight,
frameOrientation
)
preprocessor.process(frameData)
val result = zxing.decode(
frameData,
preprocessor.outWidth,
preprocessor.outHeight
)
preprocessor.destroy()
checkNotNull(result) { "no barcode found in $file" }
}
}
}
@@ -0,0 +1,83 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M32.002,-24.974h3.127v7.656h-3.127z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:pathData="m54.826,27.893c-6.851,0 -13.701,2.581 -18.924,7.745 -10.445,10.328 -10.413,27.062 0,37.423l36.218,36.036 37.879,0.902 -0.07,-38.363 -36.18,-35.998c-5.207,-5.18 -12.073,-7.745 -18.924,-7.745z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="8.60725021"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillAlpha="0.1254902"
android:strokeLineCap="butt"/>
<path
android:pathData="M28.001,54.118a26.525,26.227 0,1 0,53.049 0a26.525,26.227 0,1 0,-53.049 0z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillAlpha="1"
android:strokeLineCap="butt"/>
<path
android:pathData="M39.26,54.988a14.509,14.346 0,1 0,29.019 0a14.509,14.346 0,1 0,-29.019 0z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillAlpha="1"
android:strokeLineCap="butt"/>
<path
android:pathData="M54.034,44.513a9.535,9.428 0,1 0,19.07 0a9.535,9.428 0,1 0,-19.07 0z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="10"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillAlpha="1"
android:strokeLineCap="butt"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:pathData="m62.745,24.783c-2.055,1.011 -2.87,3.415 -1.847,5.446 0.588,1.168 1.642,1.916 2.839,2.168 -0.564,0.884 -0.835,1.972 -0.925,3.156 -1.782,-0.45 -3.735,-0.191 -5.25,0.639a0.799,0.808 90,0 0,-0.132 0.172,0.799 0.808,90 0,0 -0.132,0.172 0.799,0.808 90,0 0,-0.132 0.39,0.799 0.808,90 0,0 0.044,0.304 0.799,0.808 90,0 0,0.437 0.433,0.799 0.808,90 0,0 0.131,0.043 0.799,0.808 90,0 0,0.131 0.043,0.799 0.808,90 0,0 0.218,-0 0.799,0.808 90,0 0,0.263 -0.129c1.29,-0.707 2.97,-0.892 4.375,-0.425 0.096,0.882 0.341,1.782 0.695,2.683 -0.456,0.072 -0.936,0.177 -1.357,0.343 -1.207,0.48 -2.245,1.302 -3.022,2.244a0.799,0.808 90,0 0,-0.044 0.129,0.799 0.808,90 0,0 -0.088,0.258 0.799,0.808 90,0 0,0.044 0.304,0.799 0.808,90 0,0 0.393,0.563 0.799,0.808 90,0 0,0.394 0.131,0.799 0.808,90 0,0 0.175,-0.086 0.799,0.808 90,0 0,0.175 -0.086,0.799 0.808,90 0,0 0.219,-0.215c0.922,-1.115 2.409,-1.925 3.897,-2.025 0.494,0.845 1.016,1.575 1.658,2.209 -1.232,1.149 -2.043,2.664 -2.239,4.234a0.799,0.808 90,0 0,-0.001 0.215,0.799 0.808,90 0,0 0.174,0.346 0.799,0.808 90,0 0,0.043 0.086,0.799 0.808,90 0,0 0.219,0.217 0.799,0.808 90,0 0,0.131 0.043,0.799 0.808,90 0,0 0.131,0.043 0.799,0.808 90,0 0,0.218 -0,0.799 0.808,90 0,0 0.218,-0 0.799,0.808 90,0 0,0.132 -0.172,0.799 0.808,90 0,0 0.175,-0.086 0.799,0.808 90,0 0,0.044 -0.129,0.799 0.808,90 0,0 0.088,-0.258 0.799,0.808 90,0 0,0.044 -0.129c0.159,-1.272 0.816,-2.493 1.799,-3.371 1.966,1.394 4.252,1.797 6.122,0.876 1.892,-0.931 2.903,-3.018 2.941,-5.444 1.327,-0.259 2.813,0.014 3.936,0.656a0.799,0.808 90,0 0,0.174 0.129,0.799 0.808,90 0,0 0.131,0.043 0.799,0.808 90,0 0,0.088 -0.043,0.799 0.808,90 0,0 0.218,-0 0.799,0.808 90,0 0,0.087 -0.043,0.799 0.808,90 0,0 0.175,-0.086 0.799,0.808 90,0 0,0.132 -0.172,0.799 0.808,90 0,0 0.132,-0.172 0.799,0.808 90,0 0,0.045 -0.562,0.799 0.808,90 0,0 -0.043,-0.086 0.799,0.808 90,0 0,-0.262 -0.303,0.799 0.808,90 0,0 -0.131,-0.043c-1.386,-0.792 -3.097,-1.066 -4.766,-0.787 -0.125,-0.89 -0.309,-1.783 -0.695,-2.683 0.982,-1.073 2.47,-1.756 3.896,-1.81a0.799,0.808 90,0 0,0.131 0.043,0.799 0.808,90 0,0 0.087,-0.043 0.799,0.808 90,0 0,0.482 -0.345,0.799 0.808,90 0,0 0.044,-0.129 0.799,0.808 90,0 0,0.088 -0.476,0.799 0.808,90 0,0 -0.043,-0.086 0.799,0.808 90,0 0,-0.262 -0.303,0.799 0.808,90 0,0 -0.043,-0.086 0.799,0.808 90,0 0,-0.394 -0.131,0.799 0.808,90 0,0 -0.131,-0.043c-1.227,0.048 -2.518,0.369 -3.633,1.031 -0.388,0.233 -0.762,0.548 -1.095,0.864 -0.513,-0.821 -1.093,-1.559 -1.746,-2.166 0.47,-1.39 1.632,-2.605 2.98,-3.195a0.799,0.808 90,0 0,0.175 -0.086,0.799 0.808,90 0,0 0.132,-0.172 0.799,0.808 90,0 0,0.132 -0.172,0.799 0.808,90 0,0 0.132,-0.39 0.799,0.808 90,0 0,-0.043 -0.086,0.799 0.808,90 0,0 -0.174,-0.346 0.799,0.808 90,0 0,-0.043 -0.086,0.799 0.808,90 0,0 -0.437,-0.217 0.799,0.808 90,0 0,-0.175 0.086,0.799 0.808,90 0,0 -0.131,-0.043 0.799,0.808 90,0 0,-0.087 0.043,0.799 0.808,90 0,0 -0.131,-0.043c-1.584,0.694 -2.97,2.079 -3.681,3.756 -1.012,-0.644 -2.048,-1.087 -3.104,-1.173 0.53,-1.101 0.642,-2.414 0.05,-3.59 -1.023,-2.031 -3.541,-2.795 -5.596,-1.783z"
android:fillColor="#ff2a2a"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
<path
android:pathData="m66.624,32.489c0.281,-0.138 1.896,2.465 3.62,5.889 1.724,3.424 2.893,6.354 2.613,6.492 -0.281,0.138 -1.94,-2.551 -3.663,-5.975 -1.724,-3.424 -2.85,-6.268 -2.569,-6.406z"
android:fillColor="#d40000"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
</vector>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

+10 -6
View File
@@ -3,11 +3,7 @@
package="de.markusfisch.android.binaryeye"
android:installLocation="auto">
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:resizeable="true"
android:smallScreens="true"
android:xlargeScreens="true"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.VIBRATE"/>
@@ -17,6 +13,7 @@
tools:ignore="UnusedAttribute"
android:allowBackup="true"
android:fullBackupContent="true"
android:supportsRtl="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">
@@ -30,13 +27,17 @@
</intent-filter>
</activity>
<activity
android:name=".activity.MainActivity"
android:name=".activity.CameraActivity"
android:label="@string/scan_code">
<intent-filter>
<intent-filter android:label="@string/compose_barcode">
<action android:name="android.intent.action.SEND"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<intent-filter>
<action android:name="com.google.zxing.client.android.SCAN"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
@@ -47,5 +48,8 @@
android:scheme="http"/>
</intent-filter>
</activity>
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name"/>
</application>
</manifest>
@@ -0,0 +1,401 @@
package de.markusfisch.android.binaryeye.activity
import com.google.zxing.Result
import de.markusfisch.android.cameraview.widget.CameraView
import de.markusfisch.android.binaryeye.app.initSystemBars
import de.markusfisch.android.binaryeye.rs.Preprocessor
import de.markusfisch.android.binaryeye.zxing.Zxing
import de.markusfisch.android.binaryeye.R
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.SharedPreferences
import android.hardware.Camera
import android.net.Uri
import android.os.Bundle
import android.os.Vibrator
import android.preference.PreferenceManager
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.SeekBar
import android.widget.Toast
class CameraActivity : AppCompatActivity() {
private val zxing = Zxing()
private val decodingRunnable = Runnable {
while (decoding) {
val result = decodeFrame()
if (result != null) {
cameraView.post { found(result) }
decoding = false
break
}
}
}
private lateinit var preferences: SharedPreferences
private lateinit var vibrator: Vibrator
private lateinit var cameraView: CameraView
private lateinit var zoomBar: SeekBar
private var decoding = false
private var decodingThread: Thread? = null
private var preprocessor: Preprocessor? = null
private var frameData: ByteArray? = null
private var frameWidth: Int = 0
private var frameHeight: Int = 0
private var frameOrientation: Int = 0
private var invert = false
private var flash = false
private var returnResult = false
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
when (requestCode) {
REQUEST_CAMERA -> if (grantResults.size > 0 &&
grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(
this,
R.string.no_camera_no_fun,
Toast.LENGTH_SHORT
).show()
finish()
}
}
}
override fun onCreate(state: Bundle?) {
super.onCreate(state)
setContentView(R.layout.activity_camera)
initSystemBars(this)
setSupportActionBar(findViewById(R.id.toolbar) as Toolbar)
preferences = PreferenceManager.getDefaultSharedPreferences(this)
vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
cameraView = findViewById(R.id.camera_view) as CameraView
zoomBar = findViewById(R.id.zoom) as SeekBar
initCameraView()
initZoomBar()
restoreZoom()
initFlashFab(findViewById(R.id.flash))
}
override fun onDestroy() {
super.onDestroy()
preprocessor?.destroy()
saveZoom()
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleSendText(intent)
}
override fun onResume() {
super.onResume()
System.gc()
returnResult = "com.google.zxing.client.android.SCAN".equals(
intent.action
)
handleSendText(intent)
if (hasCameraPermission()) {
cameraView.openAsync(
CameraView.findCameraId(
Camera.CameraInfo.CAMERA_FACING_BACK
)
)
}
}
override fun onPause() {
super.onPause()
cancelDecoding()
cameraView.close()
}
override fun onRestoreInstanceState(savedState: Bundle) {
super.onRestoreInstanceState(savedState)
zoomBar.max = savedState.getInt(ZOOM_MAX)
zoomBar.progress = savedState.getInt(ZOOM_LEVEL)
}
override fun onSaveInstanceState(outState: Bundle) {
outState.putInt(ZOOM_MAX, zoomBar.max)
outState.putInt(ZOOM_LEVEL, zoomBar.progress)
super.onSaveInstanceState(outState)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.activity_camera, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.create -> {
startActivity(MainActivity.getEncodeIntent(this))
true
}
R.id.info -> {
openReadme()
true
}
else -> super.onOptionsItemSelected(item)
}
}
private fun openReadme() {
startActivity(
Intent(
Intent.ACTION_VIEW, Uri.parse(
"https://github.com/markusfisch/BinaryEye/blob/master/README.md"
)
)
)
}
private fun handleSendText(intent: Intent) {
if (!Intent.ACTION_SEND.equals(intent.getAction()) ||
!"text/plain".equals(intent.getType())) {
return
}
var text = intent.getStringExtra(Intent.EXTRA_TEXT)
if (text == null || text.isEmpty()) {
return
}
// consume this intent
intent.setAction(null)
startActivity(MainActivity.getEncodeIntent(this, text, true))
finish()
}
private fun hasCameraPermission(): Boolean {
val permission = android.Manifest.permission.CAMERA
if (ContextCompat.checkSelfPermission(this, permission) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this, arrayOf(permission),
REQUEST_CAMERA
)
return false
}
return true
}
private fun initCameraView() {
cameraView.setUseOrientationListener(true)
cameraView.setTapToFocus()
cameraView.setOnCameraListener(object : CameraView.OnCameraListener {
override fun onConfigureParameters(
parameters: Camera.Parameters
) {
if (parameters.isZoomSupported()) {
val max = parameters.getMaxZoom()
if (zoomBar.max != max) {
zoomBar.max = max
zoomBar.progress = max / 10
saveZoom()
}
parameters.setZoom(zoomBar.progress)
} else {
zoomBar.visibility = View.GONE
}
val sceneModes = parameters.supportedSceneModes
sceneModes?.let {
for (mode in sceneModes) {
if (mode.equals(Camera.Parameters.SCENE_MODE_BARCODE)) {
parameters.sceneMode = mode
break
}
}
}
CameraView.setAutoFocus(parameters)
}
override fun onCameraError() {
Toast.makeText(
this@CameraActivity,
R.string.camera_error,
Toast.LENGTH_SHORT
).show()
finish()
}
override fun onCameraReady(camera: Camera) {
frameWidth = cameraView.frameWidth
frameHeight = cameraView.frameHeight
frameOrientation = cameraView.frameOrientation
camera.setPreviewCallback { data, _ -> frameData = data }
}
override fun onPreviewStarted(camera: Camera) {
startDecoding()
}
override fun onCameraStopping(camera: Camera) {
cancelDecoding()
camera.setPreviewCallback(null)
}
})
}
private fun initZoomBar() {
zoomBar.setOnSeekBarChangeListener(object :
SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
seekBar: SeekBar,
progress: Int,
fromUser: Boolean
) {
setZoom(progress)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
}
private fun setZoom(zoom: Int) {
val camera: Camera? = cameraView.getCamera()
camera?.let {
try {
val params = camera.getParameters()
params.setZoom(zoom)
camera.setParameters(params)
} catch (e: RuntimeException) {
// ignore; there's nothing we can do
}
}
}
private fun saveZoom() {
val editor = preferences.edit()
editor.putInt(ZOOM_MAX, zoomBar.max)
editor.putInt(ZOOM_LEVEL, zoomBar.progress)
editor.apply()
}
private fun restoreZoom() {
zoomBar.max = preferences.getInt(ZOOM_MAX, zoomBar.max)
zoomBar.progress = preferences.getInt(ZOOM_LEVEL, zoomBar.progress)
}
private fun initFlashFab(fab: View) {
if (!packageManager.hasSystemFeature(
PackageManager.FEATURE_CAMERA_FLASH
)) {
fab.visibility = View.GONE
} else {
fab.setOnClickListener { _ ->
toggleTorchMode()
}
}
}
private fun toggleTorchMode() {
val camera = cameraView.getCamera()
val parameters = camera?.getParameters()
parameters?.setFlashMode(
if (flash) {
Camera.Parameters.FLASH_MODE_OFF
} else {
Camera.Parameters.FLASH_MODE_TORCH
}
)
flash = flash xor true
parameters?.let { camera.setParameters(parameters) }
}
private fun startDecoding() {
frameData = null
decoding = true
decodingThread = Thread(decodingRunnable)
decodingThread?.start()
}
private fun cancelDecoding() {
decoding = false
if (decodingThread != null) {
var retry = 100
while (retry-- > 0) {
try {
decodingThread?.join()
break
} catch (e: InterruptedException) {
decodingThread?.interrupt()
}
}
decodingThread = null
}
}
private fun decodeFrame(): Result? {
var fd = frameData
fd ?: return null
if (preprocessor == null) {
preprocessor = Preprocessor(
this,
frameWidth,
frameHeight,
frameOrientation
)
}
var pp = preprocessor
pp ?: return null
pp.process(fd)
invert = invert xor true
return zxing.decode(
fd,
pp.outWidth,
pp.outHeight,
invert
)
}
private fun found(result: Result) {
cancelDecoding()
vibrator.vibrate(100)
if (returnResult) {
val resultIntent = Intent()
resultIntent.putExtra("SCAN_RESULT", result.text)
setResult(RESULT_OK, resultIntent)
finish()
return
}
startActivity(
MainActivity.getDecodeIntent(
this,
result.text,
result.barcodeFormat
)
)
}
companion object {
private const val REQUEST_CAMERA = 1
private const val ZOOM_MAX = "zoom_max"
private const val ZOOM_LEVEL = "zoom_level"
}
}
@@ -1,46 +1,21 @@
package de.markusfisch.android.binaryeye.activity
import de.markusfisch.android.cameraview.widget.CameraView
import com.google.zxing.BarcodeFormat
import de.markusfisch.android.binaryeye.app.addFragment
import de.markusfisch.android.binaryeye.app.initSystemBars
import de.markusfisch.android.binaryeye.app.setFragment
import de.markusfisch.android.binaryeye.fragment.CameraFragment
import de.markusfisch.android.binaryeye.fragment.DecodeFragment
import de.markusfisch.android.binaryeye.fragment.EncodeFragment
import de.markusfisch.android.binaryeye.view.SystemBarMetrics
import de.markusfisch.android.binaryeye.widget.LockOnView
import de.markusfisch.android.binaryeye.R
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.View
import android.view.Window
import android.widget.Toast
class MainActivity : AppCompatActivity() {
lateinit var cameraView: CameraView
lateinit var lockOnView: LockOnView
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray) {
when (requestCode) {
REQUEST_CAMERA -> if (grantResults.size > 0 &&
grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this,
R.string.no_camera_no_fun,
Toast.LENGTH_SHORT).show()
finish()
}
}
}
override fun onSupportNavigateUp(): Boolean {
val fm = supportFragmentManager
if (fm != null && fm.backStackEntryCount > 0) {
@@ -56,90 +31,60 @@ class MainActivity : AppCompatActivity() {
setContentView(R.layout.activity_main)
initSystemBars(this)
cameraView = findViewById(R.id.camera_view) as CameraView
lockOnView = findViewById(R.id.lock_on) as LockOnView
setSupportActionBar(findViewById(R.id.toolbar) as Toolbar)
setUpListener()
checkPermissions()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
if (state == null) {
setFragment(supportFragmentManager, CameraFragment())
handleSendText(intent)
var fragment: Fragment
if (intent?.hasExtra(ENCODE) == true) {
fragment = EncodeFragment.newInstance(
intent.getStringExtra(ENCODE)
)
} else if (intent?.hasExtra(DECODE) == true) {
fragment = DecodeFragment.newInstance(
intent.getStringExtra(DECODE),
intent.getSerializableExtra(
DECODE_FORMAT
) as BarcodeFormat
)
} else {
fragment = DecodeFragment()
}
setFragment(supportFragmentManager, fragment)
}
}
override protected fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
handleSendText(intent)
}
private fun checkPermissions() {
val permission = android.Manifest.permission.CAMERA
if (ContextCompat.checkSelfPermission(this, permission) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(permission),
REQUEST_CAMERA)
}
}
private fun setUpListener() {
supportFragmentManager.addOnBackStackChangedListener { canBack() }
canBack()
}
private fun canBack() {
supportActionBar?.setDisplayHomeAsUpEnabled(
supportFragmentManager.backStackEntryCount > 0)
}
private fun handleSendText(intent: Intent) {
val type = intent.getType()
var text = intent.getStringExtra(Intent.EXTRA_TEXT)
if (!Intent.ACTION_SEND.equals(intent.getAction()) ||
!"text/plain".equals(type) ||
text.isEmpty()) {
return
}
// consume this intent
intent.setAction(null)
addFragment(supportFragmentManager,
EncodeFragment.newInstance(text))
}
companion object {
private val REQUEST_CAMERA = 1
private const val ENCODE = "encode"
private const val DECODE = "decode"
private const val DECODE_FORMAT = "decode_format"
private fun initSystemBars(activity: AppCompatActivity?) {
val view = activity?.findViewById(R.id.main_layout)
if (view != null && setSystemBarColor(activity.window,
ContextCompat.getColor(activity,
R.color.primary_dark_translucent))) {
view.setPadding(
0,
SystemBarMetrics.getStatusBarHeight(
activity.resources),
0,
0)
fun getEncodeIntent(
context: Context,
text: String? = "",
isExternal: Boolean = false
): Intent {
val intent = Intent(context, MainActivity::class.java)
intent.putExtra(ENCODE, text)
if (isExternal) {
intent.addFlags(
android.content.Intent.FLAG_ACTIVITY_NO_HISTORY or
android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK or
android.content.Intent.FLAG_ACTIVITY_NEW_TASK
)
}
return intent
}
private fun setSystemBarColor(window: Window, color: Int): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return false
}
window.statusBarColor = color
window.navigationBarColor = color
window.decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
return true
fun getDecodeIntent(
context: Context,
text: String,
format: BarcodeFormat
): Intent {
val intent = Intent(context, MainActivity::class.java)
intent.putExtra(DECODE, text)
intent.putExtra(DECODE_FORMAT, format)
return intent
}
}
}
@@ -12,7 +12,7 @@ class SplashActivity : AppCompatActivity() {
// because that would happen after the app is fully
// initialized what is too late
startActivity(Intent(applicationContext, MainActivity::class.java))
startActivity(Intent(applicationContext, CameraActivity::class.java))
finish()
}
}
@@ -15,7 +15,8 @@ fun addFragment(fm: FragmentManager?, fragment: Fragment) {
}
private fun getTransaction(
fm: FragmentManager,
fragment: Fragment): FragmentTransaction {
fm: FragmentManager,
fragment: Fragment
): FragmentTransaction {
return fm.beginTransaction().replace(R.id.content_frame, fragment)
}
@@ -0,0 +1,98 @@
package de.markusfisch.android.binaryeye.app
import de.markusfisch.android.binaryeye.R
import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Point
import android.os.Build
import android.support.v4.content.ContextCompat
import android.support.v7.app.AppCompatActivity
import android.util.TypedValue
import android.view.View
import android.view.Window
fun initSystemBars(activity: AppCompatActivity?) {
val view = activity?.findViewById(R.id.main_layout)
if (view != null && setSystemBarColor(
activity.window,
ContextCompat.getColor(
activity,
R.color.primary_dark_translucent
)
)) {
view.setPadding(0, getStatusBarHeight(activity.resources), 0, 0)
}
}
fun setSystemBarColor(window: Window, color: Int): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return false
}
window.statusBarColor = color
window.navigationBarColor = color
window.decorView.systemUiVisibility =
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
return true
}
fun getStatusAndToolBarHeight(context: Context): Int {
return getStatusBarHeight(context.resources) + getToolBarHeight(context)
}
fun getStatusBarHeight(res: Resources): Int {
return getIdentifierDimen(res, "status_bar_height")
}
fun getToolBarHeight(context: Context): Int {
val tv = TypedValue()
return if (context.theme.resolveAttribute(
android.R.attr.actionBarSize,
tv,
true
))
TypedValue.complexToDimensionPixelSize(
tv.data,
context.resources.displayMetrics
)
else
0
}
fun getNavigationBarSize(res: Resources): Point {
val size = Point(0, 0)
if (!getIdentifierBoolean(res, "config_showNavigationBar")) {
return size
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
val conf = res.getConfiguration()
if (conf.orientation == Configuration.ORIENTATION_LANDSCAPE &&
// according to https://developer.android.com/training/multiscreen/screensizes.html#TaskUseSWQuali
// only a screen < 600 dp is considered to be a phone
// and can move its navigation bar to the side
conf.smallestScreenWidthDp < 600) {
size.x = getIdentifierDimen(
res,
"navigation_bar_height_landscape"
)
return size
}
}
size.y = getIdentifierDimen(res, "navigation_bar_height")
return size
}
private fun getIdentifierBoolean(res: Resources, name: String): Boolean {
val id = res.getIdentifier(name, "bool", "android")
return id > 0 && res.getBoolean(id)
}
private fun getIdentifierDimen(res: Resources, name: String): Int {
val id = res.getIdentifier(name, "dimen", "android")
return if (id > 0) res.getDimensionPixelSize(id) else 0
}
@@ -15,15 +15,54 @@ import android.widget.ImageView
import android.widget.Toast
class BarcodeFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
state: Bundle?
): View? {
activity.setTitle(R.string.view_barcode)
val view = inflater.inflate(
R.layout.fragment_barcode,
container,
false
)
val args = getArguments()
args?.let {
val size = args.getInt(SIZE)
val bitmap: Bitmap?
try {
bitmap = Zxing.encodeAsBitmap(
args.getString(CONTENT),
args.getSerializable(FORMAT) as BarcodeFormat,
size,
size
)
} catch (e: Exception) {
Toast.makeText(
activity, e.message,
Toast.LENGTH_SHORT
).show()
fragmentManager.popBackStack()
return null
}
view.findViewById<ImageView>(R.id.barcode).setImageBitmap(bitmap)
}
return view
}
companion object {
private val CONTENT = "content"
private val FORMAT = "format"
private val SIZE = "size"
private const val CONTENT = "content"
private const val FORMAT = "format"
private const val SIZE = "size"
fun newInstance(
content: String,
format: BarcodeFormat,
size: Int): Fragment {
content: String,
format: BarcodeFormat,
size: Int
): Fragment {
val args = Bundle()
args.putString(CONTENT, content)
args.putSerializable(FORMAT, format)
@@ -33,37 +72,4 @@ class BarcodeFragment : Fragment() {
return fragment
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
state: Bundle?): View? {
activity.setTitle(R.string.view_barcode)
val view = inflater.inflate(
R.layout.fragment_barcode,
container,
false)
val args = getArguments()
args?.let {
val size = args.getInt(SIZE)
val bitmap: Bitmap?
try {
bitmap = Zxing.encodeAsBitmap(
args.getString(CONTENT),
args.getSerializable(FORMAT) as BarcodeFormat,
size,
size)
} catch (e: Exception) {
Toast.makeText(activity, e.message,
Toast.LENGTH_SHORT).show()
fragmentManager.popBackStack()
return null
}
view.findViewById<ImageView>(R.id.barcode).setImageBitmap(bitmap)
}
return view
}
}
@@ -1,242 +0,0 @@
package de.markusfisch.android.binaryeye.fragment
import com.google.zxing.Result
import com.google.zxing.ResultPoint
import de.markusfisch.android.cameraview.widget.CameraView
import de.markusfisch.android.binaryeye.activity.MainActivity
import de.markusfisch.android.binaryeye.app.addFragment
import de.markusfisch.android.binaryeye.rs.YuvToGray
import de.markusfisch.android.binaryeye.widget.LockOnView
import de.markusfisch.android.binaryeye.zxing.Zxing
import de.markusfisch.android.binaryeye.R
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Rect
import android.hardware.Camera
import android.net.Uri
import android.os.Bundle
import android.os.Vibrator
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
class CameraFragment : Fragment() {
private val zxing = Zxing()
private val decodingRunnable = Runnable {
while (decoding) {
val result = decodeFrame()
if (result != null) {
cameraView.post { found(result) }
decoding = false
break
}
}
}
private lateinit var vibrator: Vibrator
private lateinit var cameraView: CameraView
private lateinit var lockOnView: LockOnView
private lateinit var yuvToGray: YuvToGray
private var decoding = false
private var decodingThread: Thread? = null
private var frameData: ByteArray? = null
private var frameWidth: Int = 0
private var frameHeight: Int = 0
private var frameOrientation: Int = 0
private var odd = false
private var flash = false
override fun onCreate(state: Bundle?) {
super.onCreate(state)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
state: Bundle?): View? {
activity.setTitle(R.string.scan_code)
vibrator = activity.getSystemService(
Context.VIBRATOR_SERVICE) as Vibrator
yuvToGray = YuvToGray(context)
cameraView = (activity as MainActivity).cameraView
cameraView.setOnCameraListener(object : CameraView.OnCameraListener {
override fun onConfigureParameters(
parameters: Camera.Parameters) {}
override fun onCameraStarted(camera: Camera) {
frameWidth = cameraView.frameWidth
frameHeight = cameraView.frameHeight
frameOrientation = cameraView.frameOrientation
camera.setPreviewCallback { data, _ -> frameData = data }
}
override fun onCameraStopping(camera: Camera) {
camera.setPreviewCallback(null)
}
})
lockOnView = (activity as MainActivity).lockOnView
val view = inflater.inflate(
R.layout.fragment_camera,
container,
false)
view.findViewById<View>(R.id.create).setOnClickListener { _ ->
addFragment(fragmentManager, EncodeFragment())
}
return view
}
override fun onDestroyView() {
super.onDestroyView()
yuvToGray.destroy()
}
override fun onResume() {
super.onResume()
System.gc()
lockOnView.visibility = View.VISIBLE
cameraView.visibility = View.VISIBLE
cameraView.openAsync(CameraView.findCameraId(
Camera.CameraInfo.CAMERA_FACING_BACK))
startDecoding()
}
override fun onPause() {
super.onPause()
cancelDecoding()
cameraView.close()
cameraView.visibility = View.GONE
lockOnView.visibility = View.GONE
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.fragment_camera, menu)
if (!context.packageManager.hasSystemFeature(
PackageManager.FEATURE_CAMERA_FLASH)) {
menu.findItem(R.id.flash).setVisible(false)
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.flash -> {
toggleTorchMode()
true
}
R.id.info -> {
openReadme()
true
}
else -> super.onOptionsItemSelected(item)
}
}
private fun toggleTorchMode() {
val camera = cameraView.getCamera()
val parameters = camera?.getParameters()
parameters?.setFlashMode(if (flash)
Camera.Parameters.FLASH_MODE_OFF
else
Camera.Parameters.FLASH_MODE_TORCH)
flash = flash xor true
parameters?.let { camera.setParameters(parameters) }
}
private fun openReadme() {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(
"https://github.com/markusfisch/BinaryEye/blob/master/README.md")))
}
private fun startDecoding() {
activity ?: return
frameData = null
decoding = true
decodingThread = Thread(decodingRunnable)
decodingThread?.start()
}
private fun cancelDecoding() {
decoding = false
if (decodingThread != null) {
var retry = 100
while (retry-- > 0) {
try {
decodingThread?.join()
break
} catch (e: InterruptedException) {
// try again
}
}
}
}
private fun decodeFrame(): Result? {
frameData ?: return null
return zxing.decodeBitmap(yuvToGray.convert(
frameData!!, frameWidth, frameHeight, frameOrientation))
}
private fun found(result: Result) {
cancelDecoding()
vibrator.vibrate(100)
lockOnView.lock(getRelativeBounds(result.resultPoints), 250)
lockOnView.postDelayed({
addFragment(fragmentManager, DecodeFragment.newInstance(
result.text,
result.getBarcodeFormat()))
}, 500)
}
private fun getRelativeBounds(resultPoints: Array<ResultPoint>): Rect {
val fw: Float
val fh: Float
if (frameOrientation == 90 || frameOrientation == 270) {
fw = frameHeight.toFloat()
fh = frameWidth.toFloat()
} else {
fw = frameWidth.toFloat()
fh = frameHeight.toFloat()
}
val viewRect = cameraView.previewRect
val xf = fw / viewRect.width()
val yf = fh / viewRect.height()
val bounds = getBounds(resultPoints)
bounds.set(
Math.round(bounds.left / xf),
Math.round(bounds.top / yf),
Math.round(bounds.right / xf),
Math.round(bounds.bottom / yf))
bounds.offset(viewRect.left, viewRect.top)
return bounds
}
private fun getBounds(resultPoints: Array<ResultPoint>): Rect {
val bounds = Rect(0xffffff, 0xffffff, 0, 0)
for (resultPoint in resultPoints) {
val x = Math.round(resultPoint.x)
val y = Math.round(resultPoint.y)
bounds.set(
Math.min(bounds.left, x),
Math.min(bounds.top, y),
Math.max(bounds.right, x),
Math.max(bounds.bottom, y))
}
return bounds
}
}
@@ -21,20 +21,6 @@ import android.widget.EditText
import android.widget.Toast
class DecodeFragment : Fragment() {
companion object {
private val CONTENT = "content"
private val FORMAT = "format"
fun newInstance(content: String, format: BarcodeFormat): Fragment {
val args = Bundle()
args.putString(CONTENT, content)
args.putSerializable(FORMAT, format)
val fragment = DecodeFragment()
fragment.arguments = args
return fragment
}
}
private lateinit var contentView: EditText
private lateinit var format: BarcodeFormat
@@ -44,19 +30,20 @@ class DecodeFragment : Fragment() {
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
state: Bundle?): View {
inflater: LayoutInflater,
container: ViewGroup?,
state: Bundle?
): View {
activity.setTitle(R.string.content)
val view = inflater.inflate(
R.layout.fragment_decode,
container,
false)
R.layout.fragment_decode,
container,
false
)
val content = arguments?.getString(CONTENT) ?: ""
format = arguments?.getSerializable(FORMAT) as BarcodeFormat? ?:
BarcodeFormat.QR_CODE
format = arguments?.getSerializable(FORMAT) as BarcodeFormat? ?: BarcodeFormat.QR_CODE
contentView = view.findViewById<EditText>(R.id.content)
contentView.setText(content)
@@ -83,8 +70,10 @@ class DecodeFragment : Fragment() {
true
}
R.id.create -> {
addFragment(fragmentManager,
EncodeFragment.newInstance(getContent(), format))
addFragment(
fragmentManager,
EncodeFragment.newInstance(getContent(), format)
)
true
}
else -> super.onOptionsItemSelected(item)
@@ -99,24 +88,32 @@ class DecodeFragment : Fragment() {
activity ?: return
val cm = activity.getSystemService(
Context.CLIPBOARD_SERVICE) as ClipboardManager
Context.CLIPBOARD_SERVICE
) as ClipboardManager
cm.setText(text)
Toast.makeText(activity,
R.string.put_into_clipboard,
Toast.LENGTH_SHORT).show()
Toast.makeText(
activity,
R.string.put_into_clipboard,
Toast.LENGTH_SHORT
).show()
}
private fun openUrl(url: String) {
if (activity == null || url.isEmpty()) {
return
}
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse(url).normalizeScheme()
)
if (intent.resolveActivity(activity.getPackageManager()) != null) {
startActivity(intent)
} else {
Toast.makeText(activity,
R.string.cannot_resolve_action,
Toast.LENGTH_SHORT).show()
Toast.makeText(
activity,
R.string.cannot_resolve_action,
Toast.LENGTH_SHORT
).show()
}
}
@@ -126,4 +123,18 @@ class DecodeFragment : Fragment() {
intent.setType("text/plain")
startActivity(intent)
}
companion object {
private const val CONTENT = "content"
private const val FORMAT = "format"
fun newInstance(content: String, format: BarcodeFormat): Fragment {
val args = Bundle()
args.putString(CONTENT, content)
args.putSerializable(FORMAT, format)
val fragment = DecodeFragment()
fragment.arguments = args
return fragment
}
}
}
@@ -20,55 +20,43 @@ import android.widget.TextView
import android.widget.Toast
class EncodeFragment : Fragment() {
companion object {
private val CONTENT = "content"
private val FORMAT = "format"
fun newInstance(
content: String,
format: BarcodeFormat = BarcodeFormat.AZTEC): Fragment {
val args = Bundle()
args.putString(CONTENT, content)
args.putSerializable(FORMAT, format)
val fragment = EncodeFragment()
fragment.setArguments(args)
return fragment
}
}
private lateinit var formatView: Spinner
private lateinit var sizeView: TextView
private lateinit var sizeBarView: SeekBar
private val writers = arrayListOf(
BarcodeFormat.AZTEC,
BarcodeFormat.CODABAR,
BarcodeFormat.CODE_39,
BarcodeFormat.CODE_128,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.EAN_8,
BarcodeFormat.EAN_13,
BarcodeFormat.ITF,
BarcodeFormat.PDF_417,
BarcodeFormat.QR_CODE,
BarcodeFormat.UPC_A
BarcodeFormat.AZTEC,
BarcodeFormat.CODABAR,
BarcodeFormat.CODE_39,
BarcodeFormat.CODE_128,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.EAN_8,
BarcodeFormat.EAN_13,
BarcodeFormat.ITF,
BarcodeFormat.PDF_417,
BarcodeFormat.QR_CODE,
BarcodeFormat.UPC_A
)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
state: Bundle?): View {
inflater: LayoutInflater,
container: ViewGroup?,
state: Bundle?
): View {
activity.setTitle(R.string.compose_barcode)
val view = inflater.inflate(
R.layout.fragment_encode,
container,
false)
R.layout.fragment_encode,
container,
false
)
formatView = view.findViewById<Spinner>(R.id.format)
formatView.setAdapter(ArrayAdapter<String>(
formatView.setAdapter(
ArrayAdapter<String>(
activity,
android.R.layout.simple_list_item_1,
writers.map { it -> it.name }))
writers.map { it -> it.name })
)
sizeView = view.findViewById<TextView>(R.id.size_display)
sizeBarView = view.findViewById<SeekBar>(R.id.size_bar)
@@ -79,8 +67,11 @@ class EncodeFragment : Fragment() {
val args = getArguments()
args?.let {
contentView.setText(args.getString(CONTENT))
formatView.setSelection(writers.indexOf(
args.getSerializable(FORMAT) as BarcodeFormat?))
formatView.setSelection(
writers.indexOf(
args.getSerializable(FORMAT) as BarcodeFormat?
)
)
}
view.findViewById<View>(R.id.encode).setOnClickListener { v ->
@@ -88,14 +79,19 @@ class EncodeFragment : Fragment() {
var size = getSize(sizeBarView.getProgress())
val content = contentView.getText().toString()
if (content.isEmpty()) {
Toast.makeText(v.context, R.string.error_no_content,
Toast.LENGTH_SHORT).show()
Toast.makeText(
v.context, R.string.error_no_content,
Toast.LENGTH_SHORT
).show()
} else {
hideSoftKeyboard(contentView)
addFragment(fragmentManager, BarcodeFragment.newInstance(
addFragment(
fragmentManager, BarcodeFragment.newInstance(
content,
format,
size))
size
)
)
}
}
@@ -105,32 +101,51 @@ class EncodeFragment : Fragment() {
private fun initSizeBar() {
updateSize(sizeBarView.getProgress())
sizeBarView.setOnSeekBarChangeListener(
object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(
seekBar: SeekBar,
progressValue: Int,
fromUser: Boolean) {
updateSize(progressValue)
}
fromUser: Boolean
) {
updateSize(progressValue)
}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
}
private fun updateSize(power: Int) {
val size = getSize(power)
sizeView.setText("${size}x${size}")
sizeView.setText("${size}x$size")
}
private fun getSize(power: Int) = 128 * (power + 1)
private fun hideSoftKeyboard(view: View) {
val im = activity?.getSystemService(
Context.INPUT_METHOD_SERVICE) as InputMethodManager?
Context.INPUT_METHOD_SERVICE
) as InputMethodManager?
im?.let {
im.hideSoftInputFromWindow(view.getWindowToken(), 0)
}
}
companion object {
private const val CONTENT = "content"
private const val FORMAT = "format"
fun newInstance(
content: String,
format: BarcodeFormat = BarcodeFormat.AZTEC
): Fragment {
val args = Bundle()
args.putString(CONTENT, content)
args.putSerializable(FORMAT, format)
val fragment = EncodeFragment()
fragment.setArguments(args)
return fragment
}
}
}
@@ -0,0 +1,133 @@
package de.markusfisch.android.binaryeye.rs
import de.markusfisch.android.binaryeye.renderscript.ScriptC_rotator
import android.content.Context
import android.support.v8.renderscript.Allocation
import android.support.v8.renderscript.Element
import android.support.v8.renderscript.RenderScript
import android.support.v8.renderscript.ScriptIntrinsicResize
import android.support.v8.renderscript.Type
class Preprocessor(
context: Context,
width: Int,
height: Int,
val orientation: Int
) {
var outWidth = 0
var outHeight = 0
private val rs = RenderScript.create(context)
private val resizeScript = ScriptIntrinsicResize.create(rs)
private val rotatorScript = ScriptC_rotator(rs)
private var yuvType: Type? = null
private var yuvAlloc: Allocation? = null
private var resizedType: Type? = null
private var resizedAlloc: Allocation? = null
private var rotatedType: Type? = null
private var rotatedAlloc: Allocation? = null
init {
yuvType = Type.createXY(
rs,
Element.U8(rs),
width,
height // use only grayscale part
)
yuvAlloc = Allocation.createTyped(
rs,
yuvType,
Allocation.USAGE_SCRIPT
)
var f = .75f
var w = Math.round(width * f)
var h = Math.round(height * f)
resizedType = Type.createXY(
rs,
Element.U8(rs),
w,
h
)
resizedAlloc = Allocation.createTyped(
rs,
resizedType,
Allocation.USAGE_SCRIPT
)
if (orientation == 90 || orientation == 270) {
val tmp = w
w = h
h = tmp
}
outWidth = w
outHeight = h
if (orientation != 0) {
rotatedType = Type.createXY(
rs,
Element.U8(rs),
w,
h
)
rotatedAlloc = Allocation.createTyped(
rs,
rotatedType,
Allocation.USAGE_SCRIPT
)
}
}
fun destroy() {
yuvType?.destroy()
yuvType = null
yuvAlloc?.destroy()
yuvAlloc = null
resizedType?.destroy()
resizedType = null
resizedAlloc?.destroy()
resizedAlloc = null
rotatedType?.destroy()
rotatedType = null
rotatedAlloc?.destroy()
rotatedAlloc = null
resizeScript.destroy()
rotatorScript.destroy()
rs.destroy()
}
fun process(frame: ByteArray) {
yuvAlloc?.copyFrom(frame)
resizeScript.setInput(yuvAlloc)
resizeScript.forEach_bicubic(resizedAlloc)
val t = resizedType
if (t == null || orientation == 0) {
resizedAlloc?.copyTo(frame)
} else {
rotatorScript._inImage = resizedAlloc
rotatorScript._inWidth = t.x
rotatorScript._inHeight = t.y
when (orientation) {
90 -> rotatorScript.forEach_rotate90(
rotatedAlloc,
rotatedAlloc
)
180 -> rotatorScript.forEach_rotate180(
rotatedAlloc,
rotatedAlloc
)
270 -> rotatorScript.forEach_rotate270(
rotatedAlloc,
rotatedAlloc
)
}
rotatedAlloc?.copyTo(frame)
}
}
}
@@ -1,96 +0,0 @@
package de.markusfisch.android.binaryeye.rs
import de.markusfisch.android.binaryeye.renderscript.ScriptC_rotator
import de.markusfisch.android.binaryeye.renderscript.ScriptC_yuv2gray
import android.content.Context
import android.graphics.Bitmap
import android.support.v8.renderscript.Allocation
import android.support.v8.renderscript.Element
import android.support.v8.renderscript.RenderScript
import android.support.v8.renderscript.Type
class YuvToGray(context: Context) {
private val rs: RenderScript = RenderScript.create(context)
private val rotatorScript: ScriptC_rotator = ScriptC_rotator(rs)
private val yuv2grayScript: ScriptC_yuv2gray = ScriptC_yuv2gray(rs)
private var yuvType: Type? = null
private var rgbaType: Type? = null
private var yuvAlloc: Allocation? = null
private var rgbaAlloc: Allocation? = null
private var destAlloc: Allocation? = null
private var dest: Bitmap? = null
fun destroy() {
yuvType?.destroy()
yuvType = null
rgbaType?.destroy()
rgbaType = null
yuvAlloc?.destroy()
yuvAlloc = null
rgbaAlloc?.destroy()
rgbaAlloc = null
destAlloc?.destroy()
destAlloc = null
dest?.recycle()
dest = null
rotatorScript.destroy()
yuv2grayScript.destroy()
rs.destroy()
}
fun convert(
data: ByteArray,
width: Int,
height: Int,
orientation: Int): Bitmap {
if (dest == null) {
yuvType = Type.createXY(rs, Element.U8(rs), width, height * 3 / 2)
yuvAlloc = Allocation.createTyped(rs, yuvType,
Allocation.USAGE_SCRIPT)
rgbaType = Type.createXY(rs, Element.RGBA_8888(rs), width, height)
rgbaAlloc = Allocation.createTyped(rs, rgbaType,
Allocation.USAGE_SCRIPT)
var w = width
var h = height
when (orientation) {
90, 270 -> {
val tmp = w
w = h
h = tmp
}
}
dest = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
destAlloc = Allocation.createFromBitmap(
rs,
dest,
Allocation.MipmapControl.MIPMAP_NONE,
Allocation.USAGE_SCRIPT)
}
yuvAlloc?.copyFrom(data)
yuv2grayScript._inYUV = yuvAlloc
// width/height are uint_32 but Kotlin wants toLong()
yuv2grayScript._inWidth = width.toLong()
yuv2grayScript._inHeight = height.toLong()
yuv2grayScript.forEach_yuv2gray(rgbaAlloc)
rotatorScript._inImage = rgbaAlloc
rotatorScript._inWidth = width
rotatorScript._inHeight = height
when (orientation) {
0 -> destAlloc?.copyFrom(rgbaAlloc)
90 -> rotatorScript.forEach_rotate90(destAlloc, destAlloc)
180 -> rotatorScript.forEach_rotate180(destAlloc, destAlloc)
270 -> rotatorScript.forEach_rotate270(destAlloc, destAlloc)
}
destAlloc?.copyTo(dest)
return dest!!
}
}
@@ -1,62 +0,0 @@
package de.markusfisch.android.binaryeye.view
import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Point
import android.os.Build
import android.util.TypedValue
object SystemBarMetrics {
fun getStatusAndToolBarHeight(context: Context): Int {
return getStatusBarHeight(context.resources) + getToolBarHeight(context)
}
fun getStatusBarHeight(res: Resources): Int {
return getIdentifierDimen(res, "status_bar_height")
}
fun getToolBarHeight(context: Context): Int {
val tv = TypedValue()
return if (context.theme.resolveAttribute(
android.R.attr.actionBarSize,
tv,
true))
TypedValue.complexToDimensionPixelSize(
tv.data,
context.resources.displayMetrics)
else
0
}
fun getNavigationBarSize(res:Resources):Point {
val size = Point(0, 0)
if (!getIdentifierBoolean(res, "config_showNavigationBar")) {
return size
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
val conf = res.getConfiguration()
if (conf.orientation == Configuration.ORIENTATION_LANDSCAPE &&
// according to https://developer.android.com/training/multiscreen/screensizes.html#TaskUseSWQuali
// only a screen < 600 dp is considered to be a phone
// and can move its navigation bar to the side
conf.smallestScreenWidthDp < 600) {
size.x = getIdentifierDimen(res,
"navigation_bar_height_landscape")
return size
}
}
size.y = getIdentifierDimen(res, "navigation_bar_height")
return size
}
private fun getIdentifierBoolean(res:Resources, name:String):Boolean {
val id = res.getIdentifier(name, "bool", "android")
return id > 0 && res.getBoolean(id)
}
private fun getIdentifierDimen(res: Resources, name: String): Int {
val id = res.getIdentifier(name, "dimen", "android")
return if (id > 0) res.getDimensionPixelSize(id) else 0
}
}
@@ -1,262 +0,0 @@
package de.markusfisch.android.binaryeye.widget
import de.markusfisch.android.binaryeye.view.SystemBarMetrics
import de.markusfisch.android.binaryeye.R
import android.content.Context
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.Rect
import android.support.v4.content.ContextCompat
import android.util.AttributeSet
import android.view.SurfaceView
import android.view.SurfaceHolder
class LockOnView : SurfaceView {
private val markerPaint = Paint(Paint.ANTI_ALIAS_FLAG)
private val restRect = Rect()
private val startRect = Rect()
private val endRect = Rect()
private val currentRect = Rect()
private val animationRunnable = Runnable {
setAnimationStart()
while (running) {
val now = System.currentTimeMillis() - animationStart
if (now > animationDuration) {
break
}
animateCurrentRect(now)
lockCanvasAndDraw()
}
lockCanvasAndDraw()
running = false
}
@Volatile private var running = false
private lateinit var markerTopLeft: Bitmap
private lateinit var markerTopRight: Bitmap
private lateinit var markerBottomLeft: Bitmap
private lateinit var markerBottomRight: Bitmap
private var markerSize: Int = 0
private var minSize: Int = 0
private var thread: Thread? = null
private var animationStart: Long = 0
private var animationDuration: Long = 0
init {
loadMarkers(context.resources)
initSurfaceHolder(context)
setZOrderOnTop(true)
}
constructor(context: Context, attrs: AttributeSet) :
super(context, attrs) {
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) :
super(context, attrs, defStyleAttr) {
}
fun lock(rect: Rect, ms: Int) {
startRect.set(currentRect)
if (running) {
tintMarkers()
fitRect(rect)
endRect.set(rect)
setAnimationStart()
} else {
startAnimation(rect, ms)
}
}
fun reset() {
untintMarkers()
startRect.set(restRect)
currentRect.set(startRect)
lockCanvasAndDraw()
}
private fun loadMarkers(res: Resources) {
val dp = res.displayMetrics.density
markerTopLeft = BitmapFactory.decodeResource(res, R.drawable.marker)
val width = markerTopLeft.width
val height = markerTopLeft.height
markerSize = Math.max(width, height)
minSize = markerSize * 2 + Math.round(dp * 8f)
val matrix = Matrix()
matrix.setScale(-1f, 1f)
markerTopRight = Bitmap.createBitmap(markerTopLeft,
0, 0, width, height, matrix, false)
matrix.setScale(1f, -1f)
markerBottomLeft = Bitmap.createBitmap(markerTopLeft,
0, 0, width, height, matrix, false)
matrix.setScale(-1f, -1f)
markerBottomRight = Bitmap.createBitmap(markerTopLeft,
0, 0, width, height, matrix, false)
}
private fun initSurfaceHolder(context: Context) {
holder.setFormat(PixelFormat.TRANSPARENT)
holder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceChanged(
holder: SurfaceHolder,
format: Int,
width: Int,
height: Int) {
initRestRect(context, width, height)
reset()
}
override fun surfaceCreated(holder: SurfaceHolder) {}
override fun surfaceDestroyed(holder: SurfaceHolder) {
cancelAnimation()
}
})
}
private fun cancelAnimation() {
running = false
if (thread != null) {
var retry = 100
while (retry-- > 0) {
try {
thread?.join()
retry = 0
} catch (e: InterruptedException) {
// try again
}
}
}
}
private fun startAnimation(rect: Rect, ms: Int) {
if (running) {
return
}
if (rect == restRect) {
untintMarkers()
} else {
tintMarkers()
}
running = true
fitRect(rect)
endRect.set(rect)
animationDuration = ms.toLong()
thread = Thread(animationRunnable)
thread?.start()
}
private fun initRestRect(context: Context, width: Int, height: Int) {
val res = context.resources
val dp = res.displayMetrics.density
val padding = Math.round(16f * dp)
var left = padding
var top = padding + if (width > height)
SystemBarMetrics.getStatusAndToolBarHeight(context)
else
0
val navBar = SystemBarMetrics.getNavigationBarSize(res)
val paddingLeftRight = padding * 2 + navBar.x
val paddingTopBottom = top + padding + navBar.y
val innerWidth = width - paddingLeftRight
val innerHeight = height - paddingTopBottom
val size = Math.min(innerWidth, innerHeight)
left += (innerWidth - size) / 2
top += (innerHeight - size) / 2
restRect.set(left, top, left + size, top + size)
}
private fun fitRect(rect: Rect) {
val width = rect.width()
val height = rect.height()
if (width < minSize) {
val pad = (minSize - width) / 2
rect.left -= pad
rect.right += pad
}
if (height < minSize) {
val pad = (minSize - height) / 2
rect.top -= pad
rect.bottom += pad
}
}
private fun setAnimationStart() {
animationStart = System.currentTimeMillis()
}
private fun animateCurrentRect(now: Long) {
currentRect.set(
linear(now,
startRect.left,
endRect.left - startRect.left,
animationDuration),
linear(now,
startRect.top,
endRect.top - startRect.top,
animationDuration),
linear(now,
startRect.right,
endRect.right - startRect.right,
animationDuration),
linear(now,
startRect.bottom,
endRect.bottom - startRect.bottom,
animationDuration))
}
private fun linear(
time: Long,
begin: Int,
change: Int,
duration: Long): Int = Math.round(
change.toFloat() * time / duration + begin)
private fun lockCanvasAndDraw() {
val canvas = holder.lockCanvas()
if (canvas != null) {
drawMarkers(canvas, currentRect)
holder.unlockCanvasAndPost(canvas)
}
}
private fun untintMarkers() {
markerPaint.colorFilter = null
}
private fun tintMarkers() {
markerPaint.colorFilter = PorterDuffColorFilter(
ContextCompat.getColor(context, R.color.accent),
PorterDuff.Mode.SRC_IN)
}
private fun drawMarkers(canvas: Canvas, rect: Rect) {
canvas.drawColor(0, PorterDuff.Mode.CLEAR)
canvas.drawBitmap(markerTopLeft,
rect.left.toFloat(),
rect.top.toFloat(),
markerPaint)
canvas.drawBitmap(markerTopRight,
(rect.right - markerSize).toFloat(),
rect.top.toFloat(),
markerPaint)
canvas.drawBitmap(markerBottomLeft,
rect.left.toFloat(),
(rect.bottom - markerSize).toFloat(),
markerPaint)
canvas.drawBitmap(markerBottomRight,
(rect.right - markerSize).toFloat(),
(rect.bottom - markerSize).toFloat(),
markerPaint)
}
}
@@ -6,9 +6,9 @@ import com.google.zxing.DecodeHintType
import com.google.zxing.LuminanceSource
import com.google.zxing.MultiFormatReader
import com.google.zxing.MultiFormatWriter
import com.google.zxing.PlanarYUVLuminanceSource
import com.google.zxing.ReaderException
import com.google.zxing.Result
import com.google.zxing.RGBLuminanceSource
import com.google.zxing.common.HybridBinarizer
import android.graphics.Bitmap
@@ -18,60 +18,35 @@ import java.util.EnumMap
import java.util.EnumSet
class Zxing {
companion object {
private val black = 0xff000000.toInt()
private val white = 0xffffffff.toInt()
fun encodeAsBitmap(
text: String,
format: BarcodeFormat,
width: Int,
height: Int): Bitmap? {
val result = MultiFormatWriter().encode(text, format,
width, height, null)
val w = result.getWidth()
val h = result.getHeight()
val pixels = IntArray(w * h)
var offset = 0
for (y in 0..h - 1) {
for (x in 0..w - 1) {
pixels[offset + x] = if (result.get(x, y))
black
else
white
}
offset += w
}
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
bitmap.setPixels(pixels, 0, width, 0, 0, w, h)
return bitmap
}
}
private val multiFormatReader: MultiFormatReader = MultiFormatReader()
init {
val decodeFormats = EnumSet.noneOf<BarcodeFormat>(
BarcodeFormat::class.java)
decodeFormats.addAll(EnumSet.copyOf(Arrays.asList(
BarcodeFormat.AZTEC,
BarcodeFormat.CODABAR,
BarcodeFormat.CODE_39,
BarcodeFormat.CODE_93,
BarcodeFormat.CODE_128,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.EAN_8,
BarcodeFormat.EAN_13,
BarcodeFormat.ITF,
BarcodeFormat.MAXICODE,
BarcodeFormat.PDF_417,
BarcodeFormat.QR_CODE,
BarcodeFormat.RSS_14,
BarcodeFormat.RSS_EXPANDED,
BarcodeFormat.UPC_A,
BarcodeFormat.UPC_E,
BarcodeFormat.UPC_EAN_EXTENSION
)))
BarcodeFormat::class.java
)
decodeFormats.addAll(
EnumSet.copyOf(
Arrays.asList(
BarcodeFormat.AZTEC,
BarcodeFormat.CODABAR,
BarcodeFormat.CODE_39,
BarcodeFormat.CODE_93,
BarcodeFormat.CODE_128,
BarcodeFormat.DATA_MATRIX,
BarcodeFormat.EAN_8,
BarcodeFormat.EAN_13,
BarcodeFormat.ITF,
BarcodeFormat.MAXICODE,
BarcodeFormat.PDF_417,
BarcodeFormat.QR_CODE,
BarcodeFormat.RSS_14,
BarcodeFormat.RSS_EXPANDED,
BarcodeFormat.UPC_A,
BarcodeFormat.UPC_E,
BarcodeFormat.UPC_EAN_EXTENSION
)
)
)
val hints = EnumMap<DecodeHintType, Any>(DecodeHintType::class.java)
hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats)
@@ -79,12 +54,29 @@ class Zxing {
multiFormatReader.setHints(hints)
}
fun decodeBitmap(bitmap: Bitmap): Result? {
val width = bitmap.width
val height = bitmap.height
val data = IntArray(width * height)
bitmap.getPixels(data, 0, width, 0, 0, width, height)
return decodeLuminanceSource(RGBLuminanceSource(width, height, data))
fun decode(
yuvData: ByteArray,
width: Int,
height: Int,
invert: Boolean = false
): Result? {
val source = PlanarYUVLuminanceSource(
yuvData,
width,
height,
0,
0,
width,
height,
false
)
return decodeLuminanceSource(
if (invert) {
source.invert()
} else {
source
}
)
}
private fun decodeLuminanceSource(source: LuminanceSource): Result? {
@@ -97,4 +89,37 @@ class Zxing {
multiFormatReader.reset()
}
}
companion object {
private const val BLACK = 0xff000000.toInt()
private const val WHITE = 0xffffffff.toInt()
fun encodeAsBitmap(
text: String,
format: BarcodeFormat,
width: Int,
height: Int
): Bitmap? {
val result = MultiFormatWriter().encode(
text, format,
width, height, null
)
val w = result.getWidth()
val h = result.getHeight()
val pixels = IntArray(w * h)
var offset = 0
for (y in 0..h - 1) {
for (x in 0..w - 1) {
pixels[offset + x] = if (result.get(x, y))
BLACK
else
WHITE
}
offset += w
}
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
bitmap.setPixels(pixels, 0, width, 0, 0, w, h)
return bitmap
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 32 KiB

@@ -0,0 +1,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line"
android:gravity="center">
<stroke
android:width="1dp"
android:color="@color/accent"/>
</shape>
@@ -3,6 +3,6 @@
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/ic_launcher"/>
android:src="@drawable/logo"/>
</item>
</layer-list>
@@ -0,0 +1,8 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/background_color"/>
<item>
<bitmap
android:gravity="top|right"
android:src="@drawable/wallpaper"/>
</item>
</layer-list>
@@ -0,0 +1,3 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#b6d46f"/>
</shape>
@@ -0,0 +1,70 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M32.002,-24.974h3.127v7.656h-3.127z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:fillColor="#FF000000"
android:pathData="M52,-884.362h29v71h-29z"/>
<path
android:pathData="m54.826,27.893c-6.851,0 -13.701,2.581 -18.924,7.745 -10.445,10.328 -10.413,27.062 0,37.423l36.218,36.036 37.879,0.902 -0.07,-38.363 -36.18,-35.998c-5.207,-5.18 -12.073,-7.745 -18.924,-7.745z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="8.60725021"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillAlpha="0.1254902"
android:strokeLineCap="butt"/>
<path
android:pathData="M28.001,54.118a26.525,26.227 0,1 0,53.049 0a26.525,26.227 0,1 0,-53.049 0z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillAlpha="1"
android:strokeLineCap="butt"/>
<path
android:pathData="M39.26,54.988a14.509,14.346 0,1 0,29.019 0a14.509,14.346 0,1 0,-29.019 0z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="4"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillAlpha="1"
android:strokeLineCap="butt"/>
<path
android:pathData="M54.034,44.513a9.535,9.428 0,1 0,19.07 0a9.535,9.428 0,1 0,-19.07 0z"
android:strokeAlpha="1"
android:strokeLineJoin="miter"
android:strokeWidth="10"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillAlpha="1"
android:strokeLineCap="butt"/>
</vector>
@@ -0,0 +1,39 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<de.markusfisch.android.cameraview.widget.CameraView
android:id="@+id/camera_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<RelativeLayout
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true"
android:background="@drawable/background_scanner">
<include layout="@layout/toolbar"/>
<SeekBar
android:id="@+id/zoom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginBottom="8dp"
android:layout_marginRight="80dp"
android:layout_marginEnd="80dp"
android:padding="16dp"/>
<android.support.design.widget.FloatingActionButton
tools:ignore="UnusedAttribute"
android:id="@+id/flash"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_margin="20dp"
android:src="@drawable/ic_action_flash"
app:elevation="4dp"/>
</RelativeLayout>
</merge>
-10
View File
@@ -1,14 +1,4 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<de.markusfisch.android.cameraview.widget.CameraView
android:id="@+id/camera_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
<de.markusfisch.android.binaryeye.widget.LockOnView
android:id="@+id/lock_on"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"/>
<LinearLayout
android:id="@+id/main_layout"
android:layout_width="match_parent"
@@ -1,18 +0,0 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.FloatingActionButton
tools:ignore="UnusedAttribute"
android:id="@+id/create"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_margin="20dp"
android:src="@drawable/ic_action_create"
app:elevation="4dp"/>
</RelativeLayout>
+2 -1
View File
@@ -12,7 +12,8 @@
android:gravity="start|top"
android:imeOptions="flagNoExtractUi"
android:inputType="textMultiLine"
android:typeface="monospace"/>
android:typeface="monospace"
android:hint="@string/content"/>
<android.support.design.widget.FloatingActionButton
tools:ignore="UnusedAttribute"
android:id="@+id/share"
@@ -7,8 +7,8 @@
android:icon="@drawable/ic_action_info"
material:showAsAction="ifRoom"/>
<item
android:id="@+id/flash"
android:title="@string/flash"
android:icon="@drawable/ic_action_flash"
android:id="@+id/create"
android:title="@string/compose_barcode"
android:icon="@drawable/ic_action_create"
material:showAsAction="ifRoom"/>
</menu>
@@ -0,0 +1,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

+18
View File
@@ -0,0 +1,18 @@
<resources>
<string name="no_camera_no_fun">Diese App kann ohne Kamerazugriff nicht funktionieren. Tschüss!</string>
<string name="camera_error">Auf die Kamera kann nicht zugegriffen werden, bitte versuche es nochmal</string>
<string name="scan_code">Code scannen</string>
<string name="compose_barcode">Barcode erstellen</string>
<string name="content">Inhalt</string>
<string name="copy_to_clipboard">In die Zwischenablage kopieren</string>
<string name="put_into_clipboard">In die Zwischenablage legen</string>
<string name="open_url">URL öffnen</string>
<string name="cannot_resolve_action">Keine App kann das öffnen</string>
<string name="format">Format</string>
<string name="size">Größe in Pixeln</string>
<string name="input_content_here">Gib den Inhalt hier ein</string>
<string name="encode">KODIEREN</string>
<string name="error_no_content">Fehlender Inhalt</string>
<string name="view_barcode">Barcode ansehen</string>
<string name="info">Info</string>
</resources>
+3 -2
View File
@@ -3,7 +3,8 @@
<color name="primary_translucent">#8222</color>
<color name="primary_dark">#111</color>
<color name="primary_dark_translucent">#8111</color>
<color name="accent">#26e1cf</color>
<color name="accent_dark">#16d1bf</color>
<color name="accent">#b6d46f</color>
<color name="accent_dark">#a6c45f</color>
<color name="background_color">#111</color>
<color name="button_text">#fff</color>
</resources>
+2 -2
View File
@@ -1,7 +1,7 @@
<resources>
<string name="no_camera_no_fun">This app does not make any sense without camera access. Good bye.</string>
<string name="scan_code">Scan a code</string>
<string name="flash">Toggle flash</string>
<string name="camera_error">Can\'t access camera, please try again</string>
<string name="scan_code">Scan code</string>
<string name="compose_barcode">Compose barcode</string>
<string name="content">Content</string>
<string name="copy_to_clipboard">Copy to clipboard</string>
+1
View File
@@ -3,6 +3,7 @@
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
<item name="android:windowBackground">@drawable/background_window</item>
</style>
<style name="SplashTheme" parent="@style/AppTheme">
<item name="android:windowBackground">@drawable/background_splash</item>
+6 -6
View File
@@ -5,20 +5,20 @@ rs_allocation inImage;
int inWidth;
int inHeight;
uchar4 RS_KERNEL rotate90(uchar4 in, uint32_t x, uint32_t y) {
const uchar4 *out = rsGetElementAt(inImage, y, inHeight - 1 - x);
uchar RS_KERNEL rotate90(uchar in, uint32_t x, uint32_t y) {
const uchar *out = rsGetElementAt(inImage, y, inHeight - 1 - x);
return *out;
}
uchar4 RS_KERNEL rotate180(uchar4 in, uint32_t x, uint32_t y) {
const uchar4 *out = rsGetElementAt(
uchar RS_KERNEL rotate180(uchar in, uint32_t x, uint32_t y) {
const uchar *out = rsGetElementAt(
inImage,
inWidth - 1 - x,
inHeight - 1 - y);
return *out;
}
uchar4 RS_KERNEL rotate270(uchar4 in, uint32_t x, uint32_t y) {
const uchar4 *out = rsGetElementAt(inImage, inWidth - 1 - y, x);
uchar RS_KERNEL rotate270(uchar in, uint32_t x, uint32_t y) {
const uchar *out = rsGetElementAt(inImage, inWidth - 1 - y, x);
return *out;
}
-17
View File
@@ -1,17 +0,0 @@
#pragma version(1)
#pragma rs java_package_name(de.markusfisch.android.binaryeye.renderscript)
#pragma rs_fp_relaxed
rs_allocation inYUV;
uint32_t inWidth;
uint32_t inHeight;
uchar4 RS_KERNEL yuv2gray(uint32_t x, uint32_t y) {
uchar Y = rsGetElementAt_uchar(inYUV, x, y);
uchar4 out;
out.r = Y;
out.g = Y;
out.b = Y;
out.a = 255;
return out;
}
+12 -5
View File
@@ -1,12 +1,13 @@
buildscript {
ext.kotlin_version = '1.1.4-2'
ext.tools_version = '2.3.3'
ext.build_tools_version = '26.0.0'
ext.sdk_version = 26
ext.kotlin_version = '1.3.11'
ext.tools_version = '3.3.0'
ext.build_tools_version = '28.0.3'
ext.sdk_version = 28
ext.support_version = '25.3.1'
repositories {
jcenter()
google()
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
@@ -15,14 +16,20 @@ buildscript {
dependencies {
classpath "com.android.tools.build:gradle:$tools_version"
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.8'
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.10'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id 'org.sonarqube' version '2.6.2'
}
allprojects {
repositories {
jcenter()
google()
maven { url 'https://jitpack.io' }
}
gradle.projectsEvaluated {
-28
View File
@@ -1,28 +0,0 @@
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:$tools_version"
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion sdk_version
buildToolsVersion build_tools_version
defaultConfig {
minSdkVersion 9
targetSdkVersion sdk_version
versionCode 2
versionName '1.0.1'
}
}
dependencies {
compile "com.android.support:appcompat-v7:$support_version"
}
-3
View File
@@ -1,3 +0,0 @@
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="de.markusfisch.android.cameraview"/>
@@ -1,364 +0,0 @@
package de.markusfisch.android.cameraview.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Rect;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Build;
import android.util.AttributeSet;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import java.io.IOException;
import java.util.List;
public class CameraView extends FrameLayout {
public interface OnCameraListener {
void onConfigureParameters(Camera.Parameters parameters);
void onCameraStarted(Camera camera);
void onCameraStopping(Camera camera);
}
public final Rect previewRect = new Rect();
private Camera camera;
private int viewWidth;
private int viewHeight;
private int frameWidth;
private int frameHeight;
private int frameOrientation;
private OnCameraListener onCameraListener;
public static int findCameraId(int facing) {
for (int i = 0, l = Camera.getNumberOfCameras(); i < l; ++i) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == facing) {
return i;
}
}
return -1;
}
public static int getCameraOrientation(Context context, int cameraId) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(cameraId, info);
return (info.orientation - getDeviceRotation(context) + 360) % 360;
}
public static int getDeviceRotation(Context context) {
switch (((WindowManager) context
.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay()
.getRotation()) {
default:
case Surface.ROTATION_0:
return 0;
case Surface.ROTATION_90:
return 90;
case Surface.ROTATION_180:
return 180;
case Surface.ROTATION_270:
return 270;
}
}
public CameraView(Context context) {
super(context);
}
public CameraView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CameraView(
Context context,
AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void openAsync(final int cameraId) {
new AsyncTask<Void, Void, Camera>() {
@Override
protected Camera doInBackground(Void... nothings) {
if (camera != null) {
return null;
}
try {
// open() may take a while so it shouldn't be
// run on the main thread according to the docs
return Camera.open(cameraId);
} catch (RuntimeException e) {
return null;
}
}
@Override
protected void onPostExecute(Camera camera) {
if (camera == null) {
return;
}
CameraView.this.camera = camera;
Context context = getContext();
if (context == null) {
close();
return;
}
frameOrientation = getCameraOrientation(context, cameraId);
if (viewWidth > 0) {
setCameraParameters(context);
}
}
}.execute();
}
public void close() {
if (camera != null) {
if (onCameraListener != null) {
onCameraListener.onCameraStopping(camera);
}
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
}
removeAllViews();
}
public void setOnCameraListener(OnCameraListener listener) {
onCameraListener = listener;
}
public Camera getCamera() {
return camera;
}
public int getFrameWidth() {
return frameWidth;
}
public int getFrameHeight() {
return frameHeight;
}
public int getFrameOrientation() {
return frameOrientation;
}
@Override
protected void onLayout(
boolean changed,
int left,
int top,
int right,
int bottom) {
if (!changed) {
return;
}
viewWidth = right - left;
viewHeight = bottom - top;
if (camera != null && getChildCount() == 0) {
Context context = getContext();
if (context == null) {
return;
}
setCameraParameters(context);
}
}
private void setCameraParameters(Context context) {
boolean transpose = frameOrientation == 90 || frameOrientation == 270;
Camera.Parameters parameters = camera.getParameters();
parameters.setRotation(frameOrientation);
setPreviewSize(parameters, transpose);
setAutoFocus(parameters);
if (onCameraListener != null) {
onCameraListener.onConfigureParameters(parameters);
}
camera.setParameters(parameters);
camera.setDisplayOrientation(frameOrientation);
int childWidth;
int childHeight;
if (transpose) {
childWidth = frameHeight;
childHeight = frameWidth;
} else {
childWidth = frameWidth;
childHeight = frameHeight;
}
addSurfaceView(context, childWidth, childHeight);
if (onCameraListener != null) {
onCameraListener.onCameraStarted(camera);
}
}
private void setPreviewSize(
Camera.Parameters parameters,
boolean transpose) {
if (transpose) {
frameWidth = viewHeight;
frameHeight = viewWidth;
} else {
frameWidth = viewWidth;
frameHeight = viewHeight;
}
Camera.Size size = findBestPreviewSize(
// will always return at least one item
parameters.getSupportedPreviewSizes(),
frameWidth,
frameHeight);
frameWidth = size.width;
frameHeight = size.height;
parameters.setPreviewSize(frameWidth, frameHeight);
}
private static Camera.Size findBestPreviewSize(
List<Camera.Size> sizes,
int width,
int height) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) width / height;
double minDiff = Double.MAX_VALUE;
double minDiffAspect = Double.MAX_VALUE;
Camera.Size bestSize = null;
Camera.Size bestSizeAspect = null;
for (Camera.Size size : sizes) {
double diff = Math.abs(size.height - height) +
Math.abs(size.width - width);
if (diff < minDiff) {
bestSize = size;
minDiff = diff;
}
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) < ASPECT_TOLERANCE &&
diff < minDiffAspect) {
bestSizeAspect = size;
minDiffAspect = diff;
}
}
return bestSizeAspect != null ? bestSizeAspect : bestSize;
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private static void setAutoFocus(Camera.Parameters parameters) {
// best for taking pictures, API >= ICE_CREAM_SANDWICH
String continuousPicture =
Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE;
// less aggressive than CONTINUOUS_PICTURE, API >= GINGERBREAD
String continuousVideo =
Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO;
// last resort
String autoFocus = Camera.Parameters.FOCUS_MODE_AUTO;
// prefer feature detection instead of checking BUILD.VERSION
List<String> focusModes = parameters.getSupportedFocusModes();
if (focusModes.contains(continuousPicture)) {
parameters.setFocusMode(continuousPicture);
} else if (focusModes.contains(continuousVideo)) {
parameters.setFocusMode(continuousVideo);
} else if (focusModes.contains(autoFocus)) {
parameters.setFocusMode(autoFocus);
}
}
private void addSurfaceView(
Context context,
int surfaceWidth,
int surfaceHeight) {
SurfaceView surfaceView = new SurfaceView(context);
SurfaceHolder holder = surfaceView.getHolder();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
holder.setKeepScreenOn(true);
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(
SurfaceHolder holder,
int format,
int width,
int height) {
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
return;
}
camera.startPreview();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
close();
}
});
addView(surfaceView);
setChildLayout(
viewWidth,
viewHeight,
surfaceView,
surfaceWidth,
surfaceHeight,
previewRect);
}
private static void setChildLayout(
int width,
int height,
View child,
int childWidth,
int childHeight,
Rect childRect) {
int widthByHeight = width * childHeight;
int heightByWidth = height * childWidth;
boolean dontScaleBeyondScreen = Build.VERSION.SDK_INT <
Build.VERSION_CODES.ICE_CREAM_SANDWICH;
if (dontScaleBeyondScreen ?
// center within parent view
widthByHeight > heightByWidth :
// scale to cover parent view
widthByHeight < heightByWidth) {
childWidth = childWidth * height / childHeight;
childHeight = height;
} else {
childHeight = childHeight * width / childWidth;
childWidth = width;
}
int l = (width - childWidth) >> 1;
int t = dontScaleBeyondScreen ?
(height - childHeight) >> 1 :
0;
childRect.set(
l,
t,
l + childWidth,
t + childHeight);
child.layout(
childRect.left,
childRect.top,
childRect.right,
childRect.bottom);
}
}
+1 -1
View File
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
+1 -1
View File
@@ -1 +1 @@
include ':app', ':cameraview'
include ':app'
+4 -4
View File
@@ -26,7 +26,7 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.7708333"
inkscape:zoom="0.74025241"
inkscape:cx="96"
inkscape:cy="96"
inkscape:document-units="px"
@@ -35,7 +35,7 @@
units="px"
inkscape:showpageshadow="false"
inkscape:window-width="1680"
inkscape:window-height="925"
inkscape:window-height="1005"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1"
@@ -64,9 +64,9 @@
cy="958.36218"
cx="96"
id="circle5439"
style="fill:#26af9d;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
style="fill:#a6c45f;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
style="fill:#26e1cf;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
style="fill:#b6d46f;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path5437"
cx="96"
cy="956.36218"

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

+324
View File
@@ -0,0 +1,324 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="108"
height="108"
id="svg3317"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="ic_launcher_foreground.svg"
inkscape:export-filename="/home/markus/ic_launcher.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#f0f0f0"
borderopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.5870527"
inkscape:cx="19.507087"
inkscape:cy="38.86531"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showborder="true"
inkscape:showpageshadow="false"
inkscape:window-width="1426"
inkscape:window-height="878"
inkscape:window-x="109"
inkscape:window-y="15"
inkscape:window-maximized="0"
showguides="true"
inkscape:guide-bbox="true" />
<defs
id="defs3319" />
<metadata
id="metadata3322">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-944.36218)">
<flowRoot
xml:space="preserve"
id="flowRoot3776"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><flowRegion
id="flowRegion3778"><rect
id="rect3780"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="4676.4058"
y="3368.0371"
id="text5084"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086"
x="4676.4058"
y="3368.0371" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-6"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(532.64516,-5.806285)"><flowRegion
id="flowRegion3778-7"><rect
id="rect3780-2"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-0" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="5209.0508"
y="3362.2307"
id="text5084-0"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-1"
x="5209.0508"
y="3362.2307" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-8"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(658.04407,24.647949)"><flowRegion
id="flowRegion3778-4"><rect
id="rect3780-5"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-2" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="5334.4497"
y="3392.6851"
id="text5084-3"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-18"
x="5334.4497"
y="3392.6851" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-2"
style="font-style:normal;font-weight:normal;font-size:4.31339216px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><flowRegion
id="flowRegion3778-41"><rect
id="rect3780-54"
width="3.1272094"
height="7.6562715"
x="32.001694"
y="919.38837" /></flowRegion><flowPara
id="flowPara3782-28" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:4.31339216px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="530.67358"
y="1276.1099"
id="text5084-7"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-8"
x="530.67358"
y="1276.1099" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-6-6"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.15319136,0,0,0.15319148,127.35392,875.47681)"><flowRegion
id="flowRegion3778-9"><rect
id="rect3780-6"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-8" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.12765694px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="843.73926"
y="1391.4308"
id="text5084-3-4"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-9"
x="843.73926"
y="1391.4308" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-0"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.15319136,0,0,0.15319148,14.782981,876.36628)"><flowRegion
id="flowRegion3778-6"><rect
id="rect3780-9"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-3" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.12765694px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="731.16821"
y="1392.3203"
id="text5084-9"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-96"
x="731.16821"
y="1392.3203" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot5144"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.16554551,0,0,0.16554564,-16.191329,1002.8288)"><flowRegion
id="flowRegion5146"><rect
id="rect5148"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara5150" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.62182283px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="757.96692"
y="1560.3921"
id="text5152"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5154"
x="757.96692"
y="1560.3921" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot5388"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.20754958,0,0,0.20754975,18,1009.1389)"><flowRegion
id="flowRegion5390"><rect
id="rect5392"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara5394" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:8.30198669px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="988.58643"
y="1708.1735"
id="text5396"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5398"
x="988.58643"
y="1708.1735" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-2-9"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.15319136,0,0,0.15319148,274.51689,845.19743)"><flowRegion
id="flowRegion3778-7-9"><rect
id="rect3780-0"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-5" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.12765694px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="990.90228"
y="1361.1515"
id="text5084-7-9"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-0"
x="990.90228"
y="1361.1515" /></text>
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.1254902;fill-rule:nonzero;stroke:none;stroke-width:8.60725021;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 54.826172,972.2557 c -6.850552,0 -13.700955,2.58141 -18.92365,7.74543 -10.445393,10.32803 -10.413074,27.06217 0,37.42287 l 36.218217,36.036 37.879261,0.9022 -0.0703,-38.363 -36.179869,-35.99807 c -5.206507,-5.18035 -12.073095,-7.74542 -18.923649,-7.74543 z"
id="path5462"
sodipodi:nodetypes="ssscccss" />
<ellipse
cy="998.48041"
cx="54.525307"
id="circle5467"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
rx="26.524622"
ry="26.226593" />
<ellipse
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle5451"
cx="53.769596"
cy="999.35065"
rx="14.509266"
ry="14.34624" />
<ellipse
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle5455"
cx="63.569546"
cy="988.87518"
rx="9.5350714"
ry="9.4279356" />
<flowRoot
xml:space="preserve"
id="flowRoot3776-7"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.40909091,0,0,0.40449438,69.886136,669.54123)"><flowRegion
id="flowRegion3778-3"><rect
id="rect3780-3"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-6" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:16.27144623px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="1971.7896"
y="2043.4055"
id="text5084-38"
sodipodi:linespacing="125%"
transform="scale(1.0056658,0.99436615)"><tspan
sodipodi:role="line"
id="tspan5086-2"
x="1971.7896"
y="2043.4055" /></text>
<g
id="g4345"
transform="matrix(0.08186913,-0.12212103,0.12350877,0.08094925,-58.53806,925.20741)">
<path
transform="matrix(-0.71624605,0,0,0.71624605,252.9668,272.6866)"
id="path4155"
d="m 70.800257,803.10815 c 18.72634,-10.81207 42.064013,-4.55865 52.875453,14.16738 6.21553,10.76497 6.67525,22.98383 2.43735,33.71348 9.95484,0.22482 20.00712,3.82743 29.87632,9.35284 5.70581,-16.36426 17.92669,-30.34 32.41043,-37.86744 a 7.6098878,7.6098878 0 0 1 2.05397,-0.12843 7.6098878,7.6098878 0 0 1 2.05385,-0.12842 7.6098878,7.6098878 0 0 1 3.78076,1.01708 7.6098878,7.6098878 0 0 1 2.18403,1.941 7.6098878,7.6098878 0 0 1 1.16879,5.70957 7.6098878,7.6098878 0 0 1 -0.34046,1.25368 7.6098878,7.6098878 0 0 1 -0.34045,1.25368 7.6098878,7.6098878 0 0 1 -1.13869,1.71405 7.6098878,7.6098878 0 0 1 -2.39442,1.38323 c -12.33033,6.40652 -22.54596,18.62752 -26.1492,32.12255 6.50822,5.40015 12.37934,12.05934 17.69138,19.58251 2.94622,-3.19898 6.27645,-6.41509 9.78804,-8.85073 10.09338,-6.95039 22.03067,-10.77888 33.55578,-11.9223 a 7.6098878,7.6098878 0 0 1 1.25571,0.33189 7.6098878,7.6098878 0 0 1 2.51017,0.66378 7.6098878,7.6098878 0 0 1 2.18447,1.94102 7.6098878,7.6098878 0 0 1 2.42684,6.04679 7.6098878,7.6098878 0 0 1 -1.00849,3.78247 7.6098878,7.6098878 0 0 1 -1.5963,0.92072 7.6098878,7.6098878 0 0 1 -1.59626,0.92072 7.6098878,7.6098878 0 0 1 -2.85201,0.58884 c -13.65036,1.36931 -27.8309,8.78649 -36.37383,19.9433 4.14518,8.3272 7.21579,16.27327 8.91185,24.65187 15.54086,-3.62622 31.79047,-2.0192 45.28817,4.71176 a 7.6098878,7.6098878 0 0 1 1.71243,1.12411 7.6098878,7.6098878 0 0 1 1.84305,3.19152 7.6098878,7.6098878 0 0 1 0.45715,0.79218 7.6098878,7.6098878 0 0 1 0.58777,2.8607 7.6098878,7.6098878 0 0 1 -0.34045,1.25368 7.6098878,7.6098878 0 0 1 -0.34046,1.25368 7.6098878,7.6098878 0 0 1 -1.1386,1.71511 7.6098878,7.6098878 0 0 1 -1.1387,1.71411 7.6098878,7.6098878 0 0 1 -2.05385,0.12842 7.6098878,7.6098878 0 0 1 -1.59627,0.92073 7.6098878,7.6098878 0 0 1 -1.25582,-0.33184 7.6098878,7.6098878 0 0 1 -2.51059,-0.66378 7.6098878,7.6098878 0 0 1 -1.25572,-0.33193 c -10.93219,-5.45468 -24.04674,-6.71593 -36.1414,-3.61644 0.84257,22.7793 -7.86138,42.849 -24.91405,52.6953 -17.24869,9.95781 -39.08043,6.90761 -58.55086,-5.565 -8.96849,9.0596 -14.53598,22.16701 -15.27897,34.36191 a 7.6098878,7.6098878 0 0 1 0.11664,2.0437 7.6098878,7.6098878 0 0 1 -0.34045,1.2537 7.6098878,7.6098878 0 0 1 -0.79867,0.4604 7.6098878,7.6098878 0 0 1 -1.1387,1.7141 7.6098878,7.6098878 0 0 1 -0.79761,0.4603 7.6098878,7.6098878 0 0 1 -1.59628,0.9207 7.6098878,7.6098878 0 0 1 -2.05385,0.129 7.6098878,7.6098878 0 0 1 -2.053973,0.1289 7.6098878,7.6098878 0 0 1 -4.69933,-2.6091 7.6098878,7.6098878 0 0 1 -0.45715,-0.7922 7.6098878,7.6098878 0 0 1 -1.04491,-3.6529 7.6098878,7.6098878 0 0 1 0.34045,-1.2527 c 0.91965,-15.0554 7.652193,-29.93151 18.564363,-41.57551 -6.41905,-5.6678 -12.547323,-11.8152 -17.691493,-19.58247 -13.6403,2.06297 -26.80473,10.14937 -34.66043,21.06847 a 7.6098878,7.6098878 0 0 1 -0.34045,1.2537 7.6098878,7.6098878 0 0 1 -0.79761,0.4604 7.6098878,7.6098878 0 0 1 -5.24642,1.9721 7.6098878,7.6098878 0 0 1 -1.25572,-0.3319 7.6098878,7.6098878 0 0 1 -4.23746,-1.8104 7.6098878,7.6098878 0 0 1 -0.45714,-0.7923 7.6098878,7.6098878 0 0 1 -1.04492,-3.6539 7.6098878,7.6098878 0 0 1 -0.45822,-0.7923 7.6098878,7.6098878 0 0 1 1.00851,-3.7825 7.6098878,7.6098878 0 0 1 0.34045,-1.2536 c 6.76957,-9.3808 16.03633,-17.83431 27.10278,-23.09844 3.86662,-1.82118 8.31639,-3.09838 12.56029,-4.05121 -3.85055,-8.35079 -6.69506,-16.79143 -8.11382,-25.11222 -13.48882,-3.62722 -29.18257,-0.8993 -40.89482,6.58318 a 7.6098878,7.6098878 0 0 1 -1.59627,0.92073 7.6098878,7.6098878 0 0 1 -2.05386,0.12842 7.6098878,7.6098878 0 0 1 -2.05396,0.12843 7.6098878,7.6098878 0 0 1 -3.78033,-1.01711 7.6098878,7.6098878 0 0 1 -0.45714,-0.79226 7.6098878,7.6098878 0 0 1 -1.84348,-3.19254 7.6098878,7.6098878 0 0 1 -0.45715,-0.79225 7.6098878,7.6098878 0 0 1 0.55137,-4.57469 7.6098878,7.6098878 0 0 1 1.59627,-0.92074 7.6098878,7.6098878 0 0 1 0.34046,-1.25368 7.6098878,7.6098878 0 0 1 0.79759,-0.46035 7.6098878,7.6098878 0 0 1 0.34046,-1.25262 c 13.75648,-8.78862 31.97364,-12.37945 48.99964,-9.13551 0.14989,-11.34095 2.02912,-21.8008 6.83756,-30.5509 -11.50435,-1.63589 -22.5161,-7.66449 -28.77541,-18.50548 -10.81155,-18.72602 -3.76051,-42.52566 14.96583,-53.33667 z"
style="fill:#ff2a2a;fill-opacity:1;stroke:none"
inkscape:connector-curvature="0" />
<path
id="path3847"
d="m 172.88153,898.78816 c 1.83132,1.05745 -6.95107,19.96031 -20.00325,42.56771 -13.05188,22.60654 -25.3621,40.23658 -27.19342,39.17911 -1.83139,-1.05746 7.28157,-20.53316 20.33346,-43.13977 13.05218,-22.60659 25.03181,-39.66449 26.86321,-38.60705 z"
style="fill:#d40000;fill-opacity:1;stroke:none"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

+3 -3
View File
@@ -35,7 +35,7 @@
units="px"
inkscape:showpageshadow="false"
inkscape:window-width="1680"
inkscape:window-height="925"
inkscape:window-height="1005"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1"
@@ -60,14 +60,14 @@
id="layer1"
transform="translate(0,-552.36218)">
<rect
style="fill:#26e1cf;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
style="fill:#b6d46f;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4139"
width="1024"
height="500"
x="0"
y="552.36218" />
<path
style="fill:#26af9d;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
style="fill:#a6c45f;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 786.41602 28.683594 A 397.04337 397.04337 0 0 0 389.37305 425.72656 A 397.04337 397.04337 0 0 0 396.67383 500 L 1024 500 L 1024 108.21484 A 397.04337 397.04337 0 0 0 786.41602 28.683594 z "
transform="translate(0,552.36218)"
id="circle5439" />

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

+5 -5
View File
@@ -26,8 +26,8 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.7708333"
inkscape:cx="31.823204"
inkscape:zoom="1.046875"
inkscape:cx="96"
inkscape:cy="96"
inkscape:document-units="px"
inkscape:current-layer="layer1"
@@ -35,7 +35,7 @@
units="px"
inkscape:showpageshadow="false"
inkscape:window-width="1680"
inkscape:window-height="925"
inkscape:window-height="1005"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1"
@@ -64,9 +64,9 @@
cy="958.36218"
cx="96"
id="circle5439"
style="fill:#26af9d;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
style="fill:#a6c45f;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
style="fill:#26e1cf;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
style="fill:#b6d46f;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path5437"
cx="96"
cy="956.36218"

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

+286
View File
@@ -0,0 +1,286 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="108"
height="108"
id="svg3317"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="ic_launcher_foreground.svg"
inkscape:export-filename="/home/markus/ic_launcher.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#f0f0f0"
borderopacity="1"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.432512"
inkscape:cx="54"
inkscape:cy="54"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showborder="true"
inkscape:showpageshadow="false"
inkscape:window-width="1426"
inkscape:window-height="878"
inkscape:window-x="109"
inkscape:window-y="15"
inkscape:window-maximized="0"
showguides="true"
inkscape:guide-bbox="true" />
<defs
id="defs3319" />
<metadata
id="metadata3322">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-944.36218)">
<flowRoot
xml:space="preserve"
id="flowRoot3776"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><flowRegion
id="flowRegion3778"><rect
id="rect3780"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="4676.4058"
y="3368.0371"
id="text5084"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086"
x="4676.4058"
y="3368.0371" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-6"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(532.64516,-5.806285)"><flowRegion
id="flowRegion3778-7"><rect
id="rect3780-2"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-0" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="5209.0508"
y="3362.2307"
id="text5084-0"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-1"
x="5209.0508"
y="3362.2307" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-8"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="translate(658.04407,24.647949)"><flowRegion
id="flowRegion3778-4"><rect
id="rect3780-5"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-2" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="5334.4497"
y="3392.6851"
id="text5084-3"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-18"
x="5334.4497"
y="3392.6851" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-2"
style="font-style:normal;font-weight:normal;font-size:4.31339216px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"><flowRegion
id="flowRegion3778-41"><rect
id="rect3780-54"
width="3.1272094"
height="7.6562715"
x="32.001694"
y="919.38837" /></flowRegion><flowPara
id="flowPara3782-28" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:4.31339216px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="530.67358"
y="1276.1099"
id="text5084-7"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-8"
x="530.67358"
y="1276.1099" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-6-6"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.15319136,0,0,0.15319148,127.35392,875.47681)"><flowRegion
id="flowRegion3778-9"><rect
id="rect3780-6"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-8" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.12765694px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="843.73926"
y="1391.4308"
id="text5084-3-4"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-9"
x="843.73926"
y="1391.4308" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-0"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.15319136,0,0,0.15319148,14.782981,876.36628)"><flowRegion
id="flowRegion3778-6"><rect
id="rect3780-9"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-3" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.12765694px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="731.16821"
y="1392.3203"
id="text5084-9"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-96"
x="731.16821"
y="1392.3203" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot5144"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.16554551,0,0,0.16554564,-16.191329,1002.8288)"><flowRegion
id="flowRegion5146"><rect
id="rect5148"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara5150" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.62182283px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="757.96692"
y="1560.3921"
id="text5152"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5154"
x="757.96692"
y="1560.3921" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot5388"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.20754958,0,0,0.20754975,18,1009.1389)"><flowRegion
id="flowRegion5390"><rect
id="rect5392"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara5394" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:8.30198669px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="988.58643"
y="1708.1735"
id="text5396"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5398"
x="988.58643"
y="1708.1735" /></text>
<flowRoot
xml:space="preserve"
id="flowRoot3776-2-9"
style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
transform="matrix(0.15319136,0,0,0.15319148,274.51689,845.19743)"><flowRegion
id="flowRegion3778-7-9"><rect
id="rect3780-0"
width="29"
height="71"
x="52"
y="60" /></flowRegion><flowPara
id="flowPara3782-5" /></flowRoot> <text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.12765694px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="990.90228"
y="1361.1515"
id="text5084-7-9"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5086-0"
x="990.90228"
y="1361.1515" /></text>
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.1254902;fill-rule:nonzero;stroke:none;stroke-width:8.60725021;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 54.826172,972.2557 c -6.850552,0 -13.700955,2.58141 -18.92365,7.74543 -10.445393,10.32803 -10.413074,27.06217 0,37.42287 l 36.218217,36.036 37.879261,0.9022 -0.0703,-38.363 -36.179869,-35.99807 c -5.206507,-5.18035 -12.073095,-7.74542 -18.923649,-7.74543 z"
id="path5462"
sodipodi:nodetypes="ssscccss" />
<ellipse
cy="998.48041"
cx="54.525307"
id="circle5467"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
rx="26.524622"
ry="26.226593" />
<ellipse
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle5451"
cx="53.769596"
cy="999.35065"
rx="14.509266"
ry="14.34624" />
<ellipse
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle5455"
cx="63.569546"
cy="988.87518"
rx="9.5350714"
ry="9.4279356" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

+98
View File
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="192"
height="192"
viewBox="0 0 192 192"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="ic_launcher.svg"
inkscape:export-filename="/Users/markus/app_icon.png"
inkscape:export-xdpi="240"
inkscape:export-ydpi="240">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.046875"
inkscape:cx="96"
inkscape:cy="96"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:showpageshadow="false"
inkscape:window-width="1680"
inkscape:window-height="1005"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1"
showguides="false" />
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-860.36218)">
<circle
r="88"
cy="958.36218"
cx="96"
id="circle5439"
style="fill:#a6c45f;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
style="fill:#b6d46f;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path5437"
cx="96"
cy="956.36218"
r="88" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:0.1254902;fill-rule:nonzero;stroke:none;stroke-width:8.60725021;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 98.019531 32.458984 C 81.273736 32.458984 64.528308 38.840812 51.761719 51.607422 C 26.228537 77.140592 26.228537 118.59177 51.761719 144.125 L 91.40625 183.76953 A 88 88 0 0 0 96 184 A 88 88 0 0 0 184 96 A 88 88 0 0 0 183.82812 91.158203 L 144.27734 51.607422 C 131.51074 38.840812 114.76533 32.459024 98.019531 32.458984 z "
transform="translate(0,860.36218)"
id="path5462" />
<circle
r="64.837967"
cy="957.65448"
cx="97.284081"
id="circle5467"
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<circle
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle5451"
cx="95.43679"
cy="959.80591"
r="35.467094" />
<circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="circle5455"
cx="119.39222"
cy="933.90826"
r="23.307953" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

-63
View File
@@ -1,63 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
fill="#000000"
height="24"
viewBox="0 0 24 24"
width="24"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="marker.svg">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1215"
inkscape:window-height="643"
id="namedview8"
showgrid="false"
inkscape:showpageshadow="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 6.4576853,2.0235976 C 4.0190093,2.0235564 2.0237288,4.0188781 2.0237288,6.4575542 l 0,15.5188478 4.4339565,0 0,-15.5188478 15.5185857,0 0,-4.4336942 z"
id="rect4146"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sscccccs" />
<path
d="M0 0h24v24H0z"
fill="none"
id="path4" />
</svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

+7 -4
View File
@@ -102,10 +102,6 @@ type converter &>/dev/null || find_converter || {
exit 1
}
update app/src/main/res/drawable << EOF
svg/marker.svg 48
EOF
update app/src/debug/res/mipmap << EOF
svg/debug/ic_launcher.svg 48
EOF
@@ -113,3 +109,10 @@ EOF
update app/src/main/res/mipmap << EOF
svg/ic_launcher.svg 48
EOF
update app/src/main/res/drawable << EOF
svg/debug/ic_launcher_foreground.svg 108
svg/wallpaper.svg 384
svg/ic_launcher_foreground.svg 108
svg/logo.svg 80
EOF
+74
View File
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="192"
height="192"
viewBox="0 0 192 192"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="wallpaper.svg"
inkscape:export-filename="/Users/markus/app_icon.png"
inkscape:export-xdpi="240"
inkscape:export-ydpi="240">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.0833333"
inkscape:cx="96"
inkscape:cy="96"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:showpageshadow="false"
inkscape:window-width="1680"
inkscape:window-height="1001"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1"
showguides="false" />
<defs
id="defs4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-860.36218)">
<circle
r="88"
cy="882.36218"
cx="150"
id="circle4151"
style="fill:#1b1b1b;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#111111;fill-opacity:1;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 151.2832,816.81726 a 64.837967,64.837967 0 0 0 -64.837888,64.83789 64.837967,64.837967 0 0 0 64.837888,64.83789 64.837967,64.837967 0 0 0 64.83789,-64.83789 64.837967,64.837967 0 0 0 -64.83789,-64.83789 z m -1.8457,31.52148 a 35.467094,35.467094 0 0 1 2.66016,0.13282 23.307953,23.307953 0 0 0 -2.01368,9.4375 23.307953,23.307953 0 0 0 23.3086,23.30664 23.307953,23.307953 0 0 0 11.07031,-2.82032 35.467094,35.467094 0 0 1 0.44141,5.41016 35.467094,35.467094 0 0 1 -35.4668,35.4668 35.467094,35.467094 0 0 1 -35.46875,-35.4668 35.467094,35.467094 0 0 1 35.46875,-35.4668 z"
id="circle4143"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB