Chromium Code Reviews| Index: ui/file_manager/gallery/js/image_editor/exif_encoder.js |
| diff --git a/ui/file_manager/gallery/js/image_editor/exif_encoder.js b/ui/file_manager/gallery/js/image_editor/exif_encoder.js |
| index 43f88dadf4b06366125a4751188d82e1c618c587..739378ccbda3d3d5da9901fd36bf97120e70eae3 100644 |
| --- a/ui/file_manager/gallery/js/image_editor/exif_encoder.js |
| +++ b/ui/file_manager/gallery/js/image_editor/exif_encoder.js |
| @@ -5,18 +5,26 @@ |
| /** |
| * The Exif metadata encoder. |
| * Uses the metadata format as defined by ExifParser. |
| - * @param {!Object} originalMetadata Metadata to encode. |
| + * @param {!MetadataItem} originalMetadata Metadata to encode. |
| * @constructor |
| * @extends {ImageEncoder.MetadataEncoder} |
| * @struct |
| */ |
| function ExifEncoder(originalMetadata) { |
| ImageEncoder.MetadataEncoder.apply(this, arguments); |
| - |
| - if (this.metadata_.media && this.metadata_.media.ifd) |
| - this.ifd_ = this.metadata_.media.ifd; |
| - else |
| - this.ifd_ = {}; |
| + /** |
| + * Image File Directory obtained from EXIF header. |
| + * @type {!Object} |
|
yawano
2015/02/25 09:19:10
nit: @type -> @private
hirono
2015/02/25 13:28:37
Done.
|
| + */ |
| + this.ifd_ = /** @type {!Object} */( |
| + JSON.parse(JSON.stringify(originalMetadata.ifd || {}))); |
| + |
| + /** |
| + * Note use little endian if the original metadata does not have the |
| + * information. |
| + * @type {boolean} |
| + */ |
| + this.exifLittleEndian_ = !!originalMetadata.exifLittleEndian; |
| } |
| ExifEncoder.prototype = {__proto__: ImageEncoder.MetadataEncoder.prototype}; |
| @@ -32,11 +40,11 @@ ExifEncoder.SOFTWARE = 'Chrome OS Gallery App\0'; |
| /** |
| * @param {!HTMLCanvasElement} canvas |
| - * @param {Date=} opt_modificationDateTime |
| * @override |
| */ |
| -ExifEncoder.prototype.setImageData = |
| - function(canvas, opt_modificationDateTime) { |
| +ExifEncoder.prototype.setImageData = function(canvas) { |
| + ImageEncoder.MetadataEncoder.prototype.setImageData.call(this, canvas); |
| + |
| var image = this.ifd_.image; |
| if (!image) |
| image = this.ifd_.image = {}; |
| @@ -54,11 +62,7 @@ ExifEncoder.prototype.setImageData = |
| ExifEncoder.findOrCreateTag(exif, Exif.Tag.X_DIMENSION).value = canvas.width; |
| ExifEncoder.findOrCreateTag(exif, Exif.Tag.Y_DIMENSION).value = canvas.height; |
| - this.metadata_.width = canvas.width; |
| - this.metadata_.height = canvas.height; |
| - |
| // Always save in default orientation. |
| - delete this.metadata_['imageTransform']; |
| ExifEncoder.findOrCreateTag(image, Exif.Tag.ORIENTATION).value = 1; |
| // Update software name. |
| @@ -75,7 +79,7 @@ ExifEncoder.prototype.setImageData = |
| return str; |
| }; |
| - var modificationDateTime = opt_modificationDateTime || new Date(); |
| + var modificationDateTime = new Date(); |
| var dateTimeTag = ExifEncoder.findOrCreateTag(image, Exif.Tag.DATETIME, 2); |
| dateTimeTag.value = |
| padNumWithZero(modificationDateTime.getFullYear(), 4) + ':' + |
| @@ -91,24 +95,28 @@ ExifEncoder.prototype.setImageData = |
| * @override |
| */ |
| ExifEncoder.prototype.setThumbnailData = function(canvas, quality) { |
| - // Empirical formula with reasonable behavior: |
| - // 10K for 1Mpix, 30K for 5Mpix, 50K for 9Mpix and up. |
| - var pixelCount = this.metadata_.width * this.metadata_.height; |
| - var maxEncodedSize = 5000 * Math.min(10, 1 + pixelCount / 1000000); |
| - |
| - var DATA_URL_PREFIX = 'data:' + this.metadata_.media.mimeType + ';base64,'; |
| - var BASE64_BLOAT = 4 / 3; |
| - var maxDataURLLength = |
| - DATA_URL_PREFIX.length + Math.ceil(maxEncodedSize * BASE64_BLOAT); |
| - |
| - for (;; quality *= 0.8) { |
| - ImageEncoder.MetadataEncoder.prototype.setThumbnailData.call( |
| - this, canvas, quality); |
| - if (this.metadata_.thumbnailURL.length <= maxDataURLLength || quality < 0.2) |
| + if (canvas) { |
| + // Empirical formula with reasonable behavior: |
| + // 10K for 1Mpix, 30K for 5Mpix, 50K for 9Mpix and up. |
| + var pixelCount = this.imageWidth * this.imageHeight; |
| + var maxEncodedSize = 5000 * Math.min(10, 1 + pixelCount / 1000000); |
| + var DATA_URL_PREFIX = 'data:image/jpeg;base64,'; |
| + var BASE64_BLOAT = 4 / 3; |
| + var maxDataURLLength = |
| + DATA_URL_PREFIX.length + Math.ceil(maxEncodedSize * BASE64_BLOAT); |
| + for (; quality > 0.2; quality *= 0.8) { |
| + ImageEncoder.MetadataEncoder.prototype.setThumbnailData.call( |
| + this, canvas, quality); |
| + // If the obtained thumbnail URL is too long, reset the URL and try again |
| + // with less quality value. |
| + if (this.thumbnailDataUrl.length > maxDataURLLength) { |
| + this.thumbnailDataUrl = ''; |
| + continue; |
| + } |
| break; |
| + } |
| } |
| - |
| - if (canvas && this.metadata_.thumbnailURL.length <= maxDataURLLength) { |
| + if (this.thumbnailDataUrl) { |
| var thumbnail = this.ifd_.thumbnail; |
| if (!thumbnail) |
| thumbnail = this.ifd_.thumbnail = {}; |
| @@ -130,13 +138,8 @@ ExifEncoder.prototype.setThumbnailData = function(canvas, quality) { |
| ExifEncoder.findOrCreateTag(this.ifd_.image, Exif.Tag.COMPRESSION).value = |
| 6; |
| } else { |
| - console.warn( |
| - 'Thumbnail URL too long: ' + this.metadata_.thumbnailURL.length); |
| - // Delete thumbnail ifd so that it is not written out to a file, but |
| - // keep thumbnailURL for display purposes. |
| - if (this.ifd_.thumbnail) { |
| + if (this.ifd_.thumbnail) |
| delete this.ifd_.thumbnail; |
| - } |
| } |
| }; |
| @@ -207,7 +210,7 @@ ExifEncoder.prototype.encode = function() { |
| // can be directly mapped to offsets as encoded in the dictionaries. |
| var bw = new ByteWriter(bytes.buffer, HEADER_SIZE); |
| - if (this.metadata_.littleEndian) { |
| + if (this.exifLittleEndian_) { |
| bw.setByteOrder(ByteWriter.ByteOrder.LITTLE_ENDIAN); |
| bw.writeScalar(Exif.Align.LITTLE, 2); |
| } else { |
| @@ -246,8 +249,7 @@ ExifEncoder.prototype.encode = function() { |
| this.ifd_.thumbnail, |
| [Exif.Tag.JPG_THUMB_OFFSET, Exif.Tag.JPG_THUMB_LENGTH]); |
| - var thumbnailDecoded = |
| - ImageEncoder.decodeDataURL(this.metadata_.thumbnailURL); |
| + var thumbnailDecoded = ImageEncoder.decodeDataURL(this.thumbnailDataUrl); |
| bw.resolveOffset(Exif.Tag.JPG_THUMB_OFFSET); |
| bw.resolve(Exif.Tag.JPG_THUMB_LENGTH, thumbnailDecoded.length); |
| bw.writeString(thumbnailDecoded); |