Định hướng Exif phía máy khách: Xoay và phản chiếu hình ảnh JPEG


154

Ảnh máy ảnh kỹ thuật số thường được lưu dưới dạng JPEG với thẻ "định hướng" EXIF. Để hiển thị chính xác, hình ảnh cần phải được xoay / nhân đôi tùy theo hướng được đặt, nhưng trình duyệt bỏ qua thông tin này hiển thị hình ảnh. Ngay cả trong các ứng dụng web thương mại lớn, hỗ trợ cho định hướng EXIF ​​có thể được chú ý 1 . Cùng một nguồn cũng cung cấp một bản tóm tắt hay về 8 hướng khác nhau mà JPEG có thể có:

Tóm tắt định hướng EXIF

Hình ảnh mẫu có sẵn tại 4 .

Câu hỏi là làm thế nào để xoay / phản chiếu hình ảnh ở phía máy khách để nó hiển thị chính xác và có thể được xử lý thêm nếu cần thiết?

Có các thư viện JS có sẵn để phân tích dữ liệu EXIF, bao gồm cả thuộc tính định hướng 2 . Flickr lưu ý vấn đề hiệu năng có thể xảy ra khi phân tích hình ảnh lớn, yêu cầu sử dụng webworkers 3 .

Các công cụ điều khiển có thể định hướng lại chính xác các hình ảnh 5 . Một đoạn mã PHP giải quyết vấn đề có sẵn ở 6

Câu trả lời:


145

Dự án github JavaScript-Load-Image cung cấp một giải pháp hoàn chỉnh cho vấn đề định hướng EXIF, xoay / phản chiếu hình ảnh chính xác cho cả 8 định hướng exif. Xem bản demo trực tuyến của định hướng exif javascript

Hình ảnh được vẽ trên khung vẽ HTML5. Kết xuất chính xác của nó được triển khai trong js / load-image-direction.js thông qua các hoạt động canvas.

Hy vọng điều này sẽ giúp người khác tiết kiệm thời gian và dạy các công cụ tìm kiếm về loại đá quý nguồn mở này :)


