2019-pracownia-programowani.../Lookify/app/src/main/java/com/example/lookifyv2/Decode.java

182 lines
7.5 KiB
Java

package com.example.lookifyv2;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.io.File;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import static org.opencv.imgproc.Imgproc.THRESH_BINARY;
public class Decode extends AppCompatActivity {
//Inicjalizacja logów OpenCV.
static final String TAG = "OCVSample::Activity";
String filePath;
Mat matPic;
//OpenCV domyślnie uruchamia się po onCreate co powoduje problemy - zapobiegamy więc temu, zapewniając, by metoda wykorzystująca OpenCV
//uruchamiała się dopiero po jego pomyślnym załadowaniu.
//https://docs.opencv.org/2.4/platforms/android/service/doc/BaseLoaderCallback.html
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS: {
Log.i(TAG, "OpenCV loaded successfully");
decodePic(); //w praktyce tu się uruchamia cała reszta klasy
}
break;
default: {
super.onManagerConnected(status);
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_decode);
}
private void decodePic() {
//Pobieranie adresu pliku przekazanego przez poprzednie activity.
Bundle extras = getIntent().getExtras();
filePath = extras.getString("takenPic");
//Obsługa sytuacji, w której nie ma dostępu do internetu - zrobione zdjęcie zostaje usunięte i następuje przejście do klasy
//odpowiedzialnej za błędy tej części aplikacji.
CheckInternet check = new CheckInternet();
if(!check.isOnline()){
File filefordeletion = new File(filePath);
filefordeletion.delete();
Intent intent_DecodeFail = new Intent(this, DecodeFail.class);
intent_DecodeFail.putExtra("status", "offline");
startActivity(intent_DecodeFail);
finish();
}
//Tworzenie mata ze zdjęcia i usuwanie zdjęcia.
matPic = Imgcodecs.imread(filePath);
File filefordeletion = new File(filePath);
filefordeletion.delete();
Mat matPicG = new Mat();
Mat matPicGB = new Mat();
Mat matPicGBT = new Mat();
//Zdjęcie zamieniane jest na czarno-biały odpowiednik.
//Na podstawie: Amgad Muhammad - OpenCV Android Programming By Example (43% e-booka).
Imgproc.cvtColor(matPic, matPicG, Imgproc.COLOR_RGB2GRAY);
//Usuwanie "noise'u" przy jednoczesnym zachowywaniu ostrych krawędzi za pomocą bilateralnego filtru.
//Na podstawie: Daniel Lelis Baggio - OpenCV 3.0 Computer Vision with Java (s. 52).
Imgproc.bilateralFilter(matPicG, matPicGB, 5, 75, 75);
//Zwiększanie kontrastu za pomocą thresholdu.
//Na podstawie: Salil Kapur, Nisarg Thakkar - Mastering OpenCV Android Application Programming (s. 19).
Imgproc.threshold(matPicGB, matPicGBT, 100, 255, THRESH_BINARY);
//Przygotowywanie mapy bitowej, którą przeskanuje ZXing w poszukiwaniu kodu.
Bitmap bMap = Bitmap.createBitmap(matPicGBT.width(), matPicGBT.height(), Bitmap.Config.ARGB_8888); //Zwykła mapa wbudowana w
//Javę/Android Studio.
Utils.matToBitmap(matPicGBT, bMap);
int[] intArray = new int[bMap.getWidth() * bMap.getHeight()];
bMap.getPixels(intArray, 0, bMap.getWidth(), 0, 0, bMap.getWidth(), bMap.getHeight()); //intArray otrzymuje dane o kolorach
//pikseli.
LuminanceSource source = new RGBLuminanceSource(bMap.getWidth(), bMap.getHeight(), intArray); //Zamienia różne formaty map na jedną
//spójną postać; pozwala wykonać nastepny krok.
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
//Zwiększanie efektywności wykrywania kodów.
Hashtable<DecodeHintType, Object> hints = new Hashtable<>();
List<Object> formats = new ArrayList<>();
formats.add(BarcodeFormat.AZTEC);
formats.add(BarcodeFormat.CODABAR);
formats.add(BarcodeFormat.CODE_39);
formats.add(BarcodeFormat.CODE_93);
formats.add(BarcodeFormat.CODE_128);
formats.add(BarcodeFormat.DATA_MATRIX);
formats.add(BarcodeFormat.EAN_8);
formats.add(BarcodeFormat.EAN_13);
formats.add(BarcodeFormat.ITF);
formats.add(BarcodeFormat.PDF_417);
formats.add(BarcodeFormat.QR_CODE);
formats.add(BarcodeFormat.RSS_14);
formats.add(BarcodeFormat.RSS_EXPANDED);
formats.add(BarcodeFormat.UPC_A);
formats.add(BarcodeFormat.UPC_E);
hints.put(DecodeHintType.POSSIBLE_FORMATS, formats);
hints.put(DecodeHintType.TRY_HARDER, true);
int reminder = 0; //Aplikacja zawsze jest trochę w przód z wykonywaniem kodu nawet po wywołaniu finish(), więc ta zmienna gwarantuje
//brak wyświetlania kodu, jeśli nie został on znaleziony.
//Szukanie kodu na wczytanym zdjęciu i podejmowanie odpowiednich działań w zależności od tego, czy został znaleziony, czy nie.
MultiFormatReader reader = new MultiFormatReader();
String contents = null;
try {
Result result = reader.decode(bitmap, hints);
contents = result.getText();
} catch (NotFoundException e) {
reminder = -1;
e.printStackTrace();
Intent intent_DecodeFail = new Intent(this, DecodeFail.class);
intent_DecodeFail.putExtra("status", "notfound");
startActivity(intent_DecodeFail);
finish();
}
if(reminder == 0) {
Toast.makeText(this, "Zidentyfikowany kod: " + contents,
Toast.LENGTH_SHORT).show();
Intent intent_Results = new Intent(this, Results.class);
intent_Results.putExtra("decodedcode", contents);
startActivity(intent_Results);
finish();
}
}
//Druga część potrzebna do ładowania OpenCV w odpowiednim momencie, czyli gdy aplikacja była zminimalizowana, a teraz zostaje z powrotem
//zmaksymalizowana.
@Override
protected void onResume() {
super.onResume();
if (!OpenCVLoader.initDebug()) {
Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
}