Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(814)

Side by Side Diff: ui/file_manager/gallery/js/gallery_item.js

Issue 1053653003: Gallery: Support RAW files in Gallery. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix the second bind. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * Object representing an image item (a photo). 6 * Object representing an image item (a photo).
7 * 7 *
8 * @param {!FileEntry} entry Image entry. 8 * @param {!FileEntry} entry Image entry.
9 * @param {!EntryLocation} locationInfo Entry location information. 9 * @param {!EntryLocation} locationInfo Entry location information.
10 * @param {!MetadataItem} metadataItem 10 * @param {!MetadataItem} metadataItem
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 * @type {!RegExp} 148 * @type {!RegExp}
149 * @const 149 * @const
150 */ 150 */
151 Gallery.Item.REGEXP_COPY_N = 151 Gallery.Item.REGEXP_COPY_N =
152 new RegExp('^(.+)' + Gallery.Item.COPY_SIGNATURE + ' \\((\\d+)\\)$'); 152 new RegExp('^(.+)' + Gallery.Item.COPY_SIGNATURE + ' \\((\\d+)\\)$');
153 153
154 /** 154 /**
155 * Creates a name for an edited copy of the file. 155 * Creates a name for an edited copy of the file.
156 * 156 *
157 * @param {!DirectoryEntry} dirEntry Entry. 157 * @param {!DirectoryEntry} dirEntry Entry.
158 * @param {string} newMimeType Mime type of new image.
158 * @param {function(string)} callback Callback. 159 * @param {function(string)} callback Callback.
159 * @private 160 * @private
160 */ 161 */
161 Gallery.Item.prototype.createCopyName_ = function(dirEntry, callback) { 162 Gallery.Item.prototype.createCopyName_ = function(
163 dirEntry, newMimeType, callback) {
162 var name = this.getFileName(); 164 var name = this.getFileName();
163 165
164 // If the item represents a file created during the current Gallery session 166 // If the item represents a file created during the current Gallery session
165 // we reuse it for subsequent saves instead of creating multiple copies. 167 // we reuse it for subsequent saves instead of creating multiple copies.
166 if (!this.original_) { 168 if (!this.original_) {
167 callback(name); 169 callback(name);
168 return; 170 return;
169 } 171 }
170 172
171 var ext = ''; 173 var baseName = name.replace(/\.[^\.\/]+$/, '');
172 var index = name.lastIndexOf('.'); 174 var ext = newMimeType === 'image/jpeg' ? '.jpg' : '.png';
173 if (index != -1) {
174 ext = name.substr(index);
175 name = name.substr(0, index);
176 }
177
178 if (!ext.match(/jpe?g/i)) {
179 // Chrome can natively encode only two formats: JPEG and PNG.
180 // All non-JPEG images are saved in PNG, hence forcing the file extension.
181 ext = '.png';
182 }
183 175
184 function tryNext(tries) { 176 function tryNext(tries) {
185 // All the names are used. Let's overwrite the last one. 177 // All the names are used. Let's overwrite the last one.
186 if (tries == 0) { 178 if (tries == 0) {
187 setTimeout(callback, 0, name + ext); 179 setTimeout(callback, 0, baseName + ext);
188 return; 180 return;
189 } 181 }
190 182
191 // If the file name contains the copy signature add/advance the sequential 183 // If the file name contains the copy signature add/advance the sequential
192 // number. 184 // number.
193 var matchN = Gallery.Item.REGEXP_COPY_N.exec(name); 185 var matchN = Gallery.Item.REGEXP_COPY_N.exec(baseName);
194 var match0 = Gallery.Item.REGEXP_COPY_0.exec(name); 186 var match0 = Gallery.Item.REGEXP_COPY_0.exec(baseName);
195 if (matchN && matchN[1] && matchN[2]) { 187 if (matchN && matchN[1] && matchN[2]) {
196 var copyNumber = parseInt(matchN[2], 10) + 1; 188 var copyNumber = parseInt(matchN[2], 10) + 1;
197 name = matchN[1] + Gallery.Item.COPY_SIGNATURE + ' (' + copyNumber + ')'; 189 baseName = matchN[1] + Gallery.Item.COPY_SIGNATURE +
190 ' (' + copyNumber + ')';
198 } else if (match0 && match0[1]) { 191 } else if (match0 && match0[1]) {
199 name = match0[1] + Gallery.Item.COPY_SIGNATURE + ' (1)'; 192 baseName = match0[1] + Gallery.Item.COPY_SIGNATURE + ' (1)';
200 } else { 193 } else {
201 name += Gallery.Item.COPY_SIGNATURE; 194 baseName += Gallery.Item.COPY_SIGNATURE;
202 } 195 }
203 196
204 dirEntry.getFile(name + ext, {create: false, exclusive: false}, 197 dirEntry.getFile(baseName + ext, {create: false, exclusive: false},
205 tryNext.bind(null, tries - 1), 198 tryNext.bind(null, tries - 1),
206 callback.bind(null, name + ext)); 199 callback.bind(null, baseName + ext));
207 } 200 }
208 201
209 tryNext(10); 202 tryNext(10);
210 }; 203 };
211 204
212 /** 205 /**
213 * Writes the new item content to either the existing or a new file. 206 * Writes the new item content to either the existing or a new file.
214 * 207 *
215 * @param {!VolumeManager} volumeManager Volume manager instance. 208 * @param {!VolumeManager} volumeManager Volume manager instance.
216 * @param {!MetadataModel} metadataModel 209 * @param {!MetadataModel} metadataModel
217 * @param {DirectoryEntry} fallbackDir Fallback directory in case the current 210 * @param {DirectoryEntry} fallbackDir Fallback directory in case the current
218 * directory is read only. 211 * directory is read only.
219 * @param {boolean} overwrite Whether to overwrite the image to the item or not. 212 * @param {boolean} overwrite Whether to overwrite the image to the item or not.
220 * @param {!HTMLCanvasElement} canvas Source canvas. 213 * @param {!HTMLCanvasElement} canvas Source canvas.
221 * @param {function(boolean)} callback Callback accepting true for success. 214 * @param {function(boolean)} callback Callback accepting true for success.
222 */ 215 */
223 Gallery.Item.prototype.saveToFile = function( 216 Gallery.Item.prototype.saveToFile = function(
224 volumeManager, metadataModel, fallbackDir, overwrite, canvas, callback) { 217 volumeManager, metadataModel, fallbackDir, overwrite, canvas, callback) {
225 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('SaveTime')); 218 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('SaveTime'));
226 219
227 var name = this.getFileName(); 220 var name = this.getFileName();
221 var newMimeType = name.match(/\.jpe?g$/i) || FileType.isRaw(this.entry_) ?
222 'image/jpeg' : 'image/png';
228 223
229 var onSuccess = function(entry) { 224 var onSuccess = function(entry) {
230 var locationInfo = volumeManager.getLocationInfo(entry); 225 var locationInfo = volumeManager.getLocationInfo(entry);
231 if (!locationInfo) { 226 if (!locationInfo) {
232 // Reuse old location info if it fails to obtain location info. 227 // Reuse old location info if it fails to obtain location info.
233 locationInfo = this.locationInfo_; 228 locationInfo = this.locationInfo_;
234 } 229 }
235 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 1, 2); 230 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 1, 2);
236 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('SaveTime')); 231 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('SaveTime'));
237 232
(...skipping 25 matching lines...) Expand all
263 var blob; 258 var blob;
264 var fileWriter; 259 var fileWriter;
265 260
266 metadataModel.get( 261 metadataModel.get(
267 [fileEntry], 262 [fileEntry],
268 ['mediaMimeType', 'contentMimeType', 'ifd', 'exifLittleEndian'] 263 ['mediaMimeType', 'contentMimeType', 'ifd', 'exifLittleEndian']
269 ).then(function(metadataItems) { 264 ).then(function(metadataItems) {
270 // Create the blob of new image. 265 // Create the blob of new image.
271 var metadataItem = metadataItems[0]; 266 var metadataItem = metadataItems[0];
272 metadataItem.modificationTime = new Date(); 267 metadataItem.modificationTime = new Date();
268 metadataItem.mediaMimeType = newMimeType;
273 var metadataEncoder = ImageEncoder.encodeMetadata( 269 var metadataEncoder = ImageEncoder.encodeMetadata(
274 metadataItem, canvas, /* quality for thumbnail*/ 0.8); 270 metadataItem, canvas, /* quality for thumbnail*/ 0.8);
275 // Contrary to what one might think 1.0 is not a good default. Opening 271 // Contrary to what one might think 1.0 is not a good default. Opening
276 // and saving an typical photo taken with consumer camera increases 272 // and saving an typical photo taken with consumer camera increases
277 // its file size by 50-100%. Experiments show that 0.9 is much better. 273 // its file size by 50-100%. Experiments show that 0.9 is much better.
278 // It shrinks some photos a bit, keeps others about the same size, but 274 // It shrinks some photos a bit, keeps others about the same size, but
279 // does not visibly lower the quality. 275 // does not visibly lower the quality.
280 blob = ImageEncoder.getBlob(canvas, metadataEncoder, 0.9); 276 blob = ImageEncoder.getBlob(canvas, metadataEncoder, 0.9);
281 }).then(function() { 277 }.bind(this)).then(function() {
282 // Create writer. 278 // Create writer.
283 return new Promise(function(fullfill, reject) { 279 return new Promise(function(fullfill, reject) {
284 fileEntry.createWriter(fullfill, reject); 280 fileEntry.createWriter(fullfill, reject);
285 }); 281 });
286 }).then(function(writer) { 282 }).then(function(writer) {
287 fileWriter = writer; 283 fileWriter = writer;
288 284
289 // Truncates the file to 0 byte if it overwrites. 285 // Truncates the file to 0 byte if it overwrites.
290 return new Promise(function(fulfill, reject) { 286 return new Promise(function(fulfill, reject) {
291 if (!newFile) { 287 if (!newFile) {
(...skipping 29 matching lines...) Expand all
321 }.bind(this), onError); 317 }.bind(this), onError);
322 }.bind(this); 318 }.bind(this);
323 319
324 var checkExistence = function(dir) { 320 var checkExistence = function(dir) {
325 dir.getFile(name, {create: false, exclusive: false}, 321 dir.getFile(name, {create: false, exclusive: false},
326 getFile.bind(null, dir, false /* existing file */), 322 getFile.bind(null, dir, false /* existing file */),
327 getFile.bind(null, dir, true /* create new file */)); 323 getFile.bind(null, dir, true /* create new file */));
328 }; 324 };
329 325
330 var saveToDir = function(dir) { 326 var saveToDir = function(dir) {
331 if (overwrite && !this.locationInfo_.isReadOnly) { 327 if (overwrite &&
328 !this.locationInfo_.isReadOnly &&
329 !FileType.isRaw(this.entry_)) {
332 checkExistence(dir); 330 checkExistence(dir);
333 } else { 331 } else {
334 this.createCopyName_(dir, function(copyName) { 332 this.createCopyName_(dir, newMimeType, function(copyName) {
335 this.original_ = false; 333 this.original_ = false;
336 name = copyName; 334 name = copyName;
337 checkExistence(dir); 335 checkExistence(dir);
338 }.bind(this)); 336 }.bind(this));
339 } 337 }
340 }.bind(this); 338 }.bind(this);
341 339
342 if (this.locationInfo_.isReadOnly) { 340 if (this.locationInfo_.isReadOnly) {
343 saveToDir(fallbackDir); 341 saveToDir(fallbackDir);
344 } else { 342 } else {
(...skipping 30 matching lines...) Expand all
375 return Promise.reject(str('GALLERY_FILE_EXISTS')); 373 return Promise.reject(str('GALLERY_FILE_EXISTS'));
376 }, function() { 374 }, function() {
377 return new Promise( 375 return new Promise(
378 this.entry_.moveTo.bind(this.entry_, parentDirectory, newFileName)); 376 this.entry_.moveTo.bind(this.entry_, parentDirectory, newFileName));
379 }.bind(this)); 377 }.bind(this));
380 }.bind(this)); 378 }.bind(this));
381 }.bind(this)).then(function(entry) { 379 }.bind(this)).then(function(entry) {
382 this.entry_ = entry; 380 this.entry_ = entry;
383 }.bind(this)); 381 }.bind(this));
384 }; 382 };
OLDNEW
« no previous file with comments | « ui/file_manager/gallery/css/gallery.css ('k') | ui/file_manager/gallery/js/gallery_item_unittest.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698