Commit 8936b152 authored by Kuo Jen Wei's avatar Kuo Jen Wei Committed by Commit Bot

[CCA] Drop orientation before draw JPEG onto canvas.

It's a workaround for not hitting crbug.com/1043790 by setting
orientation to 1 before drawing JPEG with EXIF onto canvas.

Bug: 998944
Bug: b:147272638
Test: tast run <DUT> 'camera.CCAUIResolutions'
Change-Id: I274325e7ec4ce39fabcddb6e42e3fa1f55824514
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2040971Reviewed-by: default avatarShik Chen <shik@chromium.org>
Commit-Queue: Kuo Jen Wei <inker@chromium.org>
Auto-Submit: Kuo Jen Wei <inker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738890}
parent 99a78aea
...@@ -136,6 +136,7 @@ js_library("util") { ...@@ -136,6 +136,7 @@ js_library("util") {
":tooltip", ":tooltip",
":type", ":type",
"browser_proxy:browser_proxy", "browser_proxy:browser_proxy",
"externs:w3c_fileapi",
"mojo:chrome_helper", "mojo:chrome_helper",
] ]
externs_list = [ "$externs_path/chrome_extensions.js" ] externs_list = [ "$externs_path/chrome_extensions.js" ]
......
...@@ -8,75 +8,81 @@ import {Resolution} from './type.js'; ...@@ -8,75 +8,81 @@ import {Resolution} from './type.js';
/** /**
* Gets the clockwise rotation and flip that can orient a photo to its upright * Gets the clockwise rotation and flip that can orient a photo to its upright
* position. * position of the photo and drop its orientation information.
* @param {!Blob} blob JPEG blob that might contain EXIF orientation field. * @param {!Blob} blob JPEG blob that might contain EXIF orientation field.
* @return {Promise<Object<number, boolean>>} * @return {!Promise<{rotation: number, flip: boolean, blob: !Blob}>} The
* rotation, flip information of photo and the photo blob after drop those
* information.
*/ */
function getPhotoOrientation(blob) { function dropPhotoOrientation(blob) {
const getOrientation = new Promise((resolve, reject) => { let /** !Blob */ blobWithoutOrientation = blob;
const reader = new FileReader(); const getOrientation = (async () => {
reader.onload = function(event) { const buffer = await blob.arrayBuffer();
const view = new DataView(event.target.result); const view = new DataView(buffer);
if (view.getUint16(0, false) !== 0xFFD8) { if (view.getUint16(0, false) !== 0xFFD8) {
resolve(1); return 1;
return; }
const length = view.byteLength;
let offset = 2;
while (offset < length) {
if (view.getUint16(offset + 2, false) <= 8) {
break;
} }
const length = view.byteLength; const marker = view.getUint16(offset, false);
let offset = 2; offset += 2;
while (offset < length) { if (marker === 0xFFE1) {
if (view.getUint16(offset + 2, false) <= 8) { if (view.getUint32(offset += 2, false) !== 0x45786966) {
break; break;
} }
const marker = view.getUint16(offset, false);
offset += 2;
if (marker === 0xFFE1) {
if (view.getUint32(offset += 2, false) !== 0x45786966) {
break;
}
const little = view.getUint16(offset += 6, false) === 0x4949; const little = view.getUint16(offset += 6, false) === 0x4949;
offset += view.getUint32(offset + 4, little); offset += view.getUint32(offset + 4, little);
const tags = view.getUint16(offset, little); const tags = view.getUint16(offset, little);
offset += 2; offset += 2;
for (let i = 0; i < tags; i++) { for (let i = 0; i < tags; i++) {
if (view.getUint16(offset + (i * 12), little) === 0x0112) { if (view.getUint16(offset + (i * 12), little) === 0x0112) {
resolve(view.getUint16(offset + (i * 12) + 8, little)); offset += (i * 12) + 8;
return; const orientation = view.getUint16(offset, little);
} view.setUint16(offset, 1, little);
blobWithoutOrientation = new Blob([buffer]);
return orientation;
} }
} else if ((marker & 0xFF00) !== 0xFF00) {
break;
} else {
offset += view.getUint16(offset, false);
} }
} else if ((marker & 0xFF00) !== 0xFF00) {
break;
} else {
offset += view.getUint16(offset, false);
} }
resolve(1);
};
reader.readAsArrayBuffer(blob);
});
return getOrientation.then((orientation) => {
switch (orientation) {
case 1:
return {rotation: 0, flip: false};
case 2:
return {rotation: 0, flip: true};
case 3:
return {rotation: 180, flip: false};
case 4:
return {rotation: 180, flip: true};
case 5:
return {rotation: 90, flip: true};
case 6:
return {rotation: 90, flip: false};
case 7:
return {rotation: 270, flip: true};
case 8:
return {rotation: 270, flip: false};
default:
return {rotation: 0, flip: false};
} }
}); return 1;
})();
return getOrientation
.then((orientation) => {
switch (orientation) {
case 1:
return {rotation: 0, flip: false};
case 2:
return {rotation: 0, flip: true};
case 3:
return {rotation: 180, flip: false};
case 4:
return {rotation: 180, flip: true};
case 5:
return {rotation: 90, flip: true};
case 6:
return {rotation: 90, flip: false};
case 7:
return {rotation: 270, flip: true};
case 8:
return {rotation: 270, flip: false};
default:
return {rotation: 0, flip: false};
}
})
.then((orientInfo) => {
return Object.assign(orientInfo, {blob: blobWithoutOrientation});
});
} }
/** /**
...@@ -135,7 +141,7 @@ export function orientPhoto(blob, onSuccess, onFailure) { ...@@ -135,7 +141,7 @@ export function orientPhoto(blob, onSuccess, onFailure) {
}, 'image/jpeg'); }, 'image/jpeg');
}; };
getPhotoOrientation(blob).then((orientation) => { dropPhotoOrientation(blob).then((orientation) => {
if (orientation.rotation === 0 && !orientation.flip) { if (orientation.rotation === 0 && !orientation.flip) {
onSuccess(blob); onSuccess(blob);
} else { } else {
...@@ -144,7 +150,7 @@ export function orientPhoto(blob, onSuccess, onFailure) { ...@@ -144,7 +150,7 @@ export function orientPhoto(blob, onSuccess, onFailure) {
drawPhoto(original, orientation, onSuccess, onFailure); drawPhoto(original, orientation, onSuccess, onFailure);
}; };
original.onerror = onFailure; original.onerror = onFailure;
original.src = URL.createObjectURL(blob); original.src = URL.createObjectURL(orientation.blob);
} }
}); });
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment