VulpesOS/gaia/shared/js/media/image_size.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

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');
}
});
}