From 5f3680ad20d540f0360c36362f491cd1cdd62a3a Mon Sep 17 00:00:00 2001 From: igor Date: Tue, 25 May 2021 07:43:51 +0600 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B2=D0=BE=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 15 + .idea/.gitignore | 3 + .idea/compiler.xml | 6 + .idea/gradle.xml | 22 + .idea/jarRepositories.xml | 25 + .idea/misc.xml | 9 + .idea/runConfigurations.xml | 10 + app/.gitignore | 1 + app/build.gradle | 41 ++ app/proguard-rules.pro | 21 + .../kz/pomarka/ExampleInstrumentedTest.java | 26 + app/src/main/AndroidManifest.xml | 45 ++ app/src/main/java/kz/pomarka/BarCode.java | 449 ++++++++++++++++++ .../main/java/kz/pomarka/EmailActivity.java | 59 +++ .../main/java/kz/pomarka/MainActivity.java | 99 ++++ app/src/main/java/kz/pomarka/MyDetector.java | 195 ++++++++ .../main/java/kz/pomarka/MySurfaceView.java | 66 +++ .../main/java/kz/pomarka/PhotoActivity.java | 14 + .../main/java/kz/pomarka/ScanActivity.java | 155 ++++++ .../drawable-v24/ic_launcher_foreground.xml | 30 ++ .../res/drawable/ic_launcher_background.xml | 170 +++++++ app/src/main/res/layout/activity_email.xml | 72 +++ app/src/main/res/layout/activity_main.xml | 52 ++ app/src/main/res/layout/activity_photo.xml | 9 + app/src/main/res/layout/activity_scan.xml | 44 ++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3593 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 5339 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2636 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3388 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4926 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 7472 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7909 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 11873 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 10652 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 16570 bytes app/src/main/res/values-night/themes.xml | 16 + app/src/main/res/values/colors.xml | 10 + app/src/main/res/values/dimens.xml | 4 + app/src/main/res/values/strings.xml | 7 + app/src/main/res/values/themes.xml | 16 + app/src/main/res/xml/photos.xml | 6 + .../test/java/kz/pomarka/ExampleUnitTest.java | 17 + build.gradle | 24 + gradle.properties | 19 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 172 +++++++ gradlew.bat | 84 ++++ settings.gradle | 2 + 51 files changed, 2031 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/kz/pomarka/ExampleInstrumentedTest.java create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/kz/pomarka/BarCode.java create mode 100644 app/src/main/java/kz/pomarka/EmailActivity.java create mode 100644 app/src/main/java/kz/pomarka/MainActivity.java create mode 100644 app/src/main/java/kz/pomarka/MyDetector.java create mode 100644 app/src/main/java/kz/pomarka/MySurfaceView.java create mode 100644 app/src/main/java/kz/pomarka/PhotoActivity.java create mode 100644 app/src/main/java/kz/pomarka/ScanActivity.java create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 app/src/main/res/layout/activity_email.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/layout/activity_photo.xml create mode 100644 app/src/main/res/layout/activity_scan.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values-night/themes.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 app/src/main/res/xml/photos.xml create mode 100644 app/src/test/java/kz/pomarka/ExampleUnitTest.java create mode 100644 build.gradle create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..23a89bb --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a5f05cd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..860da66 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..797acea --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..e62f2ee --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,41 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion 30 + buildToolsVersion "29.0.3" + + defaultConfig { + applicationId "kz.pomarka" + minSdkVersion 19 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'com.google.android.material:material:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + testImplementation 'junit:junit:4.+' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + + implementation 'com.google.android.gms:play-services-vision:20.1.2' +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/kz/pomarka/ExampleInstrumentedTest.java b/app/src/androidTest/java/kz/pomarka/ExampleInstrumentedTest.java new file mode 100644 index 0000000..510f17c --- /dev/null +++ b/app/src/androidTest/java/kz/pomarka/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package kz.pomarka; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("kz.pomarka", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2298a4a --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/kz/pomarka/BarCode.java b/app/src/main/java/kz/pomarka/BarCode.java new file mode 100644 index 0000000..a0c009b --- /dev/null +++ b/app/src/main/java/kz/pomarka/BarCode.java @@ -0,0 +1,449 @@ +package kz.shopmaster.shopmasterbarcode; + +import java.util.ArrayList; + +/** + * Created by Igor on 07.12.2017. + * На вход массив float на выход стрих код в виде строки + * Распознавание только для EAN-8 и EAN-13 + */ + +public class BarCode { + + public BarCode() + { + super(); + } + + class BarLine + { + boolean black; //Чёрная то 1 + float width; //Ширина в пикселях (вещественное число так как гребень может быть одинаковой высоты подподрят тогда будет +-0,5 покселя) + boolean del; + int lines; //Ширина в полосках + + public BarLine(boolean black,float width) + { + this.black=black; + this.width=width; + this.del=false; + lines=0; + } + + }; + + //mas это полоска уже просумированных по вертикали данных с рисунка + //Если просумировали около 5 или 10 пикселей то сглаживание не нужно + public String getBarCode(float mas[]) + { + if(mas.length<10) return ""; + + float dUDp=0; //Для среднего в плюсовых значениях + int cntp=0; //Количество плюсовых значений (для среднего) + float dUDm=0; //Для среднего в минусовых значениях + int cntm=0; //Количество минусовых значений (для среднего) + //Преобразуем в таблицу переходов между светлой и тёмной частью + float[] masUD = new float[mas.length]; + for(int i=0;i0) + { + dUDp+=masUD[i]; + cntp++; + } + if(masUD[i]<0) + { + dUDm+=masUD[i]; + cntm++; + } + } + if(cntp<10 || cntm<10) return ""; //Обычно если чёрный экран + masUD[mas.length-1]=0; + dUDp=dUDp/cntp*0.9f; //Плюсовые () + dUDm=dUDm/cntm*0.9f; //Минусовые () + + //Список для записи полосок и их размера + //Если подподрят идут несколько светлых или тёмных пропускаем они должны обязательно чередоваться! + ArrayList zbr = new ArrayList(25); + boolean black=false; //Для чередования начиная с чёрной + int pmin=0; //Предыдущая позиция перехода с белого на чёрный + int pmax=0; //Предыдущая позиция перехода с чёрного на белый + int pCntr=0; //Позиция центра (чёрная полоска) она должна всегда быть на штрих коде + for(int i=0;imas.length/2 && pCntr==0) + pCntr=zbr.size(); + + if(!black) //Ищем начало чёрной так как находимся на белой полоске + { + //Начало чёрной полоски (минусовые значения) + if(masUD[i]dUDm) + break; + if(min>masUD[j]) { + min = masUD[j]; + pmin=j; + } + } + i=j-1; + //Создаю белую полоску + zbr.add(new BarLine(false,pmin-pmax)); + black=!black; + } + + }else + { + //Начало белой полоски (плюсовые значения) + if(masUD[i]>dUDp) //Больше среднего + { + float max=masUD[i]; + pmax=i; + //Ищем плюсовой гребень + int j; + for(j=i+1;j0;i--) + { + if(zbr.get(i).black) + { + pL=i; + if(i-1>=0 && zbr.get(i).width*8pR) + zbr.get(i).del=true; + + //Удяляю элементы + for(int i=0;i zbr2=(ArrayList)zbr.clone(); + + //Сортируем (новый) список по возрастанию ширины (пузырьком) + for(int i=0;izbr2.get(j).width) + { + BarLine tmp=zbr2.get(i); + zbr2.set(i,zbr2.get(j)); + zbr2.set(j,tmp); + } + } + } +*/ + + //Считая что первая линия всегда еденияная следи белых и чёрных вычисляем ширину каждой полоски + float wB=0; + float wW=0; + //Строим массив из 1 и 0 по делению на ширину 1й полоски + int bwb=1; //Предыдущее кол-во линий на 1 полоску для чёрного цвета + int bww=1; //Предыдущее кол-во линий на 1 полоску для белого цвета + float sumB=0,sumW=0; //Для подсчёта среднего + int sumBC=0,sumWC=0; + for(int i=0;iLines->Add("wB = "+FloatToStrF(wB,ffFixed, 8, 3) + " zbr.get(i).lines=" +FloatToStrF(zbr.get(i).lines,ffFixed, 8, 1)); + } + + //Вычисляем новое среднее значение ширины единичной полоски для разных по ширине полосок + sumB+=zbr.get(i).width; + sumBC++; + wB=sumB/(float)sumBC/(float)bwb; + + }else + { + if(wW==0) wW=zbr.get(i).width; //Первая всегда единичная + + zbr.get(i).lines=Math.round(zbr.get(i).width/wW); + if(zbr.get(i).lines==0) + return "";//break; + if(bww!=zbr.get(i).lines) //Так как бывает что увеличение ширины полоски бывает не равномерно + { + sumW=0; + sumWC=0; + bww=zbr.get(i).lines; + //Memo1->Lines->Add("wW = "+FloatToStrF(wW,ffFixed, 8, 3) + " zbr.get(i).lines=" +FloatToStrF(zbr.get(i).lines,ffFixed, 8, 1)); + } + + //Вычисляем новое среднее значение ширины единичной полоски для разных по ширине полосок + sumW+=zbr.get(i).width; + sumWC++; + wW=sumW/(float)sumWC/(float)bww; + } + } + + //Переводим штрих код в строку из 1 и 0 + String str=""; + String ch; + for(int i=0;iLines->Add(str.SubString(spos,7)+" = С n = "+IntToStr(num)); + } + String num13=""; + spos-=5; + if(str.substring(spos,5).equals("01010")) //Центральная двойная полоска + { + for(int i=0;i<5;i++) + { + spos-=7; + if(getOdd(str.substring(spos,7))) //Если не чётное + { + ean13[ean13n]=getNumA(str.substring(spos,7)); + //if(ean13[ean13n]==-1) ean13[ean13n]=getNumB(str.SubString(spos,7)); //Так как некоторые неправильно генерят код... + //if(ean13[ean13n]==-1) ean13[ean13n]=getNumC(str.SubString(spos,7)); //Так как некоторые неправильно генерят код... + ean13n--; + //Memo1->Lines->Add(str.SubString(spos,7)+ " = A n = "+IntToStr(num)); + num13="1"+num13; + }else //Если чётное + { + ean13[ean13n]=getNumB(str.substring(spos,7)); + //if(ean13[ean13n]==-1) ean13[ean13n]=getNumA(str.SubString(spos,7)); //Так как некоторые неправильно генерят код... + //if(ean13[ean13n]==-1) ean13[ean13n]=getNumC(str.SubString(spos,7)); //Так как некоторые неправильно генерят код... + ean13n--; + //Memo1->Lines->Add(str.SubString(spos,7)+ " = B n = "+IntToStr(num)); + num13="0"+num13; + } + } + spos-=7; + ean13[ean13n]=getNumA(str.substring(spos,7)); + ean13n--; + //Memo1->Lines->Add(str.SubString(spos,7) + " = A n = "+IntToStr(num)); + } + spos-=3; + if(str.substring(spos,3).equals("101")) //13й символ находим + { + ean13[ean13n]=getNum13(num13); + ean13n--; + //Memo1->Lines->Add(num13 + " = A n = "+IntToStr(num)); + //for(int i=0;i<13;i++) + //{ + // Memo1->Lines->Add(IntToStr(i)+") "+IntToStr(ean13[i])); + //} + + //Проверяем CRC + /*int s1=0,s2=0; + for(int i=0;i<12;i++) + { + if(i % 2 == 0) + s1+=ean13[i]; + else + s2+=ean13[i]; + } + int crc=(s2*3)+s1; + crc=Math.ceil(crc/10.0f)*10-crc; + Memo1->Lines->Add("crc = "+IntToStr(crc)+" ean13[12]="+IntToStr(ean13[12])); + if(ean13[12]==crc) Memo1->Lines->Add("crc is OK!"); + else Memo1->Lines->Add("CRC is ERROR!");*/ + } + + } + } + + return ""; + } + //--------------------------------------------------------------------------- + //Проверка на нечётность + boolean getOdd(String str) + { + int cnt=0; + for(int i=0;i= Build.VERSION_CODES.M) { + + List list = new ArrayList(); + + /*if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + list.add(Manifest.permission.ACCESS_COARSE_LOCATION); + } + if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + list.add(Manifest.permission.ACCESS_FINE_LOCATION); + } + if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { + list.add(Manifest.permission.CAMERA); + }*/ + if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + list.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); + } + /*if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + list.add(Manifest.permission.READ_EXTERNAL_STORAGE); + }*/ + + if(!list.isEmpty()) + { + ActivityCompat.requestPermissions(MainActivity.this,list.toArray(new String[list.size()]),PERMISSION_REQUEST_CODE); + granted=false; + }else + { + granted=true; + } + }else + { + granted=true; + } + + if(granted) + { + startActivity(new Intent(MainActivity.this, ScanActivity.class)); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) + { + if (requestCode == PERMISSION_REQUEST_CODE) { + + boolean grant=true; + for(int i=0;i { + private Detector mDelegate; + + MyDetector(Detector delegate) { + mDelegate = delegate; + } + + @Override + public SparseArray detect(Frame frame) { + + // *** crop the frame here + int boxx = 300; + int width = frame.getMetadata().getWidth(); + int height = frame.getMetadata().getHeight(); + int ay = (width/2) + (boxx/2); + int by = (width/2) - (boxx/2); + int ax = (height/2) + (boxx/2); + int bx = (height/2) - (boxx/2); + + YuvImage yuvimage=new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, frame.getMetadata().getWidth(), frame.getMetadata().getHeight(), null); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + yuvimage.compressToJpeg(new Rect(by, bx, ay, ax), 100, baos); // Where 100 is the quality of the generated jpeg + byte[] jpegArray = baos.toByteArray(); + Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length); + + Frame outputFrame = new Frame.Builder().setBitmap(bitmap).build(); + return mDelegate.detect(outputFrame); + + +/* int newHeight=100; + + Frame.Metadata metadata = originalFrame.getMetadata(); + int width = metadata.getWidth(); + int height = metadata.getHeight(); + + Log.i(TAG, "Padded image from: " + width + "x" + height + " to " + width + "x" + newHeight); + + ByteBuffer origBuffer = originalFrame.getGrayscaleImageData(); + int origOffset = origBuffer.arrayOffset(); + byte[] origBytes = origBuffer.array(); + + // This can be changed to just .allocate in the future, when Frame supports non-direct + // byte buffers. + ByteBuffer paddedBuffer = ByteBuffer.allocateDirect(width * newHeight); + int paddedOffset = paddedBuffer.arrayOffset(); + byte[] paddedBytes = paddedBuffer.array(); + Arrays.fill(paddedBytes, (byte) 0); + + // Copy the image content from the original, without bothering to fill in the padded bottom + // part. + for (int y = 0; y < newHeight; y++) { + int origStride = origOffset + y * width; + int paddedStride = paddedOffset + y * width; + System.arraycopy(origBytes, origStride, paddedBytes, paddedStride, width); + } + + Frame newFrame = new Frame.Builder() + .setImageData(paddedBuffer, width, newHeight, ImageFormat.NV21) + .setId(metadata.getId()) + .setRotation(metadata.getRotation()) + .setTimestampMillis(metadata.getTimestampMillis()) + .build(); + + //SaveImage(bitmap); + + return mDelegate.detect(newFrame); +*/ + + + +/* + //Какой кусок собираемся вырезать из изображения + int newW=640; + int newH=480; + //Реальные резмеры изображения + Frame.Metadata metadata = frame.getMetadata(); + int width = metadata.getWidth(); + int height = metadata.getHeight(); + //Не вылезаем за реальные размеры + if(newW>width) newW=width; + if(newH>height) newH=height; + + //Исходные данные + ByteBuffer origBuffer = frame.getGrayscaleImageData(); + int origOffset = origBuffer.arrayOffset(); + byte[] origBytes = origBuffer.array(); + + //Куда копируем + ByteBuffer paddedBuffer = ByteBuffer.allocateDirect(newW * newH); //Типа так быстрей + int paddedOffset = paddedBuffer.arrayOffset(); //Где он в памяти + byte[] paddedBytes = paddedBuffer.array(); + Arrays.fill(paddedBytes, (byte) 0); + + int posW=0; //С какой позиции копировать видео по X + int posV=0; //С какой позиции копировать видео по Y + //Копирую данные из первого буфера во второй построчно + for (int y = 0; y < newH; y++) { + int origStride = origOffset + y * width; //Позиция с которой копируем + int paddedStride = paddedOffset + y * newW; //Позиция куда копируем + + System.arraycopy(origBytes, origStride, paddedBytes, paddedStride, width); + } + + Frame newFrame = new Frame.Builder() + .setImageData(paddedBuffer, newW, newH, ImageFormat.NV21) + .setId(metadata.getId()) + .setRotation(metadata.getRotation()) + .setTimestampMillis(metadata.getTimestampMillis()) + .build(); + + + SaveImage(newFrame.getBitmap()); + + return mDelegate.detect(newFrame); +*/ + + +/* + int width = frame.getMetadata().getWidth(); + int height = frame.getMetadata().getHeight(); + int right = (width / 2) + (mBoxHeight / 2); + int left = (width / 2) - (mBoxHeight / 2); + int bottom = (height / 2) + (mBoxWidth / 2); + int top = (height / 2) - (mBoxWidth / 2); + + YuvImage yuvImage = new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, width, height, null); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + yuvImage.compressToJpeg(new Rect(left, top, right, bottom), 100, byteArrayOutputStream); + byte[] jpegArray = byteArrayOutputStream.toByteArray(); + Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length); + + Frame croppedFrame = + new Frame.Builder() + .setBitmap(bitmap) + .setRotation(frame.getMetadata().getRotation()) + .build(); + + return mDelegate.detect(croppedFrame); + // *** crop the frame here + return mDelegate.detect(frame); +*/ + } + + public boolean isOperational() { + return mDelegate.isOperational(); + } + + public boolean setFocus(int id) { + return mDelegate.setFocus(id); + } + + private void SaveImage(Bitmap finalBitmap) { + String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Pictures" + File.separator +"test.jpg"; + File file = new File(path); + try { + FileOutputStream out = new FileOutputStream(file); + finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out); + out.flush(); + out.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/kz/pomarka/MySurfaceView.java b/app/src/main/java/kz/pomarka/MySurfaceView.java new file mode 100644 index 0000000..f0aeba9 --- /dev/null +++ b/app/src/main/java/kz/pomarka/MySurfaceView.java @@ -0,0 +1,66 @@ +package kz.pomarka; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +class MySurface extends SurfaceView { + private Paint mPaint; + private Path mPath; + private Canvas mCanvas; + private SurfaceHolder mSurfaceHolder; + private float mX, mY, newX, newY; + + public MySurface(Context context) { + super(context); + initi(context); + } + + private void initi(Context context) { + mSurfaceHolder = getHolder(); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setTextSize(12); + mPaint.setColor(Color.RED); + + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + + switch (event.getAction()) { + + case MotionEvent.ACTION_DOWN: + mX = event.getX(); + mY = event.getY(); + break; + case MotionEvent.ACTION_MOVE: + newX = event.getX(); + newY = event.getY(); + break; + default: + // Do nothing + } + drawRect(); + invalidate(); + return true; + } + + private void drawRect() { + mPath = new Path(); + mPath.moveTo(mX, mY); + mCanvas = mSurfaceHolder.lockCanvas(); + mCanvas.save(); + mPath.addRect(mX, mY, newX, newY, Path.Direction.CCW); + mCanvas.drawPath(mPath, mPaint); + mCanvas.restore(); + mSurfaceHolder.unlockCanvasAndPost(mCanvas); + mX = newX; + mY = newY; + } + +} \ No newline at end of file diff --git a/app/src/main/java/kz/pomarka/PhotoActivity.java b/app/src/main/java/kz/pomarka/PhotoActivity.java new file mode 100644 index 0000000..5ae78f4 --- /dev/null +++ b/app/src/main/java/kz/pomarka/PhotoActivity.java @@ -0,0 +1,14 @@ +package kz.pomarka; + +import androidx.appcompat.app.AppCompatActivity; + +import android.os.Bundle; + +public class PhotoActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_photo); + } +} \ No newline at end of file diff --git a/app/src/main/java/kz/pomarka/ScanActivity.java b/app/src/main/java/kz/pomarka/ScanActivity.java new file mode 100644 index 0000000..2d0ca29 --- /dev/null +++ b/app/src/main/java/kz/pomarka/ScanActivity.java @@ -0,0 +1,155 @@ +package kz.pomarka; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Bundle; +import android.util.SparseArray; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.vision.CameraSource; +import com.google.android.gms.vision.Detector; +import com.google.android.gms.vision.barcode.Barcode; +import com.google.android.gms.vision.barcode.BarcodeDetector; + +import java.io.IOException; + +public class ScanActivity extends AppCompatActivity { + + SurfaceView surfaceView; + SurfaceView surfaceViewT; + TextView txtBarcodeValue; + private Detector barcodeDetector; + private CameraSource cameraSource; + private static final int REQUEST_CAMERA_PERMISSION = 201; + Button btnAction; + String intentData = ""; + boolean isEmail = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_scan); + + initViews(); + + } + + private void initViews() { + txtBarcodeValue = findViewById(R.id.txtBarcodeValue); + surfaceView = findViewById(R.id.surfaceView); + surfaceView.setZOrderOnTop(false); //CODE TO SET VIDEO VIEW TO BACK + surfaceViewT = findViewById(R.id.surfaceViewT); + surfaceViewT.setZOrderOnTop(true); + + btnAction = findViewById(R.id.btnAction); + btnAction.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (intentData.length() > 0) { + if (isEmail) + startActivity(new Intent(ScanActivity.this, EmailActivity.class).putExtra("email_address", intentData)); + else { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(intentData))); + } + } + } + }); + } + + private void initialiseDetectorsAndSources() { + + Toast.makeText(getApplicationContext(), "Barcode scanner started", Toast.LENGTH_SHORT).show(); + barcodeDetector = new BarcodeDetector.Builder(this) + .setBarcodeFormats(Barcode.ALL_FORMATS) + .build(); + + barcodeDetector = new MyDetector(barcodeDetector); + + cameraSource = new CameraSource.Builder(this, barcodeDetector) + .setRequestedPreviewSize(1920, 1080) + .setAutoFocusEnabled(true) //you should add this feature + .build(); + + surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { + @Override + public void surfaceCreated(SurfaceHolder holder) { + try { + if (ActivityCompat.checkSelfPermission(ScanActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { + cameraSource.start(surfaceView.getHolder()); + } else { + ActivityCompat.requestPermissions(ScanActivity.this, new + String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + cameraSource.stop(); + } + }); + + + barcodeDetector.setProcessor(new Detector.Processor() { + @Override + public void release() { + Toast.makeText(getApplicationContext(), "Для предотвращения утечки памяти сканер штрих-кода остановлен", Toast.LENGTH_SHORT).show(); + } + + @Override + public void receiveDetections(Detector.Detections detections) { + final SparseArray barcodes = detections.getDetectedItems(); + if (barcodes.size() != 0) { + txtBarcodeValue.post(new Runnable() { + @Override + public void run() { + + if (barcodes.valueAt(0).email != null) { + txtBarcodeValue.removeCallbacks(null); + intentData = barcodes.valueAt(0).email.address; + txtBarcodeValue.setText(intentData); + isEmail = true; + btnAction.setText("ADD CONTENT TO THE MAIL"); + } else { + isEmail = false; + btnAction.setText("LAUNCH URL"); + intentData = barcodes.valueAt(0).displayValue; + txtBarcodeValue.setText(intentData); + } + } + }); + } + } + }); + } + + @Override + protected void onPause() { + super.onPause(); + cameraSource.release(); + } + + @Override + protected void onResume() { + super.onResume(); + initialiseDetectorsAndSources(); + } + +} \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_email.xml b/app/src/main/res/layout/activity_email.xml new file mode 100644 index 0000000..648aabd --- /dev/null +++ b/app/src/main/res/layout/activity_email.xml @@ -0,0 +1,72 @@ + + + +