Przechwytuję obraz i ustawiam go do widoku obrazu.
public void captureImage() {
Intent intentCamera = new Intent("android.media.action.IMAGE_CAPTURE");
File filePhoto = new File(Environment.getExternalStorageDirectory(), "Pic.jpg");
imageUri = Uri.fromFile(filePhoto);
MyApplicationGlobal.imageUri = imageUri.getPath();
intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intentCamera, TAKE_PICTURE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intentFromCamera) {
super.onActivityResult(requestCode, resultCode, intentFromCamera);
if (resultCode == RESULT_OK && requestCode == TAKE_PICTURE) {
if (intentFromCamera != null) {
Bundle extras = intentFromCamera.getExtras();
if (extras.containsKey("data")) {
bitmap = (Bitmap) extras.get("data");
}
else {
bitmap = getBitmapFromUri();
}
}
else {
bitmap = getBitmapFromUri();
}
// imageView.setImageBitmap(bitmap);
imageView.setImageURI(imageUri);
}
else {
}
}
public Bitmap getBitmapFromUri() {
getContentResolver().notifyChange(imageUri, null);
ContentResolver cr = getContentResolver();
Bitmap bitmap;
try {
bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, imageUri);
return bitmap;
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
Problem w tym, że obraz na niektórych urządzeniach za każdym razem, gdy się obraca. Na przykład na urządzeniu Samsung działa dobrze, ale na Sony Xperia obraz jest obracany o 90 stopni, a na Toshiba Thrive (tablet) o 180 stopni.
Odpowiedzi:
Większość aparatów telefonicznych jest ustawiona poziomo, co oznacza, że jeśli zrobisz zdjęcie portretowe, powstałe zdjęcia zostaną obrócone o 90 stopni. W takim przypadku oprogramowanie aparatu powinno wypełnić dane Exif orientacją, w której zdjęcie powinno zostać wyświetlone.
Zwróć uwagę, że poniższe rozwiązanie zależy od producenta oprogramowania / urządzenia wypełniającego dane Exif, więc będzie działać w większości przypadków, ale nie jest to rozwiązanie w 100% niezawodne.
Oto
rotateImage
metoda:źródło
exif.getAttributeInt
użyciaExifInterface.ORIENTATION_UNDEFINED
jest prawie taka sama, ponieważ drugi parametr jest wartością domyślną na wypadek, gdyby funkcja nie podała tej wartości.Łącząc Jason Robinson „s odpowiedź z Felix ” s odpowiedź i wypełnienie brakujących części, tutaj jest ostateczna kompletne rozwiązanie tego problemu , który będzie wykonać następujące czynności po przetestowaniu go na Android Android 4.1 ( Jelly Bean ), Android 4.4 ( KitKat ) i Android 5.0 ( Lollipop ).
Kroki
Zmniejsz obraz, jeśli był większy niż 1024x1024.
Obróć obraz do właściwej orientacji tylko wtedy, gdy został obrócony o 90, 180 lub 270 stopni.
Przetwarzaj obrócony obraz do celów pamięci.
Oto część kodu:
Wywołaj następującą metodę z bieżącym
Context
i obrazemURI
, który chcesz naprawićOto
CalculateInSampleSize
metoda z wcześniej wspomnianego źródła :Następnie pojawia się metoda, która sprawdzi bieżącą orientację obrazu w celu ustalenia kąta obrotu
Wreszcie sama metoda rotacji
-Nie zapomnij zagłosować na odpowiedzi tych facetów za ich wysiłki i Shirish Herwade, który zadał to pomocne pytanie.
źródło
Łatwo jest wykryć orientację obrazu i zastąpić mapę bitową za pomocą:
Aby uniknąć braku pamięci w przypadku dużych obrazów, zalecamy przeskalowanie obrazu za pomocą:
Nie można użyć ExifInterface do uzyskania orientacji, ponieważ problem z systemem operacyjnym Android: https://code.google.com/p/android/issues/detail?id=19268
I oto jest
calculateInSampleSize
źródło
Rozwiązanie jednoliniowe:
Lub
Spowoduje to automatyczne wykrycie obrotu i ustawienie obrazu we właściwej orientacji
Picasso to bardzo potężna biblioteka do obsługi obrazów w Twojej aplikacji obejmuje: Złożone transformacje obrazów przy minimalnym zużyciu pamięci.
źródło
Spędziłem dużo czasu na szukaniu rozwiązania tego problemu. I w końcu udało się to zrobić. Nie zapomnij głosować na odpowiedź Jason Robinson, ponieważ moja jest oparta na jego.
Po pierwsze, powinieneś wiedzieć, że od Androida 7.0 musimy używać
FileProvider
i coś o nazwieContentUri
, w przeciwnym razie pojawi się irytujący błąd przy próbie wywołania twojegoIntent
. To jest przykładowy kod:Metoda
getUriFromPath(Context, String)
oparta na utworzonej przez użytkownika wersji AndroidaFileUri (file://...)
lubContentUri (content://...)
istnieje:Po
onActivityResult
tym, jak to złapieszuri
wykryciu, obraz jest zapisywany przez kamerę, ale teraz musisz wykryć obrót kamery, tutaj użyjemy zmodyfikowanej odpowiedzi @Jason Robinson:Najpierw musimy stworzyć
ExifInterface
na podstawieUri
Powyższy kod można uprościć, ale chcę pokazać wszystko. Dlatego
FileUri
możemy tworzyćExifInterface
na podstawieString path
, aleContentUri
nie możemy, Android nie obsługuje tego.W takim przypadku musimy użyć innego konstruktora opartego na
InputStream
. Pamiętaj, że ten konstruktor nie jest domyślnie dostępny, musisz dodać dodatkową bibliotekę:Teraz możemy użyć
getExifInterface
metody, aby uzyskać nasz kąt:Teraz masz Kąt, aby poprawnie obrócić obraz :).
źródło
Activity_main.xml
MainActivity.java
źródło
Możesz po prostu odczytać orientację czujnika aparatu, jak wskazano w Google w dokumentacji: https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html
Przykładowy kod:
źródło
Jason Robinson za odpowiedź i Sami Eltamawy odpowiedź są doskonałe.
Tylko ulepszenie, aby ukończyć podejście, powinieneś użyć kompatybilnego ExifInterface.
com.android.support:exifinterface:${lastLibVersion}
Będziesz mógł utworzyć instancję ExifInterface (API pior <24) przy pomocy
InputStream
(zContentResolver
) zamiast ścieżek uri, unikając „wyjątków Nie znaleziono pliku”https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html
źródło
Zwykle zaleca się rozwiązanie problemu z interfejsem Exif , jak sugerował @Jason Robinson. Jeśli to podejście nie działa, możesz spróbować sprawdzić orientację ostatnio wykonanego zdjęcia ...
źródło
Niestety powyższa odpowiedź @ jason-robinson nie zadziałała dla mnie.
Chociaż funkcja obracania działa idealnie:
Musiałem wykonać następujące czynności, aby uzyskać orientację, ponieważ orientacja Exif zawsze wynosiła 0
źródło
Lepiej spróbuj zrobić zdjęcie w określonej orientacji.
W celu uzyskania najlepszych rezultatów podaj orientację poziomą podczas aktywności kamery.
źródło
Jeśli ktoś ma problemy z uzyskaniem orientacji
ExifInterface
na Androidzie 4.4 (KitKat), może to być spowodowane nieprawidłową ścieżką uzyskaną z URI. Zobacz rozwiązanie propoergetPath
w pytaniu Przepełnienie stosu Uzyskaj prawdziwą ścieżkę z URI, nowej platformy dostępu do pamięci dla systemu KitKatźródło
Znajdź poniżej link to rozwiązanie jest najlepsze https://www.samieltamawy.com/how-to-fix-the-camera-intent-rotated-image-in-android/
źródło
Wybrana odpowiedź wykorzystuje najczęściej stosowaną metodę odpowiedzi na to i podobne pytania. Jednak nie działa zarówno z aparatami przednimi, jak i tylnymi w Samsungu. Dla tych, którzy szukają rozwiązania, które działa zarówno na przednich, jak i tylnych aparatach dla Samsunga i innych głównych producentów, odpowiedź nvhausid jest niesamowita:
https://stackoverflow.com/a/18915443/6080472
Dla tych, którzy nie chcą klikać, odpowiednią magią jest użycie CameraInfo zamiast polegania na EXIF.
Pełny kod w linku.
źródło
To może być oczywiste, ale zawsze pamiętaj, że możesz poradzić sobie z niektórymi z tych problemów z obsługą obrazów na serwerze. Użyłem odpowiedzi takich jak te zawarte w tym wątku, aby obsłużyć natychmiastowe wyświetlanie obrazu. Jednak moja aplikacja wymaga przechowywania obrazów na serwerze (jest to prawdopodobnie powszechny wymóg, jeśli chcesz, aby obraz trwał, gdy użytkownicy przełączają telefony).
Rozwiązania zawarte w wielu wątkach dotyczących tego tematu nie omawiają braku trwałości danych EXIF, które nie przetrwają kompresji obrazu bitmapy, co oznacza, że będziesz musiał obrócić obraz za każdym razem, gdy serwer go załaduje. Alternatywnie możesz wysłać dane orientacyjne EXIF na serwer, a następnie obrócić tam obraz, jeśli to konieczne.
Łatwiej było mi stworzyć trwałe rozwiązanie na serwerze, ponieważ nie musiałem się martwić o tajne ścieżki plików Androida.
źródło
Najprostsze rozwiązanie tego problemu:
Zapisuję obraz w formacie jpg.
źródło
Oto
Xamarin.Android
wersja:Od @Jason Robinsona odpowiedź :
Następnie
calculateInSampleSize
metoda:Od @Sami Eltamawy za odpowiedź :
źródło
Jeśli używasz Fresco, możesz użyć tego -
To automatycznie obraca obrazy na podstawie danych Exif.
Źródło: https://frescolib.org/docs/rotation.html
źródło
Poniższy kod działał ze mną, pobrałem bitmapę z plikuUri i w razie potrzeby dokonałem naprawy rotacji:
źródło
Uzyskaj odpowiedź na ten problem bez użycia ExifInterface . Możemy uzyskać obrót kamery przednią lub tylną, niezależnie od tego, którego używasz, a następnie podczas tworzenia mapy bitowej możemy obrócić mapę bitową za pomocą Matrix.postRotate (stopień)
Po obliczeniu obrotu możesz obrócić bitmapę jak poniżej:
Herare bm powinna być twoją bitmapą.
Jeśli chcesz poznać obrót kamery przedniej, po prostu zmień Camera.CameraInfo.CAMERA_FACING_BACK na Camera.CameraInfo.CAMERA_FACING_FRONT powyżej.
Mam nadzieję, że to pomoże.
źródło
Stworzyłem funkcję rozszerzenia Kotlin, która upraszcza obsługę programistów Kotlin na podstawie odpowiedzi @Jason Robinson. Mam nadzieję, że to pomoże.
źródło
Istnieje prostsze polecenie, aby naprawić ten błąd.
Po prostu dodaj po yourImageView.setBitmap (bitmap); this yourImageView.setRotation (90);
To naprawiło moje. Mam nadzieję, że to pomoże !
źródło
to zadziałało dla mnie
źródło