Saturday, July 6, 2013

Power of Two image resizer

This java app automatically resizes images to closest power of two making them suitable for OpenGL/GLES. Useful for mobile developers using OpenGLES.


Usage: java -jar ClosestPOTResizer.jar in.png OR in.jpg


Its just 7KB app. Runs on java 1.2 or above. The download package contains source code of the app and inside distributable folder the executable jar is present.

Download: ClosestPOTResizer.7z


Source code:

/* ##################################################### */

package closestpotresizer;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.IndexColorModel;
import java.io.File;
import java.io.FileInputStream;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;

/**
 *
 * @author Bindesh Kumar Singh
 * @contact bindeshkumarsingh@gmail.com
 * @website http://www.ourinnovativemind.in
 */

public class ClosestPOTResizer {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
//        System.out.println("" + POTResizer.getClosestPOT(500, false));
//        System.out.println("" + POTResizer.getClosestPOT(500, true));
        try {
            if (args.length < 1) {
                System.out.println("Usage: java -jar ClosestPOTResizer.jar \"in.png OR in.jpg\"");
                return;
            }
            POTResizer r = new POTResizer();
            r.resize(args[0]);
        } catch (Exception ex) {
            Logger.getLogger(ClosestPOTResizer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

}

class POTResizer {
   
    public void resize(final String infile) {
        try {
            BufferedImage img = ImageIO.read(new FileInputStream(infile));
           
            // get extension
            int len = infile.length();
            String extension = infile.substring( infile.lastIndexOf('.') + 1, len );
            String outfile = "POT_" + infile;
           
            // get current size
            int w = img.getWidth();
            int h = img.getHeight();

            // closest POT
            int potW = getClosestPOT(w, true);
            int potH = getClosestPOT(h, true);

            // resize to POT
            img = getScaled(img, potW, potH);

            // save resized image
            storeImage(img, new File(outfile), extension, 0.9f);

        } catch (Exception exp) {
            Logger.getLogger(POTResizer.class.getName()).log(Level.SEVERE, null, exp);
        }
    }

    public boolean storeImage(BufferedImage bi, File outputFile, String extension, float quality) {
        // e.g. storeImage( image, new File( "file.png" ), BufferedImageUtil.IMAGETYPE_PNG, 0.8f);
        try {
            //reconstruct folder structure for image file output
            if (outputFile.getParentFile() != null && !outputFile.getParentFile().exists()) {
                outputFile.getParentFile().mkdirs();
            }
            if (outputFile.exists()) {
                outputFile.delete();
            }
            //get image file suffix
            //get registry ImageWriter for specified image suffix
            // BufferedImageUtil.IMAGETYPE_PNG, 0.8f)
            Iterator writers = ImageIO.getImageWritersBySuffix(extension);
            ImageWriter imageWriter = (ImageWriter) writers.next();
            //set image output params
            ImageWriteParam params = new JPEGImageWriteParam(null);
            params.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            params.setCompressionQuality(quality);
            params.setProgressiveMode(javax.imageio.ImageWriteParam.MODE_DISABLED);
            params.setDestinationType(new ImageTypeSpecifier(IndexColorModel
                    .getRGBdefault(), IndexColorModel.getRGBdefault()
                    .createCompatibleSampleModel(16, 16)));
            //writer image to file
            ImageOutputStream imageOutputStream = ImageIO
                    .createImageOutputStream(outputFile);
            imageWriter.setOutput(imageOutputStream);
            imageWriter.write(null, new IIOImage(bi, null, null), params);
            imageOutputStream.close();
            imageWriter.dispose();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    static public int getClosestPOT(int number, boolean higher) {
        int ret = 2;
        while (ret < number) {
            ret *= 2;
            if (!higher && ret > number) {
                ret /= 2;
                return ret;
            }
        }
        return ret;
    }

    static public BufferedImage getScaled(BufferedImage img,
            int targetWidth,
            int targetHeight) {

        BufferedImage scaledImage = new BufferedImage(
                targetWidth, targetHeight, img.getType());// BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = scaledImage.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.drawImage(img, 0, 0, targetWidth - 1, targetHeight - 1, null);
        return scaledImage;
    }
   
   
}

/* ################################################### */



TAGS:
Power of two image converter resizer POT