Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
faf300db3e | ||
|
|
2fbdd03225 | ||
|
|
9f825f9d5d | ||
|
|
5ff1904148 | ||
|
|
16e80ff80e | ||
|
|
1dcd1845a7 | ||
|
|
955f507023 | ||
|
|
47a3224b27 | ||
|
|
d2bf09d321 | ||
|
|
deee39b367 | ||
|
|
4829433725 | ||
|
|
9efd43e496 | ||
|
|
5bd904ba4f | ||
|
|
3244f0775f | ||
|
|
f4d625a048 | ||
|
|
c838486ca1 | ||
|
|
d4a9ea1a4b | ||
|
|
4123905853 | ||
|
|
720811bf3b | ||
|
|
375fb4aa46 | ||
|
|
aa4b79d13d | ||
|
|
1e9c303646 | ||
|
|
d3ab28f2b3 | ||
|
|
7b67778a29 | ||
|
|
d2c8ef719b | ||
|
|
7bed192300 | ||
|
|
331f65f3a4 | ||
|
|
e17c732b6a | ||
|
|
2e60b2b997 | ||
|
|
70d9b8b99a | ||
|
|
d0cc7e0a68 | ||
|
|
264e7ad098 | ||
|
|
8c33e9bd57 | ||
|
|
a8fd37e4e4 | ||
|
|
17f11ea2de | ||
|
|
f6a582e4f7 | ||
|
|
6e645a567a | ||
|
|
e87dc35372 | ||
|
|
75f4f3eadc | ||
|
|
64e1d722d5 | ||
|
|
05a206384c | ||
|
|
04790e2b57 | ||
|
|
aa3c4a17e9 | ||
|
|
5968ae01eb | ||
|
|
57500b7700 | ||
|
|
4e17a21e5f | ||
|
|
605dc51d50 | ||
|
|
b17d29ba28 | ||
|
|
9afc7fcc62 | ||
|
|
d5543d0c39 | ||
|
|
96fea1f343 | ||
|
|
bc4d9f7148 | ||
|
|
4abacf030b | ||
|
|
279c988464 | ||
|
|
a6449b50e9 | ||
|
|
b4e6449dac | ||
|
|
c3dfadd9e6 | ||
|
|
bad5225024 | ||
|
|
aa9b4927b0 | ||
|
|
69d12910cd | ||
|
|
ee0f7c4529 | ||
|
|
1b296ff83e | ||
|
|
1a635af7b7 | ||
|
|
568530d470 |
@@ -1,18 +0,0 @@
|
||||
language: android
|
||||
android:
|
||||
components:
|
||||
- platform-tools
|
||||
- build-tools-26.0.0
|
||||
- android-26
|
||||
- extra-android-m2repository
|
||||
addons:
|
||||
sonarcloud:
|
||||
organization: "markusfisch-github"
|
||||
token:
|
||||
secure: "mTpn1JNKn/PzEFGTRvkmSfCj0c6nX8n/ef2IO0xPSFyveuM+cpNka5d4/nT1QxEqq1sLUj5HMHEShdk6XlER5Oro+DqekTSw8ONv8P24IZGjiM5noLJZ7uqv/73tM0SevROl3Ldee6AzyS7PzcextQms5UC8uyCgI2jbYwz3hpayaWPquBGRnlw7xGuYwCjJS2cMrhz8sEYRn3Egk3no1YJlxCdbIVaqtVmLweqBzLp176FWB5Svg8N3r+UzaZ3fhQn6LhlHPuObPTrCoVjy6W9TxdUsHfW3F61Zei9h1IEsCC0qsalY0OZC8ML5F2DTDp0spKHnPlXR4Q4hF9XIngk2vPVMtfJhu3JJRojjrxhtfOUZO/VS0AMpueZ5QiL1ZbHziKk9ztuRsB+OIoehWnBTq/r/igrWfqxfsq2VURfAYFldRnobBlT/svNkHBjHfZl9EqKprvwmmvw15ZD0twgsskweDn3GssHC5MGTH6+ujZI19t/SLbDMY2KVPNCrG9sHEXSqKT8wWxqGigUaIbVytD2SqGWep0qsB86FQLAXOmgr3+0upTx3B8YhMG5GGu/R45pJBwzXZbTqSx0goaxP+BBEkzcjQHNl0RvpF44m/FbPMYUBuNyHHEoEZC5G1raOV9jtI8G6whQP3OaT8lO2Aqbp1W/lTSEnCDcKYlU="
|
||||
script:
|
||||
- bash gradlew build
|
||||
- bash gradlew sonarqube
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
@@ -1,5 +1,28 @@
|
||||
# Change Log
|
||||
|
||||
## 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,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
|
||||
|
||||
@@ -22,6 +22,9 @@ sonarqube:
|
||||
infer: clean
|
||||
infer -- ./gradlew assembleDebug
|
||||
|
||||
test:
|
||||
./gradlew cAT
|
||||
|
||||
install:
|
||||
adb $(TARGET) install -r $(APK)
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Binary Eye
|
||||
|
||||
<a href="https://travis-ci.org/markusfisch/BinaryEye"><img src="https://api.travis-ci.org/markusfisch/BinaryEye.svg" alt="Travis-ci"/></a>
|
||||
|
||||
Yet another barcode scanner for Android. As if there weren't [enough][play].
|
||||
|
||||
This one is totally free, open source and does use the [ZXing][zxing] barcode
|
||||
|
||||
@@ -14,11 +14,19 @@ android {
|
||||
minSdkVersion 9
|
||||
targetSdkVersion sdk_version
|
||||
|
||||
versionCode 7
|
||||
versionName '1.3.1'
|
||||
versionCode 13
|
||||
versionName '1.3.7'
|
||||
|
||||
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,16 @@ 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 fileTree(dir: 'libs', include: '*')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation "com.android.support:appcompat-v7:$support_version"
|
||||
implementation "com.android.support:design:$support_version"
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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"/>
|
||||
@@ -33,11 +29,15 @@
|
||||
<activity
|
||||
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"/>
|
||||
|
||||
@@ -5,7 +5,7 @@ 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.YuvToGray
|
||||
import de.markusfisch.android.binaryeye.rs.Preprocessor
|
||||
import de.markusfisch.android.binaryeye.zxing.Zxing
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
@@ -24,18 +24,11 @@ import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.widget.SeekBar
|
||||
import android.widget.Toast
|
||||
|
||||
class CameraActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
private val REQUEST_CAMERA = 1
|
||||
private val ZOOM_MAX = "zoom_max"
|
||||
private val ZOOM_LEVEL = "zoom_level"
|
||||
}
|
||||
|
||||
private val zxing = Zxing()
|
||||
private val decodingRunnable = Runnable {
|
||||
while (decoding) {
|
||||
@@ -52,26 +45,31 @@ class CameraActivity : AppCompatActivity() {
|
||||
private lateinit var vibrator: Vibrator
|
||||
private lateinit var cameraView: CameraView
|
||||
private lateinit var zoomBar: SeekBar
|
||||
private lateinit var yuvToGray: YuvToGray
|
||||
|
||||
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 odd = false
|
||||
private var invert = false
|
||||
private var flash = false
|
||||
private var returnResult = false
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<String>,
|
||||
grantResults: IntArray) {
|
||||
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()
|
||||
grantResults[0] != PackageManager.PERMISSION_GRANTED) {
|
||||
Toast.makeText(
|
||||
this,
|
||||
R.string.no_camera_no_fun,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
@@ -86,13 +84,11 @@ class CameraActivity : AppCompatActivity() {
|
||||
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
||||
yuvToGray = YuvToGray(this)
|
||||
|
||||
cameraView = findViewById(R.id.camera_view) as CameraView
|
||||
zoomBar = findViewById(R.id.zoom) as SeekBar
|
||||
|
||||
initCameraView()
|
||||
setTapToFocus()
|
||||
initZoomBar()
|
||||
restoreZoom()
|
||||
initFlashFab(findViewById(R.id.flash))
|
||||
@@ -100,7 +96,7 @@ class CameraActivity : AppCompatActivity() {
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
yuvToGray.destroy()
|
||||
preprocessor?.destroy()
|
||||
saveZoom()
|
||||
}
|
||||
|
||||
@@ -112,10 +108,16 @@ class CameraActivity : AppCompatActivity() {
|
||||
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))
|
||||
startDecoding()
|
||||
cameraView.openAsync(
|
||||
CameraView.findCameraId(
|
||||
Camera.CameraInfo.CAMERA_FACING_BACK
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,13 +159,18 @@ class CameraActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun openReadme() {
|
||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(
|
||||
"https://github.com/markusfisch/BinaryEye/blob/master/README.md")))
|
||||
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())) {
|
||||
!"text/plain".equals(intent.getType())) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -175,16 +182,19 @@ class CameraActivity : AppCompatActivity() {
|
||||
// consume this intent
|
||||
intent.setAction(null)
|
||||
|
||||
startActivity(MainActivity.getEncodeIntent(this, text))
|
||||
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)
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
ActivityCompat.requestPermissions(
|
||||
this, arrayOf(permission),
|
||||
REQUEST_CAMERA
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -192,71 +202,70 @@ class CameraActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun initCameraView() {
|
||||
cameraView.setUseOrientationListener(true)
|
||||
cameraView.setTapToFocus()
|
||||
cameraView.setOnCameraListener(object : CameraView.OnCameraListener {
|
||||
override fun onConfigureParameters(
|
||||
parameters: Camera.Parameters) {
|
||||
parameters: Camera.Parameters
|
||||
) {
|
||||
if (parameters.isZoomSupported()) {
|
||||
val max = parameters.getMaxZoom()
|
||||
if (zoomBar.max != max) {
|
||||
zoomBar.max = max
|
||||
zoomBar.progress = max / 3
|
||||
zoomBar.progress = max / 10
|
||||
saveZoom()
|
||||
}
|
||||
parameters.setZoom(zoomBar.progress)
|
||||
} else {
|
||||
zoomBar.visibility = View.GONE
|
||||
}
|
||||
for (mode in parameters.getSupportedSceneModes()) {
|
||||
if (mode.equals(Camera.Parameters.SCENE_MODE_BARCODE)) {
|
||||
parameters.setSceneMode(mode)
|
||||
break
|
||||
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()
|
||||
Toast.makeText(
|
||||
this@CameraActivity,
|
||||
R.string.camera_error,
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun onCameraStarted(camera: Camera) {
|
||||
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 setTapToFocus() {
|
||||
val runnable = Runnable {
|
||||
cameraView.setFocusArea(null)
|
||||
}
|
||||
cameraView.setOnTouchListener({ v: View, event: MotionEvent ->
|
||||
val camera = cameraView.getCamera()
|
||||
camera?.cancelAutoFocus()
|
||||
cameraView.setFocusArea(cameraView.calculateFocusRect(
|
||||
event.getX(), event.getY(), 100))
|
||||
camera?.autoFocus({ _: Boolean, _: Camera ->
|
||||
cameraView.removeCallbacks(runnable)
|
||||
cameraView.postDelayed(runnable, 3000)
|
||||
})
|
||||
v.performClick()
|
||||
true
|
||||
})
|
||||
}
|
||||
|
||||
private fun initZoomBar() {
|
||||
zoomBar.setOnSeekBarChangeListener(object :
|
||||
SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(seekBar: SeekBar, progress: Int,
|
||||
fromUser: Boolean) {
|
||||
SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(
|
||||
seekBar: SeekBar,
|
||||
progress: Int,
|
||||
fromUser: Boolean
|
||||
) {
|
||||
setZoom(progress)
|
||||
}
|
||||
|
||||
@@ -293,7 +302,8 @@ class CameraActivity : AppCompatActivity() {
|
||||
|
||||
private fun initFlashFab(fab: View) {
|
||||
if (!packageManager.hasSystemFeature(
|
||||
PackageManager.FEATURE_CAMERA_FLASH)) {
|
||||
PackageManager.FEATURE_CAMERA_FLASH
|
||||
)) {
|
||||
fab.visibility = View.GONE
|
||||
} else {
|
||||
fab.setOnClickListener { _ ->
|
||||
@@ -305,10 +315,13 @@ class CameraActivity : AppCompatActivity() {
|
||||
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)
|
||||
parameters?.setFlashMode(
|
||||
if (flash) {
|
||||
Camera.Parameters.FLASH_MODE_OFF
|
||||
} else {
|
||||
Camera.Parameters.FLASH_MODE_TORCH
|
||||
}
|
||||
)
|
||||
flash = flash xor true
|
||||
parameters?.let { camera.setParameters(parameters) }
|
||||
}
|
||||
@@ -332,20 +345,57 @@ class CameraActivity : AppCompatActivity() {
|
||||
decodingThread?.interrupt()
|
||||
}
|
||||
}
|
||||
decodingThread = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun decodeFrame(): Result? {
|
||||
frameData ?: return null
|
||||
return zxing.decodeBitmap(yuvToGray.convert(
|
||||
frameData!!, frameWidth, frameHeight, frameOrientation))
|
||||
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)
|
||||
|
||||
startActivity(MainActivity.getDecodeIntent(this, result.text,
|
||||
result.getBarcodeFormat()))
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,26 +16,6 @@ import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
private val ENCODE = "encode"
|
||||
private val DECODE = "decode"
|
||||
private val DECODE_FORMAT = "decode_format"
|
||||
|
||||
fun getEncodeIntent(context: Context, text: String? = ""): Intent {
|
||||
val intent = Intent(context, MainActivity::class.java)
|
||||
intent.putExtra(ENCODE, text)
|
||||
return intent
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
val fm = supportFragmentManager
|
||||
if (fm != null && fm.backStackEntryCount > 0) {
|
||||
@@ -55,20 +35,56 @@ class MainActivity : AppCompatActivity() {
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
if (state == null) {
|
||||
val intent = getIntent()
|
||||
var fragment: Fragment
|
||||
if (intent != null && intent.hasExtra(ENCODE)) {
|
||||
if (intent?.hasExtra(ENCODE) == true) {
|
||||
fragment = EncodeFragment.newInstance(
|
||||
intent.getStringExtra(ENCODE))
|
||||
} else if (intent != null && intent.hasExtra(DECODE)) {
|
||||
intent.getStringExtra(ENCODE)
|
||||
)
|
||||
} else if (intent?.hasExtra(DECODE) == true) {
|
||||
fragment = DecodeFragment.newInstance(
|
||||
intent.getStringExtra(DECODE),
|
||||
intent.getSerializableExtra(
|
||||
DECODE_FORMAT) as BarcodeFormat)
|
||||
intent.getStringExtra(DECODE),
|
||||
intent.getSerializableExtra(
|
||||
DECODE_FORMAT
|
||||
) as BarcodeFormat
|
||||
)
|
||||
} else {
|
||||
fragment = DecodeFragment()
|
||||
}
|
||||
setFragment(supportFragmentManager, fragment)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ENCODE = "encode"
|
||||
private const val DECODE = "decode"
|
||||
private const val DECODE_FORMAT = "decode_format"
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package de.markusfisch.android.binaryeye.app
|
||||
|
||||
import de.markusfisch.android.binaryeye.view.SystemBarMetrics
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
|
||||
import android.os.Build
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
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,
|
||||
SystemBarMetrics.getStatusBarHeight(
|
||||
activity.resources),
|
||||
0,
|
||||
0)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,104 +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
|
||||
private var odd = true
|
||||
|
||||
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()
|
||||
|
||||
// invert every second frame to also read inverted barcodes
|
||||
if (odd) {
|
||||
yuv2grayScript.forEach_yuv2gray(rgbaAlloc)
|
||||
} else {
|
||||
yuv2grayScript.forEach_yuv2inverted(rgbaAlloc)
|
||||
}
|
||||
odd = odd xor true
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -3,6 +3,6 @@
|
||||
<item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/ic_launcher"/>
|
||||
android:src="@drawable/logo"/>
|
||||
</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>
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,27 +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;
|
||||
}
|
||||
|
||||
uchar4 RS_KERNEL yuv2inverted(uint32_t x, uint32_t y) {
|
||||
uchar Y = 255 - rsGetElementAt_uchar(inYUV, x, y);
|
||||
uchar4 out;
|
||||
out.r = Y;
|
||||
out.g = Y;
|
||||
out.b = Y;
|
||||
out.a = 255;
|
||||
return out;
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.1.51'
|
||||
ext.tools_version = '2.3.3'
|
||||
ext.build_tools_version = '26.0.0'
|
||||
ext.sdk_version = 26
|
||||
ext.kotlin_version = '1.3.10'
|
||||
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,18 +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.5'
|
||||
id 'org.sonarqube' version '2.6.2'
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
|
||||
@@ -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 5
|
||||
versionName '1.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "com.android.support:appcompat-v7:$support_version"
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.markusfisch.android.cameraview"/>
|
||||
@@ -1,421 +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.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CameraView extends FrameLayout {
|
||||
public interface OnCameraListener {
|
||||
void onConfigureParameters(Camera.Parameters parameters);
|
||||
void onCameraError();
|
||||
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()) {
|
||||
case Surface.ROTATION_90:
|
||||
return 90;
|
||||
case Surface.ROTATION_180:
|
||||
return 180;
|
||||
case Surface.ROTATION_270:
|
||||
return 270;
|
||||
case Surface.ROTATION_0:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
public static boolean 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);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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 (CameraView.this.camera != null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// open() may take a while so it shouldn't be
|
||||
// invoked 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) {
|
||||
if (onCameraListener != null &&
|
||||
CameraView.this.camera == null) {
|
||||
onCameraListener.onCameraError();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public Rect calculateFocusRect(float x, float y, int radius) {
|
||||
int cx = Math.round(2000f / viewWidth * x - 1000f);
|
||||
int cy = Math.round(2000f / viewHeight * y - 1000f);
|
||||
return new Rect(
|
||||
Math.max(-1000, cx - radius),
|
||||
Math.max(-1000, cy - radius),
|
||||
Math.min(1000, cx + radius),
|
||||
Math.min(1000, cy + radius));
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
public boolean setFocusArea(Rect area) {
|
||||
if (camera == null || Build.VERSION.SDK_INT <
|
||||
Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
if (parameters.getMaxNumFocusAreas() > 0) {
|
||||
if (area != null) {
|
||||
List<Camera.Area> focusAreas =
|
||||
new ArrayList<Camera.Area>();
|
||||
focusAreas.add(new Camera.Area(area, 1000));
|
||||
parameters.setFocusAreas(focusAreas);
|
||||
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
||||
} else {
|
||||
parameters.setFocusAreas(null);
|
||||
CameraView.setAutoFocus(parameters);
|
||||
}
|
||||
}
|
||||
camera.setParameters(parameters);
|
||||
return true;
|
||||
} catch (RuntimeException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
try {
|
||||
Camera.Parameters parameters = camera.getParameters();
|
||||
parameters.setRotation(frameOrientation);
|
||||
setPreviewSize(parameters, transpose);
|
||||
if (onCameraListener != null) {
|
||||
onCameraListener.onConfigureParameters(parameters);
|
||||
}
|
||||
camera.setParameters(parameters);
|
||||
} catch (RuntimeException e) {
|
||||
if (onCameraListener != null) {
|
||||
onCameraListener.onCameraError();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
if (size != null) {
|
||||
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 = (double) 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
// wait until the surface has dimensions
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
@@ -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 @@
|
||||
include ':app', ':cameraview'
|
||||
include ':app'
|
||||
|
||||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -111,5 +111,8 @@ 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
|
||||
|
||||