Here is some code to convert a raw tiff image to a compressed one :

First remove the colors from the image

There are different ways to construct the target BufferedImage : with TYPE_BYTE_BINARY, we get a black and white image


        BufferedImage raw = ImageIO.read(new File("src/main/resources/strawberry.jpg"));
        BufferedImage img = new BufferedImage(
                raw.getWidth(),
                raw.getHeight(),
                BufferedImage.TYPE_BYTE_BINARY);

        Graphics2D graphic = img.createGraphics();
        graphic.drawImage(raw, 0, 0, Color.WHITE, null);
        graphic.dispose();

Compress the image

We can compress the image thanks to this code :

        Iterator<ImageWriter> tiff = ImageIO.getImageWritersByFormatName("TIFF");
        ImageWriter tiffImageWriter = tiff.next();
        TIFFImageWriteParam defaultWriteParam = new TIFFImageWriteParam(Locale.FRANCE);
        defaultWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        defaultWriteParam.setCompressionType("CCITT T.6");
        defaultWriteParam.setTIFFCompressor(new TIFFT6Compressor());

and one can adjust the metadata with that code :

 IIOMetadata metadata = createMetadata(tiffImageWriter, defaultWriteParam, 300);

 /*...*/

 private static IIOMetadata createMetadata(ImageWriter writer, ImageWriteParam writerParams, int resolution) throws
            IIOInvalidTreeException
    {
        // Get default metadata from writer
        ImageTypeSpecifier type = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY);
        IIOMetadata meta = writer.getDefaultImageMetadata(type, writerParams);

        // Convert default metadata to TIFF metadata
        TIFFDirectory dir = TIFFDirectory.createFromMetadata(meta);

        // Get {X,Y} resolution tags
        BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();
        TIFFTag tagXRes = base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION);
        TIFFTag tagYRes = base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION);

        // Create {X,Y} resolution fields
        TIFFField fieldXRes = new TIFFField(tagXRes, TIFFTag.TIFF_RATIONAL, 1, new long[][] { { resolution, 1 } });
        TIFFField fieldYRes = new TIFFField(tagYRes, TIFFTag.TIFF_RATIONAL, 1, new long[][] { { resolution, 1 } });

        // Add {X,Y} resolution fields to TIFFDirectory
        dir.addTIFFField(fieldXRes);
        dir.addTIFFField(fieldYRes);

        // Add unit field to TIFFDirectory (change to RESOLUTION_UNIT_CENTIMETER if necessary)
        dir.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_INCH));

        // Return TIFF metadata so it can be picked up by the IIOImage
        return dir.getAsMetadata();
    }

And then save the image with that snippet:

        FileOutputStream output = new FileOutputStream(target);
        ImageOutputStream ios = ImageIO.createImageOutputStream(output);
        tiffImageWriter.setOutput(ios);
        tiffImageWriter.write(null, new IIOImage(img, null, metadata), defaultWriteParam);
        //tiffImageWriter.write(img);

        ios.flush();
        output.flush();
        ios.close();

the original image :

will become :

compressed.tiff

Complete Code


import com.github.jaiimageio.impl.plugins.tiff.TIFFT6Compressor;
import com.github.jaiimageio.plugins.tiff.*;

import javax.imageio.*;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;

public class Main {

    public static void main(String[] args) throws IOException {

        BufferedImage raw = ImageIO.read(new File("src/main/resources/strawberry.jpg"));
        BufferedImage img = new BufferedImage(
                raw.getWidth(),
                raw.getHeight(),
                BufferedImage.TYPE_BYTE_BINARY);

        Graphics2D graphic = img.createGraphics();
        graphic.drawImage(raw, 0, 0, Color.WHITE, null);
        graphic.dispose();
        String target = "src/main/resources/compressed.tiff";

        Iterator<ImageWriter> tiff = ImageIO.getImageWritersByFormatName("TIFF");
        ImageWriter tiffImageWriter = tiff.next();
        TIFFImageWriteParam defaultWriteParam = new TIFFImageWriteParam(Locale.FRANCE);
        defaultWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        defaultWriteParam.setCompressionType("CCITT T.6");
        defaultWriteParam.setTIFFCompressor(new TIFFT6Compressor());
//        ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY);
//        IIOMetadata metadata = tiffImageWriter.getDefaultImageMetadata(typeSpecifier, defaultWriteParam);
//
//        setDPI(metadata);

        IIOMetadata metadata = createMetadata(tiffImageWriter, defaultWriteParam, 300);

        FileOutputStream output = new FileOutputStream(target);
        ImageOutputStream ios = ImageIO.createImageOutputStream(output);
        tiffImageWriter.setOutput(ios);
        tiffImageWriter.write(null, new IIOImage(img, null, metadata), defaultWriteParam);
        //tiffImageWriter.write(img);

        ios.flush();
        output.flush();
        ios.close();

        //ImageIO.write(img, "tiff", new File(target));

    }

    private static IIOMetadata createMetadata(ImageWriter writer, ImageWriteParam writerParams, int resolution) throws
            IIOInvalidTreeException
    {
        // Get default metadata from writer
        ImageTypeSpecifier type = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY);
        IIOMetadata meta = writer.getDefaultImageMetadata(type, writerParams);

        // Convert default metadata to TIFF metadata
        TIFFDirectory dir = TIFFDirectory.createFromMetadata(meta);

        // Get {X,Y} resolution tags
        BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();
        TIFFTag tagXRes = base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION);
        TIFFTag tagYRes = base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION);

        // Create {X,Y} resolution fields
        TIFFField fieldXRes = new TIFFField(tagXRes, TIFFTag.TIFF_RATIONAL, 1, new long[][] { { resolution, 1 } });
        TIFFField fieldYRes = new TIFFField(tagYRes, TIFFTag.TIFF_RATIONAL, 1, new long[][] { { resolution, 1 } });

        // Add {X,Y} resolution fields to TIFFDirectory
        dir.addTIFFField(fieldXRes);
        dir.addTIFFField(fieldYRes);

        // Add unit field to TIFFDirectory (change to RESOLUTION_UNIT_CENTIMETER if necessary)
        dir.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_INCH));

        // Return TIFF metadata so it can be picked up by the IIOImage
        return dir.getAsMetadata();
    }

Previous Post Next Post