Facebook Spectrum is a new open-source image processing library for iOS and Android that aims to make the upload process for images more efficient and reliable, striving for the best balance between image quality and file size.
As mobile camera hardware rapidly improves, our phones capture and store larger and larger files. Uploading these large files can eat up mobile data; it can take forever for them to load; and, sometimes, the files fail to load at all.
Additionally, uploading large images is often simply wasteful, since the image will be often resized for the recipient. For these reasons, the approach that Spectrum follows is transcoding the image on the device before uploading it. This consists in applying a list of transformations, called “recipes”, in accordance to the image format and the developer’s quality requirements. So, for each image, the library will scan the recipe and select the most efficient, possibly lossless “recipe” for the requested operation, such as uploading or cropping and rotating.
Resizing an image, which is the most important factor to affect the final image size, can be accomplished by using sampling or interpolation techniques, and Spectrum is able to determine which technique to apply based on the kind of transformation required. For example, sampling is always more efficient than interpolation but can be applied only for given ratios of input and output image sizes. To allow for the selection of the most efficient techniques in a larger number of cases, Spectrum supports the specification of approximate output image size, such as “exact or smaller” and “exact or larger”. This makes it possible to adjust the output image size in a way that, for example, sampling can be used.
This is an example of how you can transcode an image for upload using Spectre:
FSPEncodeRequirement *encodeRequirement =
[FSPEncodeRequirement encodeRequirementWithFormat:FSPEncodedImageFormat.jpeg
mode:FSPEncodeRequirementModeLossy
quality:80];
FSPTransformations *transformations = [FSPTransformations new];
transformations.resizeRequirement =
[[FSPResizeRequirement alloc] initWithMode:FSPResizeRequirementModeExactOrSmaller
targetSize:CGSizeMake(2048, 2048)];
FSPEncodeOptions *options =
[FSPEncodeOptions encodeOptionsWithEncodeRequirement:encodeRequirement
transformations:transformations
metadata:nil
configuration:nil
outputPixelSpecificationRequirement:nil];
NSError *error;
FSPResultData *result = [FSPSpectrum.sharedInstance encodeImage:image options:options error:&error];
As you can see from the code above, you can encode a JPEG image by specifying the format and the required quality level, whether lossy or lossless and any attribute relative to the image format, and a set of desired transformations, such as scaling down. You do not need to provide any low-level detail about how the transcoding should be carried through.
Spectrum is written around a C++ core and provides Java and Objective-C APIs. It supports images in JPEG, PNG, and WebP format and uses native libraries such as MozJpeg and libpng for finer-grained control of image encoding beyond what supported by the general purpose platform APIs. You can download it from GitHub.