Orientacja Exif po stronie klienta JS: Obracanie i lustrzane odbicie obrazów JPEG


154

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:

Podsumowanie orientacji EXIF

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

Odpowiedzi:


145

Projekt JavaScript-Load-Image na githubie zapewnia kompletne rozwiązanie problemu orientacji EXIF, poprawnie obracając / odbierając lustrzane odbicie obrazów dla wszystkich 8 orientacji exif. Zobacz demo online z orientacją javascript exif

Obraz jest rysowany na płótnie HTML5. Jego poprawne renderowanie jest implementowane w js / load-image-Orientation.js poprzez operacje na płótnie.

Mam nadzieję, że to zaoszczędzi komuś trochę czasu i uczy wyszukiwarki o tym klejnocie open source :)


1
Korzystam z tej biblioteki, ale ostatnio zepsuła się na iOS 8.3, gdzie potrzebuję jej najbardziej do pracy :(
— Gordon niedz.

2
Naprawdę staram się zobaczyć, jak to jest pomocne. Bawię się tym, próbując się tego nauczyć, więc mogę albo przeanalizować stronę i obrócić obrazy, gdy trzeba je obrócić, albo wykryć orientację i obrócić plik (w jakiś sposób) przed wysłaniem go. Demo też nie. Po prostu pobiera plik z pliku wejściowego i wyświetla go we właściwy sposób, kiedy jest to przydatne w prawdziwym świecie? Kiedy analizuję moją stronę i przesyłam adresy URL z tagów obrazu do biblioteki loadImage, nie ma danych exif, więc nie mogę tego zrobić. Do przesłania zwraca obiekt płótna, więc nie mogę wysłać go na serwer ani nic.
— igneozaur

3
@igneosaur: możesz wysyłać dane zakodowane w base64 do serwera za pomocą, canvas.toDataURL()dekodować i zapisywać po stronie serwera.
— br4nnigan

1
zamiast używać projektu load-image, możesz użyć części jego kodu do wypalenia własnego - po prostu zajrzyj na github.com/blueimp/JavaScript-Load-Image/blob/master/js/… .
— Andy Lorenz

1
Czy istnieje sposób, aby płótno, które tworzy ta biblioteka, było responsywne jak zwykły <img>tag?
— Erik Berkun-Drevnig

103

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 .

function resetOrientation(srcBase64, srcOrientation, callback) {
  var img = new Image();    

  img.onload = function() {
    var width = img.width,
        height = img.height,
        canvas = document.createElement('canvas'),
        ctx = canvas.getContext("2d");

    // set proper canvas dimensions before transform & export
    if (4 < srcOrientation && srcOrientation < 9) {
      canvas.width = height;
      canvas.height = width;
    } else {
      canvas.width = width;
      canvas.height = height;
    }

    // transform context before drawing image
    switch (srcOrientation) {
      case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
      case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
      case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
      case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
      case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
      case 7: ctx.transform(0, -1, -1, 0, height, width); break;
      case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
      default: break;
    }

    // draw image
    ctx.drawImage(img, 0, 0);

    // export base64
    callback(canvas.toDataURL());
  };

  img.src = srcBase64;
};

7
Domyślny przypadek w orientacji switchnie jest potrzebny, ponieważ ta transformacja nic nie robi. Rozważ również użycie srcOrientation > 4 && srcOrientation < 9zamiast [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!
— Ryan Casas

4
@RyanCasas Nie zdawałem sobie sprawy, jak ciężkie może indexOfbyć 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!
— WunderBart

1
Użyłem tej odpowiedzi w Android WebView i okazało się, że jest kilka urządzeń z Androidem, które nie obsługują WebGL w WebView (patrz bugs.chromium.org/p/chromium/issues/detail?id=555116 ) obrót może zająć bardzo dużo czasu na takich urządzeniach w zależności od rozmiaru obrazu.
— ndreisg

1
W przypadku użycia z przywołanym materiałem getOrientationjestem ciekawy, czy jest to wydajne pod względem wydajności. getOrientationwywołania fileReader.readAsArrayBuffer, a następnie wywołujemy URL.createObjectURLi przekazujemy wynik do resetOrientation, 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?
— Oliver Joseph Ash

1
Co zrobić z przeglądarkami, w których orientacja będzie już przestrzegana? Uważam, że tak jest w przypadku iOS Safari i przeglądarek obsługujących CSS, image-orientation: from-imagegdy jest używany.
— Oliver Joseph Ash

40

Jeśli

width = img.width;
height = img.height;
var ctx = canvas.getContext('2d');

Następnie możesz użyć tych przekształceń, aby obrócić obraz do orientacji 1

Od orientacji:

  1. ctx.transform(1, 0, 0, 1, 0, 0);
  2. ctx.transform(-1, 0, 0, 1, width, 0);
  3. ctx.transform(-1, 0, 0, -1, width, height);
  4. ctx.transform(1, 0, 0, -1, 0, height);
  5. ctx.transform(0, 1, 1, 0, 0, 0);
  6. ctx.transform(0, 1, -1, 0, height, 0);
  7. ctx.transform(0, -1, -1, 0, height, width);
  8. ctx.transform(0, -1, 1, 0, 0, width);

Przed narysowaniem obrazu na ctx


58
co się tu w ogóle dzieje?
— Muhammad Umer

1
Dzięki temu wystarczy znać orientację (np. Przez EXIF), a następnie obracać w razie potrzeby. Połowa tego, czego szukam.
— Brenden

2
te transformacje nie zadziałały dla mnie - zamiast tego użyłem kodu z projektu load-image na github.com/blueimp/JavaScript-Load-Image/blob/master/js/ ... aby uzyskać to, co uważam za dobrze sprawdzony kod która używa operacji tłumaczenia i obracania w kontekście płótna oraz zamiany szerokości / wysokości. Dał mi 100% wyników po wielu godzinach eksperymentowania z innymi próbami transformacji itp.
— Andy Lorenz

1
Dlaczego ma to znaczenie, kiedy rysujesz obraz na ctx? Nie możesz obrócić płótna po narysowaniu na nim obrazu?
— AlxVallejo,

Obrót dla orientacji 8 działa u mnie w ten sposób: ctx.transform (0, -1, 1, 0, 0, height);
— Giorgio Barchiesi

24

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)

  1. 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:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.1.0/exif.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image-scale.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/blueimp-load-image/2.12.2/load-image-orientation.min.js"></script>

    Zauważ, że wersja 2.2 exif-js wydaje się mieć problemy, więc użyliśmy 2.1

  2. 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 :)

