JavaScript Load Image
A JavaScript library to load and transform image files.
Contents
Description
JavaScript Load Image is a library to load images provided as File
or Blob
objects or via URL
. It returns an optionally scaled, cropped or
rotated HTML img
or canvas
element.
It also provides methods to parse image metadata to extract
IPTC and
Exif tags as well as embedded thumbnail
images, to overwrite the Exif Orientation value and to restore the complete
image header after resizing.
Setup
Install via NPM:
npm install blueimp-load-image
Include the (combined and minified) JavaScript Load Image script in your HTML
markup:
<script src="js/load-image.all.min.js"></script>
Or alternatively, choose which components you want to include:
<script src="js/load-image.js"></script>
<script src="js/load-image-scale.js"></script>
<script src="js/load-image-meta.js"></script>
<script src="js/load-image-fetch.js"></script>
<script src="js/load-image-orientation.js"></script>
<script src="js/load-image-exif.js"></script>
<script src="js/load-image-exif-map.js"></script>
<script src="js/load-image-iptc.js"></script>
<script src="js/load-image-iptc-map.js"></script>
Usage
Image loading
In your application code, use the loadImage()
function like this:
document.getElementById('file-input').onchange = function (e) {
loadImage(
e.target.files[0],
function (img) {
document.body.appendChild(img)
},
{ maxWidth: 600 }
)
}
Or using the
Promise
based API like this:
document.getElementById('file-input').onchange = function (e) {
loadImage(e.target.files[0], { maxWidth: 600 }).then(function (data) {
document.body.appendChild(data.image)
})
}
Image scaling
It is also possible to use the image scaling functionality directly with an
existing image:
var scaledImage = loadImage.scale(
img,
{ maxWidth: 600 }
)
Requirements
The JavaScript Load Image library has zero dependencies, but benefits from the
following two
polyfills:
API
Callback
Function signature
The loadImage()
function accepts a
File or
Blob object or an image
URL as first argument.
If a File or
Blob is passed as
parameter, it returns an HTML img
element if the browser supports the
URL API, alternatively a
FileReader object
if the FileReader
API is supported, or false
.
It always returns an HTML
img element
when passing an image URL:
var loadingImage = loadImage(
'https://example.org/image.png',
function (img) {
document.body.appendChild(img)
},
{ maxWidth: 600 }
)
Canceling event handling
The img
element or
FileReader object
returned by the loadImage()
function allows to cancel event handling by
setting the onload
and onerror
event handlers to null:
var loadingImage = loadImage(
'https://example.org/image.png',
function (img) {
document.body.appendChild(img)
},
{ maxWidth: 600 }
)
loadingImage.onload = loadingImage.onerror = null
Callback arguments
For the callback style API, the second argument to loadImage()
must be a
callback
function, which is called when the image has been loaded or an error
occurred while loading the image.
The callback function is passed two arguments:
- An HTML img
element or
canvas
element, or an
Event object of
type
error
. - An object with the original image dimensions as properties and potentially
additional metadata.
loadImage(
fileOrBlobOrUrl,
function (img, data) {
document.body.appendChild(img)
console.log('Original image width: ', data.originalWidth)
console.log('Original image height: ', data.originalHeight)
},
{ maxWidth: 600, meta: true }
)
Please note:
The original image dimensions reflect the natural width and height of the loaded
image before applying any transformation.
For consistent values across browsers, metadata parsing has
to be enabled via meta:true
, so loadImage
can detect automatic image
orientation and normalize the dimensions.
Error handling
Example code implementing error handling:
loadImage(
fileOrBlobOrUrl,
function (img, data) {
if (img.type === 'error') {
console.error('Error loading image file')
} else {
document.body.appendChild(img)
}
},
{ maxWidth: 600 }
)
Promise
If the loadImage()
function is called without a callback
function as second
argument and the
Promise
API is available, it returns a Promise
object:
loadImage(fileOrBlobOrUrl, { maxWidth: 600, meta: true })
.then(function (data) {
document.body.appendChild(data.image)
console.log('Original image width: ', data.originalWidth)
console.log('Original image height: ', data.originalHeight)
})
.catch(function (err) {
console.log(err)
})
The Promise
resolves with an object with the following properties:
image
: An HTML
img or
canvas element.originalWidth
: The original width of the image.originalHeight
: The original height of the image.
Please also read the note about original image dimensions normalization in the
callback arguments section.
If metadata has been parsed, additional properties might be
present on the object.
If image loading fails, the Promise
rejects with an
Event object of type
error
.
Options
The optional options argument to loadImage()
allows to configure the image
loading.
It can be used the following way using the callback style:
loadImage(
fileOrBlobOrUrl,
function (img) {
document.body.appendChild(img)
},
{
maxWidth: 600,
maxHeight: 300,
minWidth: 100,
minHeight: 50,
canvas: true
}
)
Or the following way with the Promise
based API:
loadImage(fileOrBlobOrUrl, {
maxWidth: 600,
maxHeight: 300,
minWidth: 100,
minHeight: 50,
canvas: true
}).then(function (data) {
document.body.appendChild(data.image)
})
All settings are optional. By default, the image is returned as HTML img
element without any image size restrictions.
maxWidth
Defines the maximum width of the img
/canvas
element.
maxHeight
Defines the maximum height of the img
/canvas
element.
minWidth
Defines the minimum width of the img
/canvas
element.
minHeight
Defines the minimum height of the img
/canvas
element.
sourceWidth
The width of the sub-rectangle of the source image to draw into the destination
canvas.
Defaults to the source image width and requires canvas: true
.
sourceHeight
The height of the sub-rectangle of the source image to draw into the destination
canvas.
Defaults to the source image height and requires canvas: true
.
top
The top margin of the sub-rectangle of the source image.
Defaults to 0
and requires canvas: true
.
right
The right margin of the sub-rectangle of the source image.
Defaults to 0
and requires canvas: true
.
bottom
The bottom margin of the sub-rectangle of the source image.
Defaults to 0
and requires canvas: true
.
left
The left margin of the sub-rectangle of the source image.
Defaults to 0
and requires canvas: true
.
contain
Scales the image up/down to contain it in the max dimensions if set to true
.
This emulates the CSS feature
background-image: contain.
cover
Scales the image up/down to cover the max dimensions with the image dimensions
if set to true
.
This emulates the CSS feature
background-image: cover.
aspectRatio
Crops the image to the given aspect ratio (e.g. 16/9
).
Setting the aspectRatio
also enables the crop
option.
pixelRatio
Defines the ratio of the canvas pixels to the physical image pixels on the
screen.
Should be set to
window.devicePixelRatio
unless the scaled image is not rendered on screen.
Defaults to 1
and requires canvas: true
.
downsamplingRatio
Defines the ratio in which the image is downsampled (scaled down in steps).
By default, images are downsampled in one step.
With a ratio of 0.5
, each step scales the image to half the size, before
reaching the target dimensions.
Requires canvas: true
.
imageSmoothingEnabled
If set to false
,
disables image smoothing.
Defaults to true
and requires canvas: true
.
imageSmoothingQuality
Sets the
quality of image smoothing.
Possible values: 'low'
, 'medium'
, 'high'
Defaults to 'low'
and requires canvas: true
.
crop
Crops the image to the maxWidth
/maxHeight
constraints if set to true
.
Enabling the crop
option also enables the canvas
option.
orientation
Transform the canvas according to the specified Exif orientation, which can be
an integer
in the range of 1
to 8
or the boolean value true
.
When set to true
, it will set the orientation value based on the EXIF data of
the image, which will be parsed automatically if the Exif extension is
available.
Exif orientation values to correctly display the letter F:
1 2
██████ ██████
██ ██
████ ████
██ ██
██ ██
3 4
██ ██
██ ██
████ ████
██ ██
██████ ██████
5 6
██████████ ██
██ ██ ██ ██
██ ██████████
7 8
██ ██████████
██ ██ ██ ██
██████████ ██
Setting orientation
to true
enables the canvas
and meta
options, unless
the browser supports automatic image orientation (see
browser support for image-orientation).
Setting orientation
to 1
enables the canvas
and meta
options if the
browser does support automatic image orientation (to allow reset of the
orientation).
Setting orientation
to an integer in the range of 2
to 8
always enables
the canvas
option and also enables the meta
option if the browser supports
automatic image orientation (again to allow reset).
meta
Automatically parses the image metadata if set to true
.
If metadata has been found, the data object passed as second argument to the
callback function has additional properties (see
metadata parsing).
If the file is given as URL and the browser supports the
fetch API or the
XHR
responseType
blob
, fetches the file as Blob
to be able to parse the metadata.
canvas
Returns the image as
canvas element if
set to true
.
crossOrigin
Sets the crossOrigin
property on the img
element for loading
CORS enabled images.
noRevoke
By default, the
created object URL
is revoked after the image has been loaded, except when this option is set to
true
.
Metadata parsing
If the Load Image Meta extension is included, it is possible to parse image meta
data automatically with the meta
option:
loadImage(
fileOrBlobOrUrl,
function (img, data) {
console.log('Original image head: ', data.imageHead)
console.log('Exif data: ', data.exif)
console.log('IPTC data: ', data.iptc)
},
{ meta: true }
)
Or alternatively via loadImage.parseMetaData
, which can be used with an
available File
or Blob
object as first argument:
loadImage.parseMetaData(
fileOrBlob,
function (data) {
console.log('Original image head: ', data.imageHead)
console.log('Exif data: ', data.exif)
console.log('IPTC data: ', data.iptc)
},
{
maxMetaDataSize: 262144
}
)
Or using the
Promise
based API:
loadImage
.parseMetaData(fileOrBlob, {
maxMetaDataSize: 262144
})
.then(function (data) {
console.log('Original image head: ', data.imageHead)
console.log('Exif data: ', data.exif)
console.log('IPTC data: ', data.iptc)
})
The Metadata extension adds additional options used for the parseMetaData
method:
maxMetaDataSize
: Maximum number of bytes of metadata to parse.disableImageHead
: Disable parsing the original image head.disableMetaDataParsers
: Disable parsing metadata (image head only)
Image head
Resized JPEG images can be combined with their original image head via
loadImage.replaceHead
, which requires the resized image as Blob
object as
first argument and an ArrayBuffer
image head as second argument.
With callback style, the third argument must be a callback
function, which is
called with the new Blob
object:
loadImage(
fileOrBlobOrUrl,
function (img, data) {
if (data.imageHead) {
img.toBlob(function (blob) {
loadImage.replaceHead(blob, data.imageHead, function (newBlob) {
})
}, 'image/jpeg')
}
},
{ meta: true, canvas: true, maxWidth: 800 }
)
Or using the
Promise
based API like this:
loadImage(fileOrBlobOrUrl, { meta: true, canvas: true, maxWidth: 800 })
.then(function (data) {
if (!data.imageHead) throw new Error('Could not parse image metadata')
return new Promise(function (resolve) {
data.image.toBlob(function (blob) {
data.blob = blob
resolve(data)
}, 'image/jpeg')
})
})
.then(function (data) {
return loadImage.replaceHead(data.blob, data.imageHead)
})
.then(function (blob) {
})
.catch(function (err) {
console.error(err)
})
Please note:
Blob
objects of resized images can be created via
canvas.toBlob.
blueimp-canvas-to-blob
provides a polyfill for browsers without native
canvas.toBlob
support.
Exif parser
If you include the Load Image Exif Parser extension, the argument passed to the
callback for parseMetaData
will contain the following additional properties if
Exif data could be found in the given image:
exif
: The parsed Exif tagsexifOffsets
: The parsed Exif tag offsetsexifTiffOffset
: TIFF header offset (used for offset pointers)exifLittleEndian
: little endian order if true, big endian if false
The exif
object stores the parsed Exif tags:
var orientation = data.exif[0x0112]
The exif
and exifOffsets
objects also provide a get()
method to retrieve
the tag value/offset via the tag's mapped name:
var orientation = data.exif.get('Orientation')
var orientationOffset = data.exifOffsets.get('Orientation')
By default, only the following names are mapped:
If you also include the Load Image Exif Map library, additional tag mappings
become available, as well as three additional methods:
exif.getText()
exif.getName()
exif.getAll()
var orientationText = data.exif.getText('Orientation')
var name = data.exif.getName(0x0112)
var allTags = data.exif.getAll()
Exif Thumbnail
Example code displaying a thumbnail image embedded into the Exif metadata:
loadImage(
fileOrBlobOrUrl,
function (img, data) {
var exif = data.exif
var thumbnail = exif && exif.get('Thumbnail')
var blob = thumbnail && thumbnail.get('Blob')
if (blob) {
loadImage(
blob,
function (thumbImage) {
document.body.appendChild(thumbImage)
},
{ orientation: exif.get('Orientation') }
)
}
},
{ meta: true }
)
Exif IFD
Example code displaying data from the Exif IFD (Image File Directory) that
contains Exif specified TIFF tags:
loadImage(
fileOrBlobOrUrl,
function (img, data) {
var exifIFD = data.exif && data.exif.get('Exif')
if (exifIFD) {
console.log(exifIFD.getAll())
console.log(exifIFD.get('UserComment'))
}
},
{ meta: true }
)
GPSInfo IFD
Example code displaying data from the Exif IFD (Image File Directory) that
contains GPS info:
loadImage(
fileOrBlobOrUrl,
function (img, data) {
var gpsInfo = data.exif && data.exif.get('GPSInfo')
if (gpsInfo) {
console.log(gpsInfo.getAll())
console.log(gpsInfo.get('GPSLatitude'))
}
},
{ meta: true }
)
Interoperability IFD
Example code displaying data from the Exif IFD (Image File Directory) that
contains Interoperability data:
loadImage(
fileOrBlobOrUrl,
function (img, data) {
var interoperabilityData = data.exif && data.exif.get('Interoperability')
if (interoperabilityData) {
console.log(interoperabilityData.get('InteroperabilityIndex'))
}
},
{ meta: true }
)
Exif parser options
The Exif parser adds additional options:
disableExif
: Disables Exif parsing when true
.disableExifOffsets
: Disables storing Exif tag offsets when true
.includeExifTags
: A map of Exif tags to include for parsing (includes all but
the excluded tags by default).excludeExifTags
: A map of Exif tags to exclude from parsing (defaults to
exclude Exif
MakerNote
).
An example parsing only Orientation, Thumbnail and ExifVersion tags:
loadImage.parseMetaData(
fileOrBlob,
function (data) {
console.log('Exif data: ', data.exif)
},
{
includeExifTags: {
0x0112: true,
ifd1: {
0x0201: true,
0x0202: true
},
0x8769: {
0x9000: true
}
}
}
)
An example excluding Exif
MakerNote
and GPSInfo
:
loadImage.parseMetaData(
fileOrBlob,
function (data) {
console.log('Exif data: ', data.exif)
},
{
excludeExifTags: {
0x8769: {
0x927c: true
},
0x8825: true
}
}
)
Exif writer
The Exif parser extension also includes a minimal writer that allows to override
the Exif Orientation
value in the parsed imageHead
ArrayBuffer
:
loadImage(
fileOrBlobOrUrl,
function (img, data) {
if (data.imageHead && data.exif) {
loadImage.writeExifData(data.imageHead, data, 'Orientation', 1)
img.toBlob(function (blob) {
loadImage.replaceHead(blob, data.imageHead, function (newBlob) {
})
}, 'image/jpeg')
}
},
{ meta: true, orientation: true, canvas: true, maxWidth: 800 }
)
Please note:
The Exif writer relies on the Exif tag offsets being available as
data.exifOffsets
property, which requires that Exif data has been parsed from
the image.
The Exif writer can only change existing values, not add new tags, e.g. it
cannot add an Exif Orientation
tag for an image that does not have one.
IPTC parser
If you include the Load Image IPTC Parser extension, the argument passed to the
callback for parseMetaData
will contain the following additional properties if
IPTC data could be found in the given image:
iptc
: The parsed IPTC tagsiptcOffsets
: The parsed IPTC tag offsets
The iptc
object stores the parsed IPTC tags:
var objectname = data.iptc[5]
The iptc
and iptcOffsets
objects also provide a get()
method to retrieve
the tag value/offset via the tag's mapped name:
var objectname = data.iptc.get('ObjectName')
By default, only the following names are mapped:
If you also include the Load Image IPTC Map library, additional tag mappings
become available, as well as three additional methods:
iptc.getText()
iptc.getName()
iptc.getAll()
var keywords = data.iptc.getText('Keywords')
var name = data.iptc.getName(5)
var allTags = data.iptc.getAll()
IPTC parser options
The IPTC parser adds additional options:
disableIptc
: Disables IPTC parsing when true.disableIptcOffsets
: Disables storing IPTC tag offsets when true
.includeIptcTags
: A map of IPTC tags to include for parsing (includes all but
the excluded tags by default).excludeIptcTags
: A map of IPTC tags to exclude from parsing (defaults to
exclude ObjectPreviewData
).
An example parsing only the ObjectName
tag:
loadImage.parseMetaData(
fileOrBlob,
function (data) {
console.log('IPTC data: ', data.iptc)
},
{
includeIptcTags: {
5: true
}
}
)
An example excluding ApplicationRecordVersion
and ObjectPreviewData
:
loadImage.parseMetaData(
fileOrBlob,
function (data) {
console.log('IPTC data: ', data.iptc)
},
{
excludeIptcTags: {
0: true,
202: true
}
}
)
License
The JavaScript Load Image library is released under the
MIT license.
Credits
- Original image metadata handling implemented with the help and contribution of
Achim Stöhr.
- Original Exif tags mapping based on Jacob Seidelin's
exif-js library.
- Original IPTC parser implementation by
Dave Bevan.