File format conversion within Apps Scripts
Introduction
Working on a recent Apps Scripts project, I had the need to convert images from whatever format I found them in into BMP format.
Wait… BMP format? Yes, seriously. Well, I didn’t have to but it actually turned out to be the easiest way to achieve what I needed: I wanted to manipulate images at a pixel level, and whilst the PNG spec turned out to be really readable and not too hard to implement, BMP was still plain easier for getting quickly to pixel data.
So, pained as I was to use the BMP format, this was a perfect opportunity to use
the power of the Blob
class, to get some conversion for free.
Format conversion with Blobs
Apps Scripts provides a class, the Blob
,
which can be used for converting data between one format and another.
In addition to this class, a range of other Apps Scripts objects implement the
the BlobSource
interface
which allows them to be used as the source of a conversion from one format to
another.
In either case, conversion can be achieved by:
var newFormatBlob = myBlobSource.getAs('<mimetype>');
If the object being converted can be converted to the new format, then that’s all! (If the conversion doesn’t make sense, like converting a zip file to a PNG, an error will be thrown.)
Converting images
So, as you’ll recall, I needed to convert a range of images to BMP. These images happened to be located online. The solution I ended up using was roughly the following:
/**
* @param {string} url The URL of the image.
* @param {string} destMimeType The MIME type for the converted image.
* @return {Blob} The converted image.
* @throws {Error} On fetch failure or conversion failure.
*/
function convertImage(url, destMimeType) {
var data = UrlFetchApp.fetch(url);
var contentType = data.getHeaders()['Content-Type'];
var image = Utilities.newBlob(data.getContent(), contentType);
var convertedImage = image.getAs(destMimeType);
return convertedImage;
}
function main() {
var bmp = convertImage('http://example.com/hello.jpg', MimeType.BMP);
// ... do something with my BMP ...
}
The only addition here from what I’ve already described is that the
Utilities
class provides the means to create a Blob
from a Byte[]
array through the use
of newBlob
Simplifying conversion
As it turns out, this process can be simplfied: HTTPResponse
,
as returned from
UrlFetchApp.fetch
implements the BlobSource
interface - how epic is that? So we can instead write:
/**
* @param {string} url The URL of the image.
* @param {string} destMimeType The MIME type for the converted image.
* @return {Blob} The converted image.
* @throws {Error} On fetch failure or conversion failure.
*/
function convertImage(url, destMimeType) {
var data = UrlFetchApp.fetch(url);
var convertedImage = data.getAs(destMimeType);
return convertedImage;
}
as HTTPResponse
is capable of of converting the content of the response
directly to an image. No need to extract the MIME type from the headers or
provide an array of bytes.
Conclusion
The BlobSource
interface is a really nice feature within Apps Scripts. If
there is one complaint, it is that beyond images, some of the conversions you
might expect between various document formats, don’t appear to work so readily.
I hope that in the future, further conversions are added, and further
classes choose to implement BlobSource
.
And that I can avoid working with BMPs in the future too…