window.loadImage("/your-image.jpg", function (img) {
  if (img.type === "error") {
    console.log("couldn't load image:", img);
  } else {
    window.EXIF.getData(img, function () {
        var orientation = EXIF.getTag(this, "Orientation");
        var canvas = window.loadImage.scale(img, {orientation: orientation || 0, canvas: true});
        document.getElementById("container").appendChild(canvas); 
        // or using jquery $("#container").append(canvas);

    });
  }
});

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ć;)

$("#my-image").attr("src",canvas.toDataURL());

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:

<iframe src="/my-image.jpg"></iframe>

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 )

img {
   image-orientation: from-image;
}

Rozwiązanie 1 nie działa dla mnie. Zwraca okno.loadImage jest niezdefiniowane
— Perry,

Stało się tak, jeśli nie uwzględniono bibliotek, o których wspominam w kroku 1
— Fareed Alnamrouti

Włączyłem biblioteki. Podoba mi się prostota twojego przykładu, ale ciągle otrzymuję ten komunikat o błędzie.
— Perry,

1
wygląda na to, że exif-js został uszkodzony, sprawdź moją edycję Dodałem również pełny kod na github: github.com/digital-flowers/loadimage-exif-example
— Fareed Alnamrouti

1
ok sprawdź projekt na githubie jest nowy plik "upload.html", nie ma za co :)
— Fareed Alnamrouti

10

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ę.

function getDataUrl(file, callback2) {
        var callback = function (srcOrientation) {
            var reader2 = new FileReader();
            reader2.onload = function (e) {
                var srcBase64 = e.target.result;
                var img = new Image();

                img.onload = function () {
                    var width = img.width,
                        height = img.height,
                        canvas = document.createElement('canvas'),
                        ctx = canvas.getContext("2d");

                    // set proper canvas dimensions before transform & export
                    if (4 < srcOrientation && srcOrientation < 9) {
                        canvas.width = height;
                        canvas.height = width;
                    } else {
                        canvas.width = width;
                        canvas.height = height;
                    }

                    // transform context before drawing image
                    switch (srcOrientation) {
                        case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
                        case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
                        case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
                        case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
                        case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
                        case 7: ctx.transform(0, -1, -1, 0, height, width); break;
                        case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
                        default: break;
                    }

                    // draw image
                    ctx.drawImage(img, 0, 0);

                    // export base64
                    callback2(canvas.toDataURL());
                };

                img.src = srcBase64;
            }

            reader2.readAsDataURL(file);
        }

        var reader = new FileReader();
        reader.onload = function (e) {

            var view = new DataView(e.target.result);
            if (view.getUint16(0, false) != 0xFFD8) return callback(-2);
            var length = view.byteLength, offset = 2;
            while (offset < length) {
                var marker = view.getUint16(offset, false);
                offset += 2;
                if (marker == 0xFFE1) {
                    if (view.getUint32(offset += 2, false) != 0x45786966) return callback(-1);
                    var little = view.getUint16(offset += 6, false) == 0x4949;
                    offset += view.getUint32(offset + 4, little);
                    var tags = view.getUint16(offset, little);
                    offset += 2;
                    for (var i = 0; i < tags; i++)
                        if (view.getUint16(offset + (i * 12), little) == 0x0112)
                            return callback(view.getUint16(offset + (i * 12) + 8, little));
                }
                else if ((marker & 0xFF00) != 0xFF00) break;
                else offset += view.getUint16(offset, false);
            }
            return callback(-1);
        };
        reader.readAsArrayBuffer(file);
    }

