Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Split Images Into Small, Medium, and High Resolutions With a Backendless API Service

DZone's Guide to

How to Split Images Into Small, Medium, and High Resolutions With a Backendless API Service

To improve performance, control how much bandwidth your application uses by splitting your images into different resolutions with an API service.

· Performance Zone ·
Free Resource

Sensu is an open source monitoring event pipeline. Try it today.

Images displayed in your app often may be responsible for the bandwidth consumed by the device, which has a direct impact on the performance, battery level and the amount of memory which the app allocates. As a result, optimizing images can often bring noticeable performance improvements for your app: the fewer bytes it needs to download, the smaller impact is on the client's bandwidth and the faster app will download and render content on the screen.

Let's imagine you have an app where you store pictures to show them to your app's users. But what happens if the resolution of these images is high and they are taking a lot of space? Download of these files is time-consuming and, as a result, it slows down your app making the user experience substandard.

A recommended approach is to create image thumbnails with lower resolutions relative to the original one. These thumbnails can be used to preview the image in the application.

The thumbnails can be generated using Backendless API Services (the Business Logic section). If you are not familiar with how to create your own API Service, please check the How to generate a QR code with Backendless API Service post, which describes the process of API service creation in greater detail.

In this article, we will focus on the task of generating thumbnail images with different resolutions.

Below is the source code for the service which performs the task:

import com.backendless.Backendless;
import com.backendless.servercode.BackendlessService;
 
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
 
 
@BackendlessService
public class ImageResizer
{
 private static final double coefficient_1 = 0.75;
 private static final double coefficient_2 = 0.5;
 private static final double coefficient_3 = 0.25;
 private static final String repoStartPath = "/files/";
 
 public void resizeImage( String imageId ) throws IOException
 {
   // retrieving record from table 'images' from Backendless Data
   Map<String, Object> imageData = Backendless.Data.of( "images" ).findById( imageId );
   String stringUrl = (String) imageData.get( "original" );
 
   // parse url to retrieve file name and path (for saving in Backendless Files)
   URL imageUrl = new URL( stringUrl );
   String fullPath = imageUrl.getPath();
   String srcFileName = fullPath.substring( fullPath.lastIndexOf( '/' ) + 1 );
   String path = fullPath.substring( fullPath.indexOf( repoStartPath ) + repoStartPath.length(), fullPath.lastIndexOf( srcFileName ) - 1 );
 
   final String baseFileName = srcFileName.substring( 0, srcFileName.lastIndexOf( '.' ) );
 
   // read image in memory
   BufferedImage srcImg = ImageIO.read( imageUrl );
 
   // resize images with different coefficients
   BufferedImage img1 = getScaledImage( srcImg, coefficient_1 );
   String outputFileName = baseFileName + "__1.jpeg";
   saveImage( img1, path, outputFileName );
 
   BufferedImage img2 = getScaledImage( srcImg, coefficient_2 );
   outputFileName = baseFileName + "__2.jpeg";
   saveImage( img2, path, outputFileName );
 
   BufferedImage img3 = getScaledImage( srcImg, coefficient_3 );
   outputFileName = baseFileName + "__3.jpeg";
   saveImage( img3, path, outputFileName );
 }
 
 private BufferedImage getScaledImage( BufferedImage srcImg, double coefficient )
 {
   int targetWidth = (int) Math.round( srcImg.getWidth() * coefficient );
   int targetHeight = (int) Math.round( srcImg.getHeight() * coefficient );
 
   BufferedImage resizedImg = new BufferedImage( targetWidth, targetHeight, Transparency.OPAQUE );
 
   Graphics2D g2 = resizedImg.createGraphics();
   g2.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC );
   g2.drawImage( srcImg, 0, 0, targetWidth, targetHeight, null );
   g2.dispose();
 
   return resizedImg;
 }
 
 private void saveImage( BufferedImage bufImg, String path, String fileName ) throws IOException
 {
   ImageWriter imageWriter = ImageIO.getImageWritersByFormatName( "jpeg" ).next();
 
   ImageWriteParam param = imageWriter.getDefaultWriteParam();
   param.setCompressionMode( ImageWriteParam.MODE_EXPLICIT );
   param.setCompressionQuality( 0.9F ); // set quality
 
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   imageWriter.setOutput( ImageIO.createImageOutputStream( baos ) );
   imageWriter.write( null, new IIOImage( bufImg, null, null ), param );
 
   Backendless.Files.saveFile( path, fileName, baos.toByteArray() );
   baos.close();
 }
}


We would also need at least one image file for testing. So, let's just go to the directory: Files section and upload a test picture into the images directory:

Once it is done, go to the Data section and create the table with two fields:

column name: name , data type STRING   

column name: original , data type FILE REFERENCE  

Switch to the DATA BROWSER section and create a new object as shown below. The original column must contain a file reference to the file for which the thumbnails will be generated by the service:

Now run CodeRunner in the debug mode and try your service in action using the API Services section of the Business Logic screen:

the imageId argument is an objectId of the record in the images table.

And here is the result:

As you can see, the newly created images have different file sizes, and you can use any of those thumbnail types for the preview purposes in your app.

Sensu: workflow automation for monitoring. Learn more—download the whitepaper.

Topics:
server code ,api services ,performance ,tutorial ,images ,resolution

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}