Commit cfc48a48 authored by hirono's avatar hirono Committed by Commit bot

Add ImageOrientation class.

Currently we uses different number expressing image orientation for EXIF and
drive metadata.

The CL added generic ImageOrientation class that is going to replace the image
orientation numbers.

BUG=396702
TEST=ImageOrientationTest

Review URL: https://codereview.chromium.org/1025593002

Cr-Commit-Position: refs/heads/master@{#321541}
parent b3fa4672
......@@ -158,3 +158,8 @@ IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ExifParser) {
RunTest(base::FilePath(FILE_PATH_LITERAL(
"foreground/js/metadata/exif_parser_unittest.html")));
}
IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ImageOrientation) {
RunTest(base::FilePath(FILE_PATH_LITERAL(
"foreground/js/metadata/image_orientation_unittest.html")));
}
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* Class representing image orientation.
* The constructor takes 2x2 matrix value that cancels the image orientation:
* |a, c|
* |b, d|
* @param {number} a
* @param {number} b
* @param {number} c
* @param {number} d
* @struct
* @constructor
*/
function ImageOrientation(a, b, c, d) {
/**
* @public {number}
* @const
*/
this.a = a;
/**
* @public {number}
* @const
*/
this.b = b;
/**
* @public {number}
* @const
*/
this.c = c;
/**
* @public {number}
* @const
*/
this.d = d;
}
/**
* @param {number} orientation 1-based orientation number defined by EXIF.
* @return {!ImageOrientation}
*/
ImageOrientation.fromExifOrientation = function(orientation) {
switch (~~orientation) {
case 1:
return new ImageOrientation(1, 0, 0, 1);
case 2:
return new ImageOrientation(-1, 0, 0, 1);
case 3:
return new ImageOrientation(-1, 0, 0, -1);
case 4:
return new ImageOrientation(1, 0, 0, -1);
case 5:
return new ImageOrientation(0, 1, 1, 0);
case 6:
return new ImageOrientation(0, 1, -1, 0);
case 7:
return new ImageOrientation(0, -1, -1, 0);
case 8:
return new ImageOrientation(0, -1, 1, 0);
default:
console.error('Invalid orientation number.');
return new ImageOrientation(1, 0, 0, 1);
}
};
/**
* @param {number} rotation90 Clockwise degrees / 90.
* @return {!ImageOrientation}
*/
ImageOrientation.fromDriveOrientation = function(rotation90) {
switch (~~(rotation90 % 4)) {
case 0:
return new ImageOrientation(1, 0, 0, 1);
case 1:
return new ImageOrientation(0, -1, 1, 0);
case 2:
return new ImageOrientation(-1, 0, 0, -1);
case 3:
return new ImageOrientation(0, 1, -1, 0);
default:
console.error('Invalid orientation number.');
return new ImageOrientation(1, 0, 0, 1);
}
};
/**
* Obtains the image size after cancelling its orientation.
* @param {number} imageWidth
* @param {number} imageHeight
* @return {{width:number, height:number}}
*/
ImageOrientation.prototype.getSizeAfterCancelling = function(
imageWidth, imageHeight) {
var projectedX = this.a * imageWidth + this.c * imageHeight;
var projectedY = this.b * imageWidth + this.d * imageHeight;
return {
width: Math.abs(projectedX),
height: Math.abs(projectedY)
};
};
/**
* Applies the transformation that cancels the image orientation to the given
* context.
* @param {!CanvasRenderingContext2D} context
* @param {number} imageWidth
* @param {number} imageHeight
*/
ImageOrientation.prototype.cancelImageOrientation = function(
context, imageWidth, imageHeight) {
// Calculate where to project the point of (imageWidth, imageHeight).
var projectedX = this.a * imageWidth + this.c * imageHeight;
var projectedY = this.b * imageWidth + this.d * imageHeight;
// If the projected point coordinates are negative, add offset to cancel it.
var offsetX = projectedX < 0 ? -projectedX : 0;
var offsetY = projectedY < 0 ? -projectedY : 0;
// Apply the transform.
context.setTransform(this.a, this.b, this.c, this.d, offsetX, offsetY);
};
<!DOCTYPE html>
<!-- Copyright 2015 The Chromium Authors. All rights reserved.
-- Use of this source code is governed by a BSD-style license that can be
-- found in the LICENSE file.
-->
<script src="image_orientation.js"></script>
<script src="image_orientation_unittest.js"></script>
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function testGetSizeAfterCancelling() {
// Crockwise 90 degrees image orientation.
var orientation = new ImageOrientation(0, 1, 1, 0);
// After cancelling orientation, the width and the height are swapped.
var size = orientation.getSizeAfterCancelling(100, 200);
assertEquals(200, size.width);
assertEquals(100, size.height);
}
function testCancelImageOrientation() {
// Crockwise 90 degrees image orientation.
var orientation = new ImageOrientation(0, 1, 1, 0);
var canvas = document.createElement('canvas');
canvas.width = 2;
canvas.height = 1;
var context = canvas.getContext('2d');
var imageData = context.createImageData(2, 1);
imageData.data[0] = 255; // R
imageData.data[1] = 0; // G
imageData.data[2] = 0; // B
imageData.data[3] = 100; // A
imageData.data[4] = 0; // R
imageData.data[5] = 0; // G
imageData.data[6] = 0; // B
imageData.data[7] = 100; // A
context.putImageData(imageData, 0, 0);
var destinationCanvas = document.createElement('canvas');
destinationCanvas.width = 1;
destinationCanvas.height = 2;
var destinationContext = destinationCanvas.getContext('2d');
orientation.cancelImageOrientation(destinationContext, 2, 1);
destinationContext.drawImage(canvas, 0, 0);
var destinationImageData = destinationContext.getImageData(0, 0, 1, 2);
assertArrayEquals([255, 0, 0, 100, 0, 0, 0, 100], destinationImageData.data);
}
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