które można łatwo nazwać w ten sposób

getDataUrl(input.files[0], function (imgBase64) {
      vm.user.BioPhoto = imgBase64;
});

2
Dziękuję po ponad 2-godzinnym wyszukiwaniu w google znajduję odpowiednie rozwiązanie.
— Pan Trieu,

2
dlaczego ktoś byłby leniwy, gdyby wolał dużo lżejsze rozwiązanie?
— dewd

4
Przeniesiono do Typescript i zoptymalizowano od około 4 sekund do ~ 20 milisekund. Kodowanie Base64 było wąskim gardłem - użycie image/jpegzamiast domyślnego image/pngi 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ę ...)
— mindplay.dk

8

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;

var handleTakePhoto = function () {
    let fileInput: HTMLInputElement = <HTMLInputElement>document.getElementById('photoInput');
    fileInput.addEventListener('change', (e: any) => handleInputUpdated(fileInput, e.target.files));
    fileInput.click();
}

var handleInputUpdated = function (fileInput: HTMLInputElement, fileList) {
    let file = null;

    if (fileList.length > 0 && fileList[0].type.match(/^image\//)) {
        isLoading(true);
        file = fileList[0];
        getOrientation(file, function (orientation) {
            if (orientation == 1) {
                imageBinary(URL.createObjectURL(file));
                isLoading(false);
            }
            else 
            {
                resetOrientation(URL.createObjectURL(file), orientation, function (resetBase64Image) {
                    imageBinary(resetBase64Image);
                    isLoading(false);
                });
            }
        });
    }

    fileInput.removeEventListener('change');
}


// from http://stackoverflow.com/a/32490603
export function getOrientation(file, callback) {
    var reader = new FileReader();

    reader.onload = function (event: any) {
        var view = new DataView(event.target.result);

        if (view.getUint16(0, false) != 0xFFD8) return callback(-2);

        var length = view.byteLength,
            offset = 2;

        while (offset < length) {
            var marker = view.getUint16(offset, false);
            offset += 2;

            if (marker == 0xFFE1) {
                if (view.getUint32(offset += 2, false) != 0x45786966) {
                    return callback(-1);
                }
                var little = view.getUint16(offset += 6, false) == 0x4949;
                offset += view.getUint32(offset + 4, little);
                var tags = view.getUint16(offset, little);
                offset += 2;

                for (var i = 0; i < tags; i++)
                    if (view.getUint16(offset + (i * 12), little) == 0x0112)
                        return callback(view.getUint16(offset + (i * 12) + 8, little));
            }
            else if ((marker & 0xFF00) != 0xFF00) break;
            else offset += view.getUint16(offset, false);
        }
        return callback(-1);
    };

    reader.readAsArrayBuffer(file.slice(0, 64 * 1024));
};

export function resetOrientation(srcBase64, srcOrientation, callback) {
    var img = new Image();

    img.onload = function () {
        var width = img.width,
            height = img.height,
            canvas = document.createElement('canvas'),
            ctx = canvas.getContext("2d");

        // set proper canvas dimensions before transform & export
        if (4 < srcOrientation && srcOrientation < 9) {
            canvas.width = height;
            canvas.height = width;
        } else {
            canvas.width = width;
            canvas.height = height;
        }

        // transform context before drawing image
        switch (srcOrientation) {
            case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
            case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
            case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
            case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
            case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
            case 7: ctx.transform(0, -1, -1, 0, height, width); break;
            case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
            default: break;
        }

        // draw image
        ctx.drawImage(img, 0, 0);

        // export base64
        callback(canvas.toDataURL());
    };

    img.src = srcBase64;
}

1
Świetne podejście. Powinieneś także rozważyć obsługę -2i -1powrót z, getOrientationaby nie próbować obracać plików innych niż jpg lub obrazów bez danych dotyczących obrotu.
— Steven Lambert

Zrobiłem więcej optymalizacji, zobacz mój komentarz powyżej - właśnie dodałem również twoją file.slice()optymalizację, ale prawdziwy wzrost polega na użyciu mniejszych obrazów i image/jpegformatu wyjściowego do tworzenia mniejszych adresów URL danych. (nie ma zauważalnego opóźnienia nawet dla zdjęć 10-megapikselowych.)
— mindplay.dk

Ostrożnie file.slice(), ponieważ zapobiegniesz obsłudze źródeł obrazu base64.
— Mark

Dziękuję - chcesz udostępnić zmianę dla alternatywy?
— statler

7

Ktoś ma jedną wkładkę?

Nie widziałem nikogo wspominającego o browser-image-compressionbibliotece . Ma funkcję pomocniczą idealną do tego.

Stosowanie: const orientation = await imageCompression.getExifOrientation(file)

Takie przydatne narzędzie również na wiele innych sposobów.


To daje orientację. Ale jak przy użyciu tych informacji utworzyć nowy obiekt pliku .jpg po stronie klienta?
— masterxilo

FileO 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ą canvasi toDataURLmetody.
— gilbert-v

1
Nie, możesz stworzyć obiekt File z Bloba. Plik Plik (części tablicy, nazwa pliku ciągu, właściwości BlobPropertyBag); developer.mozilla.org/de/docs/Web/API/File
— masterxilo

2
Złota naklejka! @masterxilo
— gilbert-v

2
To działało świetnie dla mnie! Od 2 dni zmagałem się z orientacjami! Wszystkie opublikowane oświadczenia dotyczące przełączania transformacji z jakiegoś powodu nie obsługiwałyby zdjęć portretowych z mojego telefonu, byłyby czarne paski. Prawdopodobnie dlatego, że próbowałem kompresować i obracać w tym samym czasie.
— cjd82187


1

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.

.

<?php
    $image_url = 'your image url.jpg';
    $exif = @exif_read_data($image_url,0,true);
    $orientation = @$exif['IFD0']['Orientation'];
?>

<style>
.imgCont{
    width:100%;
    overflow:auto;
}
.imgCont2[data-orientation="8"]{
    transform:rotate(270deg);
    margin:15% 0;
}
.imgCont2[data-orientation="6"]{
    transform:rotate(90deg);
    margin:15% 0;
}
.imgCont2[data-orientation="3"]{
    transform:rotate(180deg);
}
img{
    width:100%;
}
</style>

<div class="imgCont">
  <div class="imgCont1">
    <div class="imgCont2" data-orientation="<?php echo($orientation) ?>">
      <img src="<?php echo($image_url) ?>">
    </div>
  </div>
</div>

Dzięki, to wydaje się być najlepszym rozwiązaniem, mimo wszystko na moje potrzeby. Nie ma potrzeby korzystania z zewnętrznych bibliotek i długich bloków niepotrzebnego kodu. Po prostu określ orientację z exif za pomocą php, wyślij go do widoku i użyj go do uruchomienia klas CSS, które obracają się o odpowiednią liczbę stopni. Ładnie i czysto! Edycja: spowoduje to nadmierne obrócenie obrazów w przeglądarkach, które faktycznie odczytują dane exif i odpowiednio się obrócą. AKA, to naprawi problem na komputerze, ale utworzy nowy na iOS Safari.
— cwal

0

Oprócz odpowiedzi @fareed namrouti,

Powinno to być używane, jeśli obraz ma być przeglądany z elementu wejściowego pliku

<input type="file" name="file" id="file-input"><br/>
image after transform: <br/>
<div id="container"></div>

<script>
    document.getElementById('file-input').onchange = function (e) {
        var image = e.target.files[0];
        window.loadImage(image, function (img) {
            if (img.type === "error") {
                console.log("couldn't load image:", img);
            } else {
                window.EXIF.getData(image, function () {
                    console.log("load image done!");
                    var orientation = window.EXIF.getTag(this, "Orientation");
                    var canvas = window.loadImage.scale(img,
                        {orientation: orientation || 0, canvas: true, maxWidth: 200});
                    document.getElementById("container").appendChild(canvas);
                    // or using jquery $("#container").append(canvas);
                });
            }
        });
    };
</script>

0

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.

<?php

header("Content-type: image/jpeg");
$img = 'IMG URL';

$exif = @exif_read_data($img,0,true);
$orientation = @$exif['IFD0']['Orientation'];
if($orientation == 7 || $orientation == 8) {
    $degrees = 90;
} elseif($orientation == 5 || $orientation == 6) {
    $degrees = 270;
} elseif($orientation == 3 || $orientation == 4) {
    $degrees = 180;
} else {
    $degrees = 0;
}
$rotate = imagerotate(imagecreatefromjpeg($img), $degrees, 0);
imagejpeg($rotate);
imagedestroy($rotate);

?>

Twoje zdrowie

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.