1
Tôi đã sử dụng thư viện này nhưng gần đây nó đã bị hỏng trên iOS 8.3, đó là nơi tôi cần nó để hoạt động nhất :(
Gordon Sun

2
Tôi thực sự vật lộn để xem điều này hữu ích như thế nào. Tôi đang chơi xung quanh với nó để cố gắng học nó để tôi có thể phân tích một trang và xoay hình ảnh khi chúng cần được xoay, hoặc phát hiện hướng và xoay tệp (bằng cách nào đó) trước khi thực sự tải lên. Bản demo không có. Nó chỉ đơn giản là lấy một tập tin từ một tập tin đầu vào và hiển thị nó đúng cách, khi nào nó hữu ích trong thế giới thực? Khi tôi phân tích trang của mình và đưa các URL từ thẻ hình ảnh vào thư viện loadImage, không có dữ liệu exif nên không thể làm điều đó. Để tải lên, nó trả về một đối tượng canvas để tôi không thể gửi nó đến máy chủ hoặc bất cứ thứ gì.
igneizard

3
@igneizard: bạn có thể gửi dữ liệu được mã hóa base64 đến máy chủ canvas.toDataURL()và giải mã và lưu phía máy chủ.
br4nnigan

1
thay vì sử dụng dự án hình ảnh tải, bạn có thể sử dụng một số cơ sở mã của nó để tự nướng - chỉ cần xem trong github.com/blueimp/JavaScript-Load-Image/blob/master/js/ .
Andy Lorenz

1
Có cách nào để tạo canvas mà thư viện này tạo phản hồi như <img>thẻ thông thường không?
Erik Berkun-Drevnig

103

Biến đổi bối cảnh của Mederr hoạt động hoàn hảo. Nếu bạn cần trích xuất hướng chỉ sử dụng chức năng này - bạn không cần bất kỳ lib đọc EXIF ​​nào. Dưới đây là một chức năng để thiết lập lại định hướng trong hình ảnh cơ sở64. Đây là một câu đố cho nó . Tôi cũng đã chuẩn bị một mẹo nhỏ với bản demo trích xuất định hướng .

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
Trường hợp mặc định trong định hướng switchlà không cần thiết, vì phép biến đổi đó không làm gì cả. Ngoài ra, hãy cân nhắc sử dụng srcOrientation > 4 && srcOrientation < 9thay vì [5,6,7,8].indexOf(srcOrientation) > -1, vì nó nhanh hơn và ít tốn tài nguyên hơn (cả RAM & CPU). Không cần phải có một mảng ở đó. Điều này rất quan trọng khi bó rất nhiều hình ảnh, trong đó mỗi bit đều được tính. Nếu không, câu trả lời khá tốt. Nâng cao!
Ryan Casas

4
@RyanCasas Tôi không nhận thức được mức độ nặng nề của indexOfnhững gì bạn đề xuất. Tôi đã chạy một vòng lặp đơn giản với số lần lặp 10M và nó nhanh hơn 1400%. Nice: D Cảm ơn rất nhiều!
WunderBart

1
Tôi đã sử dụng câu trả lời này trong WebView trên Android và hóa ra, có một số thiết bị Android không hỗ trợ WebGL trong WebView (xem bug.chromium.org/p/chromium/issues/detail?id=555116 ) xoay có thể mất rất lâu trên các thiết bị như vậy tùy thuộc vào kích thước của hình ảnh.
ndreisg

1
Khi được sử dụng với tham chiếu getOrientation, tôi tò mò liệu điều này có hiệu quả về mặt hiệu suất hay không. getOrientationgọi fileReader.readAsArrayBuffervà sau đó chúng tôi gọi URL.createObjectURLvà chuyển kết quả vào resetOrientation, tải URL này dưới dạng hình ảnh. Điều này có nghĩa là tệp hình ảnh sẽ được "tải" / đọc bởi trình duyệt không chỉ một lần mà hai lần, hay tôi hiểu nhầm?
Oliver Joseph Ash

1
Ngoài ra, phải làm gì với các trình duyệt nơi định hướng sẽ được tôn trọng? Tôi tin rằng đây là trường hợp của iOS Safari và trong các trình duyệt hỗ trợ CSS image-orientation: from-imagekhi nó được sử dụng.
Oliver Joseph Ash

40

Nếu

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

Sau đó, bạn có thể sử dụng các biến đổi này để chuyển hình ảnh sang hướng 1

Từ định hướng:

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

Trước khi vẽ hình ảnh trên ctx


58
Điều gì đang xảy ra ở đây?
Muhammad Umer

1
Với điều này, bạn chỉ cần biết định hướng (ví dụ thông qua EXIF) và sau đó xoay khi cần thiết. Một nửa những gì tôi đang tìm kiếm.
Brenden

2
những biến đổi này không hiệu quả với tôi - thay vào đó tôi đã sử dụng mã từ dự án hình ảnh tải tại github.com/blueimp/JavaScript-Load-Image/blob/master/js/iêu để có được những gì tôi tin là mã được chứng minh tốt trong đó sử dụng cả hai thao tác dịch, xoay trên bối cảnh canvas cộng với hoán đổi chiều rộng / chiều cao. Đã cho tôi kết quả 100% sau nhiều giờ thử nghiệm với các nỗ lực khác để chuyển đổi, v.v.
Andy Lorenz

1
Tại sao nó không quan trọng khi bạn vẽ hình ảnh trên ctx? Bạn không thể xoay khung vẽ sau khi vẽ một hình ảnh trên đó?
AlxVallejo

Xoay cho định hướng 8 hoạt động theo cách này đối với tôi: ctx.transform (0, -1, 1, 0, 0, chiều cao);
Giorgio Barchiesi

24

ok ngoài câu trả lời @ user3096626 tôi nghĩ sẽ hữu ích hơn nếu ai đó cung cấp ví dụ mã, ví dụ sau sẽ chỉ cho bạn cách sửa hướng hình ảnh đến từ url (hình ảnh từ xa):


Giải pháp 1: sử dụng javascript (được khuyến nghị)

  1. vì thư viện hình ảnh tải không trích xuất các thẻ exif chỉ từ hình ảnh url (tệp / blob), nên chúng tôi sẽ sử dụng cả thư viện javascript exif-jsload-image , vì vậy trước tiên hãy thêm các thư viện này vào trang của bạn như sau:

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

    Lưu ý phiên bản 2.2 của exif-js dường như có vấn đề nên chúng tôi đã sử dụng 2.1

  2. về cơ bản những gì chúng ta sẽ làm là

    a - tải hình ảnh bằng cách sử dụng window.loadImage()

    b - đọc thẻ exif bằng window.EXIF.getData()

    c - chuyển đổi hình ảnh thành canvas và sửa hướng hình ảnh bằng cách sử dụng window.loadImage.scale()

    d - đặt khung vẽ vào tài liệu

bạn đi đây :)

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

    });
  }
});

tất nhiên bạn cũng có thể lấy hình ảnh dưới dạng base64 từ đối tượng canvas và đặt nó vào thuộc tính img src, vì vậy sử dụng jQuery bạn có thể làm được;)

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

đây là mã đầy đủ trên: github: https://github.com/digital-flowers/loadimage-exif-example


Giải pháp 2: sử dụng html (hack trình duyệt)

Có một cách hack rất nhanh và dễ dàng, hầu hết các trình duyệt hiển thị hình ảnh theo đúng hướng nếu hình ảnh được mở trực tiếp bên trong một tab mới mà không có bất kỳ html nào (LOL tôi không biết tại sao), vì vậy về cơ bản bạn có thể hiển thị hình ảnh của mình bằng iframe bằng cách đặt thuộc tính iframe src làm url hình ảnh trực tiếp:

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

Giải pháp 3: sử dụng css (chỉ firefox & safari trên ios)

Có thuộc tính css3 để sửa hướng hình ảnh nhưng vấn đề nó chỉ hoạt động trên firefox và safari / ios, nó vẫn đáng được đề cập vì sẽ sớm có sẵn cho tất cả các trình duyệt (Thông tin hỗ trợ trình duyệt từ caniuse )

img {
   image-orientation: from-image;
}

Giải pháp 1 không hiệu quả với tôi. Cửa sổ đang quay lại .loadImage không được xác định
Perry

Điều này xảy ra nếu bạn không bao gồm các thư viện mà tôi đề cập ở bước 1
Fareed Alnamrouti

Tôi bao gồm các thư viện. Tôi thích sự đơn giản của ví dụ của bạn nhưng tôi tiếp tục nhận được thông báo lỗi đó.
Perry

1
có vẻ như exif-js đã bị hỏng, vui lòng kiểm tra chỉnh sửa của tôi. Tôi cũng đã thêm mã đầy đủ trên github: github.com/digital-flowers/loadimage-exif-example
Fareed Alnamrouti

1
ok kiểm tra dự án github có một tệp mới "upload.html", bạn được chào đón :)
Fnamed Alnamrouti

10

