Question

I'm wondering if anyone knows of a way to force Android to create indexed-color PNG files with it's compress function.

For example:

    InputStream FIS = ...
    BitmapFactory.Options opt = new BitmapFactory.Options();
    opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
    opt.inScaled = false;
    Bitmap img = BitmapFactory.decodeStream(FIS, null, opt);

    // Resize
    float scale = 0.8f;
    Matrix matrix = new Matrix();
    matrix.postScale(scale, scale);
    Bitmap scaledBitmap = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
    img = null; // Free

    // Write
    File sdCard = Environment.getExternalStorageDirectory();
    File dir = new File(sdCard.getAbsolutePath() + "/scaled/");
    FileOutputStream FOS = new FileOutputStream(new File(dir, "out.png"));
    scaledBitmap.compress(Bitmap.CompressFormat.PNG, 100, FOS);
    scaledBitmap = null; // Free

This code opens a PNG file, resizes it to 80% and saves it to the SD Card. The resulting image is, indeed, scaled to 80%, but the resulting file size is almost 5x the size of the original.

-rw-rw-r-- 1 user user  55878 Sep 10 19:00 8500_001.2B.png  <- Input
-rwxr--r-- 1 user user 245933 Sep 10 21:49 out.png          <- Output

The reason for this is because the original file is using indexed-color (PseudoClass), not true color (DirectClass). [1]

$ identify 8500_001.2B.png
8500_001.2B.png PNG 1712x2200 1712x2200+0+0 8-bit PseudoClass 2c 55.9KB 0.000u 0:00.000

$ identify out.png
out.png PNG 1370x1760 1370x1760+0+0 8-bit DirectClass 246KB 0.000u 0:00.000

ImageMagick is smart enough to encode the original bicolor image using indexed-color and a two-color colormap. That file after being opened, scaled and re-encoded in Android does not do that, but rather uses true color for each of the pixels and results in a much larger file size.

Questions

  1. Does anyone know if there is a way to force the standard Android library to compress the file using a colormap?
  2. If not, does anyone know if there are any pure-java implementations that would accomplish just those 3 tasks (decode, scale, encode)?

Thanks in advance.

[1] The PNG Specification

Was it helpful?

Solution

does anyone know if there are any pure-java implementations

Yes, with pngj library. Its a plain .jar library.

Take a look at here: Create Index PNG with PNGJ 2.1.1

For some java samples, here's one java application: NeatoCode Techniques by Lance Nanek

OTHER TIPS

It might be possible to use pngj a java library that can saved indexed pngs.

http://code.google.com/p/pngj/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top