Zdjęcia z aparatów cyfrowych są często zapisywane w formacie JPEG ze znacznikiem „orientacji” EXIF. Aby wyświetlać poprawnie, obrazy muszą być obracane / lustrzane w zależności od ustawionej orientacji, ale przeglądarki ignorują tę informację, renderując obraz. Nawet w dużych komercyjnych aplikacjach internetowych obsługa orientacji EXIF może być nierówna 1 . To samo źródło zawiera również ładne podsumowanie 8 różnych orientacji, jakie może mieć JPEG:
Przykładowe obrazy są dostępne pod adresem 4 .
Pytanie brzmi, jak obrócić / odbić obraz po stronie klienta, aby wyświetlał się poprawnie i w razie potrzeby mógł być dalej przetwarzany?
Dostępne są biblioteki JS do analizowania danych EXIF, w tym atrybutu orientacji 2 . Flickr zauważył możliwy problem z wydajnością podczas analizowania dużych obrazów, co wymaga użycia pracowników sieci 3 .
Narzędzia konsoli mogą poprawnie zmienić orientację obrazów 5 . Skrypt PHP rozwiązujący ten problem jest dostępny pod numerem 6
źródło
canvas.toDataURL()
dekodować i zapisywać po stronie serwera.<img>
tag?Transformacja kontekstu Mederr działa doskonale. Jeśli chcesz wyodrębnić orientację, użyj tylko tej funkcji - nie potrzebujesz żadnych bibliotek do odczytu EXIF. Poniżej znajduje się funkcja ponownego ustawiania orientacji w obrazie base64. Oto skrzypce do tego . Przygotowałem też skrzypce z demo ekstrakcji orientacji .
źródło
switch
nie jest potrzebny, ponieważ ta transformacja nic nie robi. Rozważ również użyciesrcOrientation > 4 && srcOrientation < 9
zamiast[5,6,7,8].indexOf(srcOrientation) > -1
, ponieważ jest szybszy i mniej zasobochłonny (zarówno pamięć RAM, jak i procesor). Nie ma potrzeby posiadania tam tablicy. Jest to ważne podczas grupowania wielu obrazów, gdzie liczy się każdy bit. W przeciwnym razie całkiem dobra odpowiedź. Głosowano!indexOf
być w porównaniu z tym, co proponujesz. Uruchomiłem prostą pętlę z iteracjami 10M i była o 1400% szybsza. Fajnie: D Wielkie dzięki!getOrientation
jestem ciekawy, czy jest to wydajne pod względem wydajności.getOrientation
wywołaniafileReader.readAsArrayBuffer
, a następnie wywołujemyURL.createObjectURL
i przekazujemy wynik doresetOrientation
, który ładuje ten adres URL jako obraz. Czy to oznacza, że plik obrazu zostanie „załadowany” / odczytany przez przeglądarkę nie raz, ale dwa razy, czy źle rozumiem?image-orientation: from-image
gdy jest używany.Jeśli
Następnie możesz użyć tych przekształceń, aby obrócić obraz do orientacji 1
Od orientacji:
ctx.transform(1, 0, 0, 1, 0, 0);
ctx.transform(-1, 0, 0, 1, width, 0);
ctx.transform(-1, 0, 0, -1, width, height);
ctx.transform(1, 0, 0, -1, 0, height);
ctx.transform(0, 1, 1, 0, 0, 0);
ctx.transform(0, 1, -1, 0, height, 0);
ctx.transform(0, -1, -1, 0, height, width);
ctx.transform(0, -1, 1, 0, 0, width);
Przed narysowaniem obrazu na ctx
źródło
ok oprócz odpowiedzi @ user3096626 myślę, że będzie bardziej pomocne, jeśli ktoś poda przykład kodu, poniższy przykład pokaże, jak naprawić orientację obrazu pochodzącą z adresu URL (zdalne obrazy):
Rozwiązanie 1: użycie javascript (zalecane)
ponieważ biblioteka load-image nie wyodrębnia tagów exif tylko z obrazów url (plik / blob), użyjemy zarówno bibliotek javascript exif-js, jak i load-image , więc najpierw dodaj te biblioteki do swojej strony w następujący sposób:
Zauważ, że wersja 2.2 exif-js wydaje się mieć problemy, więc użyliśmy 2.1
to w zasadzie to, co zrobimy, jest
a - załaduj obraz za pomocą
window.loadImage()
b - czytaj znaczniki exif używając
window.EXIF.getData()
c - przekonwertuj obraz na płótno i napraw orientację obrazu za pomocą
window.loadImage.scale()
d - umieść płótno w dokumencie
proszę bardzo :)
oczywiście możesz również pobrać obraz jako base64 z obiektu canvas i umieścić go w atrybucie img src, więc używając jQuery możesz to zrobić;)
tutaj jest pełny kod na: github: https://github.com/digital-flowers/loadimage-exif-example
Rozwiązanie 2: Używanie html (hack przeglądarki)
jest bardzo szybki i łatwy hack, większość przeglądarek wyświetla obraz we właściwej orientacji, jeśli obraz jest otwierany bezpośrednio w nowej karcie bez kodu HTML (LOL nie wiem dlaczego), więc w zasadzie możesz wyświetlić obraz za pomocą iframe umieszczając atrybut iframe src bezpośrednio jako adres URL obrazu:
Rozwiązanie 3: Korzystanie z CSS (tylko Firefox i Safari na iOS)
istnieje atrybut css3 do naprawy orientacji obrazu, ale problem, z którym działa tylko na Firefox i Safari / iOS, jest nadal warty uwagi, ponieważ wkrótce będzie dostępny dla wszystkich przeglądarek (informacje o obsłudze przeglądarek z caniuse )
źródło
Dla tych, którzy mają plik z kontrolki wejściowej, nie wiedzą, jaka jest jego orientacja, są nieco leniwi i nie chcą dołączać dużej biblioteki poniżej, kod dostarczony przez @WunderBart połączony z odpowiedzią, do której prowadzi ( https://stackoverflow.com/a/32490603 ), który znajdzie orientację.
które można łatwo nazwać w ten sposób
źródło
image/jpeg
zamiast domyślnegoimage/png
i zmiana rozmiaru obrazu wyjściowego do maksymalnej szerokości (w moim przypadku 400px) spowodowało ogromną różnicę. (działa to dobrze w przypadku miniatur, ale jeśli musisz wyświetlić pełny obraz, sugerowałbym unikanie base64 i po prostu wstrzyknięcie elementu canvas bezpośrednio na stronę ...)Odpowiedź WunderBart była dla mnie najlepsza. Zwróć uwagę, że możesz to znacznie przyspieszyć, jeśli obrazy są często we właściwej kolejności, po prostu najpierw testując orientację i pomijając resztę kodu, jeśli nie jest wymagana rotacja.
Zbieranie wszystkich informacji z wunderbart razem, coś takiego;
źródło
-2
i-1
powrót z,getOrientation
aby nie próbować obracać plików innych niż jpg lub obrazów bez danych dotyczących obrotu.file.slice()
optymalizację, ale prawdziwy wzrost polega na użyciu mniejszych obrazów iimage/jpeg
formatu wyjściowego do tworzenia mniejszych adresów URL danych. (nie ma zauważalnego opóźnienia nawet dla zdjęć 10-megapikselowych.)file.slice()
, ponieważ zapobiegniesz obsłudze źródeł obrazu base64.Ktoś ma jedną wkładkę?
Nie widziałem nikogo wspominającego o
browser-image-compression
bibliotece . Ma funkcję pomocniczą idealną do tego.Stosowanie:
const orientation = await imageCompression.getExifOrientation(file)
Takie przydatne narzędzie również na wiele innych sposobów.
źródło
File
O ile wiem, nie możesz tworzyć obiektów. Następną najlepszą rzeczą byłoby wysłanie obrazu i orientacji na serwer i wykonanie tam manipulacji plikami. Lub możesz wygenerować ciąg base64 za pomocącanvas
itoDataURL
metody.Stworzyłem klasę opakowaną w moduł ES6, który dokładnie to rozwiązuje.
Ma 103 linie, bez zależności i dość ładnie skonstruowane i udokumentowane, co ma być łatwe do modyfikacji / ponownego użycia.
Obsługuje wszystkie 8 możliwych orientacji i jest oparty na obietnicy.
Proszę bardzo, mam nadzieję, że to nadal komuś pomoże: https://gist.github.com/vdavid/3f9b66b60f52204317a4cc0e77097913
źródło
Używam rozwiązania mieszanego (php + css).
Pojemniki są potrzebne do:
div.imgCont2
pojemnik potrzebny do obracania;div.imgCont1
kontener potrzebny do zoomOut -width:150%
;div.imgCont
kontener potrzebny dla pasków przewijania, gdy obraz jest zoomOut..
źródło
Oprócz odpowiedzi @fareed namrouti,
Powinno to być używane, jeśli obraz ma być przeglądany z elementu wejściowego pliku
źródło
Napisałem mały skrypt php, który obraca obraz. Pamiętaj, aby zapisać obraz na korzyść po prostu przelicz go przy każdym żądaniu.
Twoje zdrowie
źródło