Đối với những người có tệp từ điều khiển đầu vào, không biết định hướng của nó là gì, hơi lười biếng và không muốn bao gồm một thư viện lớn bên dưới là mã được cung cấp bởi @WunderBart kết hợp với câu trả lời mà anh ta liên kết đến ( https://stackoverflow.com/a/32490603 ) tìm thấy hướng.

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

có thể dễ dàng được gọi như vậy

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

2
Cảm ơn sau hơn 2 giờ tìm kiếm bằng google tôi tìm được giải pháp phù hợp.
Mr.Trieu

2
Tại sao một người nào đó lười biếng để thích một giải pháp nhẹ hơn nhiều?
sương

4
Được chuyển sang Bản in và được tối ưu hóa từ khoảng 4 giây đến ~ 20 mili giây. Mã hóa Base64 là nút cổ chai - sử dụng image/jpegthay vì mặc định image/pngvà thay đổi kích thước hình ảnh đầu ra thành chiều rộng tối đa (400px trong trường hợp của tôi) đã tạo ra sự khác biệt lớn. (điều này hoạt động tốt cho hình thu nhỏ, nhưng nếu bạn phải hiển thị hình ảnh đầy đủ, tôi khuyên bạn nên tránh base64 và chỉ cần đưa phần tử canvas trực tiếp vào trang ...)
mindplay.dk

8

Câu trả lời của WunderBart là tốt nhất cho tôi. Lưu ý rằng bạn có thể tăng tốc nó lên rất nhiều nếu hình ảnh của bạn thường đi đúng hướng, chỉ cần kiểm tra hướng trước và bỏ qua phần còn lại của mã nếu không yêu cầu xoay.

Đặt tất cả các thông tin từ wunderbart lại với nhau, đại loại như thế này;

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
Cách tiếp cận tuyệt vời. Bạn cũng nên xem xét việc xử lý -2-1trả lại getOrientationđể bạn không cố xoay các hình ảnh không phải là jpg hoặc hình ảnh mà không có dữ liệu xoay.
Steven Lambert

Tôi đã thực hiện nhiều tối ưu hóa hơn, xem nhận xét của tôi ở trên - Tôi cũng vừa thêm file.slice()tối ưu hóa của bạn , nhưng sự tăng cường thực sự đến từ việc sử dụng hình ảnh nhỏ hơn và image/jpegđịnh dạng đầu ra để tạo URL dữ liệu nhỏ hơn. (không có độ trễ đáng chú ý ngay cả đối với hình ảnh 10 megapixel.)
mindplay.dk

Cẩn thận với file.slice(), vì bạn sẽ ngăn chặn sự hỗ trợ của các nguồn hình ảnh base64.
Đánh dấu

Cảm ơn mark - quan tâm để cung cấp một chỉnh sửa cho một sự thay thế?
statler

7

Ai lót ai?

Tôi chưa thấy ai nhắc đến browser-image-compressionthư viện . Nó có một chức năng trợ giúp hoàn hảo cho việc này.

Sử dụng: const orientation = await imageCompression.getExifOrientation(file)

Như một công cụ hữu ích theo nhiều cách khác nữa.


Điều này có được định hướng. Nhưng làm cách nào để tạo một đối tượng Tệp .jpg mới ở phía máy khách bằng thông tin này?
masterxilo

Bạn không thể tạo Filecác đối tượng theo như tôi biết. Điều tốt nhất tiếp theo sẽ là gửi hình ảnh và định hướng lên máy chủ và thực hiện thao tác với tệp ở đó. Hoặc bạn có thể tạo một chuỗi base64 bằng cách sử dụng canvastoDataURLphương thức.
gilbert-v

1
Không, bạn có thể tạo một đối tượng Tệp từ Blob. Tệp tệp (Phần mảng, Tên tệp chuỗi, thuộc tính BlobPropertyBag); developer.mozilla.org/de/docs/Web/API/File
masterxilo

2
Nhãn dán vàng! @masterxilo
gilbert-v

2
Nó hiệu quả tuyệt vời đối với tôi! Tôi đã vật lộn với định hướng trong 2 ngày qua! Tất cả các câu lệnh chuyển đổi được đăng sẽ không xử lý hình ảnh chân dung từ điện thoại của tôi vì một số lý do, sẽ có các thanh màu đen. Có lẽ bởi vì tôi đã cố gắng nén và xoay cùng một lúc.
cjd82187

2

Tôi đã tạo một lớp được bọc trong một mô-đun ES6 để giải quyết chính xác điều này.

Đó là 103 dòng, không phụ thuộc, và được cấu trúc và ghi lại khá độc đáo, có nghĩa là dễ dàng sửa đổi / tái sử dụng.

Xử lý tất cả 8 định hướng có thể, và dựa trên Promise.

Ở đây bạn đi, hy vọng điều này vẫn giúp được ai đó: https://gist.github.com/vdavid/3f9b66b60f52204317a4cc0e77097913


1

Tôi đang sử dụng giải pháp hỗn hợp (php + css).

Các container cần thiết cho:

  • div.imgCont2 thùng chứa cần thiết để xoay;
  • div.imgCont1thùng chứa cần thiết để zoomOut - width:150%;
  • div.imgCont thùng chứa cần thiết cho thanh cuộn, khi hình ảnh là 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>

Cảm ơn, đây có vẻ là giải pháp tốt nhất, dù sao cho nhu cầu của tôi. Không cần thư viện bên ngoài và không có khối mã dài không cần thiết. Chỉ cần xác định hướng từ exif với php, gửi nó đến dạng xem và sử dụng nó để kích hoạt các lớp CSS xoay số độ thích hợp. Đẹp và sạch sẽ! Chỉnh sửa: điều này sẽ xoay qua hình ảnh trong các trình duyệt thực sự đọc dữ liệu exif và xoay tương ứng. AKA nó sẽ khắc phục sự cố trên máy tính để bàn nhưng tạo một lỗi mới trên ios safari.
cwal

0

Ngoài câu trả lời của @fareed namrouti,

Điều này nên được sử dụng nếu hình ảnh phải được duyệt từ một yếu tố đầu vào tập tin

<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

Tôi đã viết một đoạn mã php nhỏ để xoay hình ảnh. Hãy chắc chắn để lưu trữ hình ảnh có lợi cho chỉ cần tính toán lại mỗi yêu cầu.

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

?>

Chúc mừng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.