Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
105 lines
3.5 KiB
JavaScript
Executable file
105 lines
3.5 KiB
JavaScript
Executable file
/* exported getImageSize */
|
|
/* global BlobView */
|
|
/* global parseJPEGMetadata */
|
|
|
|
/*
|
|
* Determine the pixel dimensions of an image without actually
|
|
* decoding the image. Passes an object of metadata to the callback
|
|
* function on success or an error message to the error function on
|
|
* failure. The metadata object will include type, width and height
|
|
* properties. Supported image types are GIF, PNG and JPEG. JPEG
|
|
* metadata may also include information about an EXIF preview image.
|
|
*
|
|
* Because of shortcomings in the way Gecko handles images, the
|
|
* Gallery app will crash with an OOM error if it attempts to decode
|
|
* and display an image that is too big. Images require 4 bytes per
|
|
* pixel, so a 10 megapixel photograph requires 40 megabytes of image
|
|
* memory. This function gives the gallery app a way to reject images
|
|
* that are too large.
|
|
*
|
|
* Requires the BlobView class from shared/js/blobview.js and the
|
|
* parseJPEGMetadata() function from shared/js/media/jpeg_metadata_parser.js
|
|
*/
|
|
function getImageSize(blob, callback, error) {
|
|
'use strict';
|
|
|
|
BlobView.get(blob, 0, Math.min(1024, blob.size), function(data) {
|
|
// Make sure we are at least 8 bytes long before reading the first 8 bytes
|
|
if (data.byteLength <= 8) {
|
|
error('corrupt image file');
|
|
return;
|
|
}
|
|
var magic = data.getBinaryText(0, 8);
|
|
if (magic.substring(0, 4) === 'GIF8') {
|
|
try {
|
|
callback({
|
|
type: 'gif',
|
|
width: data.getUint16(6, true),
|
|
height: data.getUint16(8, true)
|
|
});
|
|
}
|
|
catch (e) {
|
|
error(e.toString());
|
|
}
|
|
}
|
|
else if (magic.substring(0, 8) === '\x89PNG\r\n\x1A\n') {
|
|
try {
|
|
callback({
|
|
type: 'png',
|
|
width: data.getUint32(16, false),
|
|
height: data.getUint32(20, false)
|
|
});
|
|
}
|
|
catch (e) {
|
|
error(e.toString());
|
|
}
|
|
}
|
|
else if (magic.substring(0, 2) === 'BM' &&
|
|
data.getUint32(2, true) === blob.size) {
|
|
// This is a BMP file
|
|
try {
|
|
var width, height;
|
|
|
|
if (data.getUint16(14, true) === 12) { // check format version
|
|
width = data.getUint16(18, true); // 16-bit little endian width
|
|
height = data.getUint16(20, true); // 16-bit little endian height
|
|
}
|
|
else { // newer versions of the format use 32-bit ints
|
|
width = data.getUint32(18, true); // 32-bit little endian width
|
|
height = data.getUint32(22, true); // 32-bit little endian height
|
|
}
|
|
|
|
callback({
|
|
type: 'bmp',
|
|
width: width,
|
|
height: height
|
|
});
|
|
}
|
|
catch (e) {
|
|
error(e.toString());
|
|
}
|
|
}
|
|
else if (magic.substring(0, 2) === '\xFF\xD8') {
|
|
parseJPEGMetadata(blob,
|
|
function(metadata) {
|
|
if (metadata.progressive) {
|
|
// If the jpeg parser tells us that this is
|
|
// a progressive jpeg, then treat that as a
|
|
// distinct image type because pjpegs have
|
|
// such different memory requirements than
|
|
// regular jpegs.
|
|
delete metadata.progressive;
|
|
metadata.type = 'pjpeg';
|
|
}
|
|
else {
|
|
metadata.type = 'jpeg';
|
|
}
|
|
callback(metadata);
|
|
},
|
|
error);
|
|
}
|
|
else {
|
|
error('unknown image type');
|
|
}
|
|
});
|
|
}
|