Thursday, December 15, 2011

Read Properties of all pages (available images) from multi-page TIFF image:

         After a long time (almost after 2 year) I am writing on this topic and (to be honest) not in touch with the topic now, so if I miss something which is important for you or help something related to your task then you can ask me in the comment section or you can write me on my email address.  I will definitely try (my best) to resolve your issue and get back to you with some solution.  (I hope there are number of topics available for this on internet now and you can get the solution from some other places also.)

 Here we START our work (with some basics):
As we already know that each page which is available inside the multi-page TIFF file contains its own property in it (as an image metadata).  Here I am going to share with you a sample code for “How to read all the available properties of each page from its metadata?”  The properties presence in metadata gives you the exact information about the image.  Sometime when we work on some image part there we need to get this data and process our part of work accordingly.  If we know this (metadata) information (input image) then we can easily maintain the quality of image (output) as per our original one. 

:: List of Image Properties (just for your information):
  1. Image Width
  2. Image Length
  3. Bits Per Sample
  4. Compression
  5. Photometric Interpretation
  6. Image Description
  7. Strip Offsets
  8. Orientation
  9. Samples Per Pixel
  10. Rows Per Strip
  11. Strip Byte Counts
  12. X-Resolution
  13. Y-Resolution
  14. Planar Configuration
  15. Resolution Unit etc.


Process Description:

It’s a very simple code to get these properties from an individual page (or you can say “image”).  Even if you don’t know or don’t want to remember all property names “Not an Issue”.  By default you will get this list of information from image metadata.  Its come in a set (from metadata of operational image).  You just need to focus on your part i.e. which one (property) is important for you and how to fetch it from this bunch.   Once you get this information you can able to set your output image property with the same values. (Anyway, this is another topic to consider and you can get it as per your requirements.  If you want to get any particular field from property of image you can use the field tag number to get that information.).


Reading image Metadata (Properties):

(Need to) Import Packages:

java.io.File;
java.io.FileNotFoundException;
java.io.IOException;
java.util.Iterator;

javax.imageio.ImageIO;
javax.imageio.ImageReadParam;
javax.imageio.ImageReader;
javax.imageio.metadata.IIOMetadata;
javax.imageio.stream.FileImageInputStream;
javax.imageio.stream.ImageInputStream;

com.sun.media.imageio.plugins.tiff.TIFFDirectory;
com.sun.media.imageio.plugins.tiff.TIFFField;
com.sun.media.jai.codec.FileSeekableStream;
com.sun.media.jai.codec.ImageCodec;
com.sun.media.jai.codec.ImageDecoder;

(Use Google to search related API for detailed information.  I know you can get these packages and APIs from internet. or simply click on the reference link below  J  )

Source Code:
Here only one method which I use for this and really nothing special in it. J   You can get the idea about source code from comments.


Method:

public void readTiffImageProperties(String inputTifImagePath) {
Iterator readersIterator = ImageIO.getImageReadersByFormatName("tif");
ImageReader imageReader = (ImageReader)readersIterator.next();
ImageInputStream imageInputStream;
try {
imageInputStream = new FileImageInputStream(new File(inputTifImagePath));
imageReader.setInput(imageInputStream,false, true);
           
/* Take a input from a file */
FileSeekableStream fileSeekableStream;
fileSeekableStream = new FileSeekableStream(inputTifImagePath);
                 
/* create ImageDecoder to count your pages from multi-page tiff */
ImageDecoder iDecoder = ImageCodec.createImageDecoder("tiff", fileSeekableStream, null);
                 
/* count the number of pages inside the multi-page tiff */
int pageCount = iDecoder.getNumPages();
                 
/* use first for loop to get pages one by one */
for(int page = 0; page < pageCount; page++){
/* get image metadata for each page */
IIOMetadata imageMetadata = imageReader.getImageMetadata(page);
                       
/*
 * The root of all the tags for this image is the IFD (Image File Directory).
 * Get the IFD from where we can get all the tags for the image.
 */
TIFFDirectory ifd = TIFFDirectory.createFromMetadata(imageMetadata);
                       
/* Create a Array of TIFFField*/
TIFFField[] allTiffFields = ifd.getTIFFFields();
                       
/* use second for loop to get all field data */
for (int i = 0; i < allTiffFields.length; i++) {
TIFFField tiffField = allTiffFields[i];
                             
/* name of property */
String nameOfField = tiffField.getTag().getName();
                             
/* Tag no. of the property (optional) */
int numberOfField = tiffField.getTagNumber();
                             
/* Type of property (optional) */
String typeOfField = TIFFField.getTypeName(tiffField.getType());
                             
/* Value of Property*/
String valueOfField = tiffField.getValueAsString(0);
                             
/* print it down as per your way */
System.out.println((i+1)+". " + nameOfField + ", " + numberOfField + ", " + typeOfField + ", " + valueOfField);
}
/* just for separate between two page (image) property */
            System.out.println("======================================");
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}


What more you need to do:
  • Create a java file.  (Let’s assume the name of class is TIFFPageProperties or you can go with your conventions)
  • Copy and paste the methods inside (“TIFFPageProperties”/?) java class
  • Write a main method which will pass a parameter to readTiffImageProperties method.  Pass the Tiff image file path as a parameter to this method.
  • Compile and Run the code


References:
Java SE Technical Documentation: Oracle Java Docs - javase

Note:  For detailed information visit Oracle documentation.  Any question or suggestions from your side are always welcome.




Wednesday, February 17, 2010

Image DPI setting

Here is the important topic of this blog.  How to create TIFF image using java code?  There are various options (APIs) available for tiff image creation using java technology.  You can do this with using different API’s available in java technology.

At the same time when we create the TIFF image, we need to take care of some image operation and information (i.e. image metadata).  We need to maintain the DPI of given image, horizontal and vertical scaling (height and width), maintain the metadata etc.  For this I divided the source code into different parts.  Later you can see the specific topics related to image operation, source code and its explanation.

Image DPI:

In this post I am giving an explanation of DPI setting of an image.  Whenever we do work with image processing one of the biggest things which we need to do is maintaining the DPI of that image or setting the DPI of image.  After converting image into BufferedImage, by default its density of dots per inches will set to 96 dpi.  Cause of this we can not maintain the quality of image.  Less DPI means reduce the density of dot per inches and it directly affect on image quality.  For this we need to set X and Y resolution in an image metadata.

JPEG image DPI setting:

Need to Import Packages:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;

(SUN Microsystems provided API details of above mentioned classes.  Use Google to search related API on SUN site for detailed information.)

Source Code:
  
Static Variables:
// static variable for value of X resolution
private static int X_DPI = 200;
// static variable for value of Y resolution
private static int Y_DPI = 200;


Method:
void setDPIOfAnInputJPGImage(File inputFile, File outputFile) {
        try {
            // create input buffered image
            BufferedImage image = ImageIO.read(inputFile);
            // create jpegEncode for output image
            JPEGImageEncoder jpegEncoder = JPEGCodec
                    .createJPEGEncoder(new FileOutputStream(outputFile));
            // create jpeg encoder from getting defaul value from input buffered
            // image
            JPEGEncodeParam jpegEncodeParam = jpegEncoder
                    .getDefaultJPEGEncodeParam(image);
            // setting up density unit paramter
            jpegEncodeParam
                    .setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
            // setting up jpeg encode parameter
            jpegEncoder.setJPEGEncodeParam(jpegEncodeParam);
            // set quality parameter
            jpegEncodeParam.setQuality(0.75f, false);
            // set X-resolution
            jpegEncodeParam.setXDensity(X_DPI);
            // set Y-resolution
            jpegEncodeParam.setYDensity(Y_DPI);
            // encode output image
            jpegEncoder.encode(image, jpegEncodeParam);
            // flush the buffer image
            image.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

What more you need to do:
- Create a java class
- Declare the static variable for resolution (DPI is totally depends on the value which provided by user i.e. value of X_DPI and Y_DPI)
- Copy and paste above method inside java class (setDPIOfAnInputJPGImage)
- Write a main method which will pass two File objects to the DPI setting method (first for input image and second for output image)
- Compile and Run the code

References:
Java Media API: http://java.sun.com/javase/technologies/desktop/media/

Note:  For detailed information visit SUN Microsystems.  Any query and suggestions from your side will always welcome.

Wednesday, January 27, 2010

TIFF page extraction using JAI (Java Advanced Imaging)

     One of the most important parts in TIFF image development is multi-page tiff image extraction.  For image processing work, there are number of 3rd party software available in today’s market.  But when things comes to the online image processing work that time, either you write to a code for image operations as per your requirements or use a 3rd party software which support your applications.  Use of 3rd party software is not a good way to develop your application.  This is the only reason I went for our own implementations.
   
     Working with the DMS (Document Management System) / Document Image Processing, Digital Photography, Defense or Intelligent etc. are always required the image operations.  Multi-page TIFF image extraction is not an important or required part of my DMS project.  But the knowledge of tiff image extraction is a good for future prospects.  There are some parts of the codes available for tiff extraction on web world (just need to do good Google search).  To implement imaging part I decided to go with JAI (Java  Advanced Imaging).  Next topic we will see the advantages of JAI over other imaging APIs.

    At the time of TIFF page extraction, the main thing which we need to care is output image quality.  For me, it’s not important work to extract the pages from tiff image.  Quality is hardly matters as per my requirements.  That’s why I only need to extract the pages in other image type like .jpeg or .png etc.  I had set and used both types for extraction, JPEG for color images and PNG for black and white (binary/bilevel) images.  To maintain the quality of output image means to set the metadata for that image.  e.g. setting DPI of image, bit depth, horizontal and vertical resolutions etc.  I used default metadata for output image which gives 96 dpi horizontal and vertical resolutions. 


JAI (Java Advanced Imaging):
Implements a set of core image processing capabilities.
Include image tiling, regions of interest, and deferred execution.
Offer a set of core image processing operators.
Support image processing using the Java programming Language.

Why JAI?:
JAI offers lots of advantages for developers.
Platform Independent:  JAI applications will run on any machine where Java Virtual Machine is available.  It follows the Java run time library model which provides the platform independence. 

Object-oriented programming:  The API of JAI is object oriented.  It follows the object instantiation, flow of process data, concept of subclasses and parent classes, etc.

High Performance:  Using device independency we can do different types of implementations.  Its possible using JAI API.

Distributed Imaging:  JAI is also well suited as a client-server imaging programming.  Without affecting an object, remote method invocation (RMI) allows java code on a client to invoke method calls which placed in another machine.


Need to Import Packages:
java.awt.image.RenderedImage;
java.awt.image.renderable.ParameterBlock;
javax.media.jai.JAI;
javax.media.jai.RenderedOp;
com.sun.media.jai.codec.FileSeekableStream;
com.sun.media.jai.codec.ImageCodec;
com.sun.media.jai.codec.ImageDecoder;
com.sun.media.jai.codec.SeekableStream;
java.io.File;
java.io.IOException;

(SUN Microsystems offers detailed API of above mentioned classes.  Use Google to search related API on SUN site for detailed information.)

Source Code:
/*
 * Method for extraction
 * tiffFilePath: path of input tiff image
 * outputFileType: ouput image type (for color
 * image “jpeg” and for bilevel image “png”)
 */
public static void extractMultiPageTiff(String tiffFilePath,
    String outputFileType) throws IOException {

    /*
     * create object of RenderedIamge to produce
     * image data in form of Rasters
     */
    RenderedImage renderedImage[], page;
    File file = new File(tiffFilePath);
    /*
     * SeekabaleStream is use for taking input from file.
     * FileSeekableStream is not committed part of JAI API.
     */
    SeekableStream seekableStream = new FileSeekableStream(file);
    ImageDecoder imageDecoder = ImageCodec.createImageDecoder("tiff",
            seekableStream, null);
    renderedImage = new RenderedImage[imageDecoder.getNumPages()];

    /* count no. of pages available inside input tiff file */
    int count = 0;
    for (int i = 0; i < imageDecoder.getNumPages(); i++) {
        renderedImage[i] = imageDecoder.decodeAsRenderedImage(i);
        count++;
    }

    /* set output folder path */
    String outputFolderName;
    String[] temp = null;
    temp = tiffFilePath.split("\\.");
    outputFolderName = temp[0];
    /*
     * create file object of output folder
     * and make a directory
     */
    File fileObjForOPFolder = new File(outputFolderName);
    fileObjForOPFolder.mkdirs();

    /*
     * extract no. of image available inside
     * the input tiff file
     */
    for (int i = 0; i < count; i++) {
        page = imageDecoder.decodeAsRenderedImage(i);
        File fileObj = new File(outputFolderName
                + "/" + (i + 1) + ".jpg");
        /*
         * ParameterBlock create a generic
         * interface for parameter passing
         */
        ParameterBlock parameterBlock = new ParameterBlock();
        /* add source of page */
        parameterBlock.addSource(page);
        /* add o/p file path */
        parameterBlock.add(fileObj.toString());
        /* add o/p file type */
        parameterBlock.add(outputFileType);
        /* create output image using JAI filestore */
        RenderedOp renderedOp = JAI.create("filestore",
                parameterBlock);
        renderedOp.dispose();
    }
}

   
References:
Java Advanced Imaging API: http://java.sun.com/javase/technologies/desktop/media/
Java Advanced Imaging Website: https://jai.dev.java.net/
Programming in JAI (Guide for developers):
http://java.sun.com/products/java-media/jai/forDevelopers/jai1_0_1guide-unc/



Note:  Detailed information regarding JAI topic is available on SUN site. If you have any better idea or knew any simple and better solution than this, please share it with the blog topic.  Suggestions from your side are always welcome.

Thursday, January 21, 2010

TIFF Developement In Java

This blog only contains my own work experience in R&D and development related to TIFF image files using Java technology. It contains only some basic information and operations. This post provides basic idea about Tagged Image File Format. I spend lots of time for completion of this task and I think this is very useful for new java image developer. Adobe provides you everything related to TIFF image (specification, developer resources, libraries etc.), only thing you need to do is code as per your requirement. Later on I will add the development and implementation part of TIFF extraction and TIFF creation. For detail specification, you can visit the official links present in reference section at the end of this document.

Tiff (Tagged Image File Format):
One of the most popular and flexible image file formats used in web world is TIFF. This format is originally developed by company Aldus (now Adobe System). Adobe System now holds the official copyright to the TIFF image specification. The TIFF format is the standard in DMS (document management systems) using its most popular compression scheme CCITT Group IV 2D compression, which supports black and white images.
To save the storage capacity in high volume storage scanning, documents are scanned in bitonal format (black and white) rather than color or gray scale. Suitable file format with different and lossless compression scheme for today’s World Wide Web. Tiff is supported by the number of imaging software, applications and word processors. It can save multi-page documents to a single TIFF file rather than saving separate files. Tiff formats are also useful for transporting image files from one application to another or from one machine to another as they are designed to be independent of any particular hardware or software.

File Format Information:
(Image File Format)
- Code : TIFF
- File Extension : .tiff, .tif
- Media type : image/tiff, image/tiff-fx
- Compression : lossless
- Pixel Supported : a. 1 – 64 bit integer, signed/unsigned.
b. 32/64 bit IEEE floating point.
- Capability : black and white, grayscale, palette color and full color image data
- Developed by : Aldus (now Adobe Systems)

Why TIFF Development:
As per the development point of view-
- Flexible and platform-independent image format for development and storage.
- TIFF provides lossless image creation and compressions.
- Supported by the number of image manipulation software.
- Developers can use their private (own) tags in TIFF.
- Developers can include the own information inside the TIFF file.
- Saves storage space when required to store huge scanned data.
- Ignore developers’ private tags whenever not recognized by TIFF reader.
- Store multiple images within a single file.
- Developer can choose the best color scheme as per requirement.
- Don’t need a license from Adobe for Implementation of TIFF reading & writing applicaiton.
- Adobe provides full TIFF specification for download.

Color space and compression scheme:
TIFF allows for a wide range of different compression schemes and color spaces.
TIFF ImageWriter contain following compression types:
CCITT RLE
- Only applicable for Black and White Images (i.e. bilevel/binary images)
Modified Huffman compression
CCITT T.4
- Only applicable for Black and White Images (i.e. bilevel/binary images)
CCITT T.6
- Only applicable for Black and White Images (i.e. bilevel/binary images).
LZW
- Lossless Compression
- Use for maintain quality of image not for compression
JPEG
- Lossy compression
- Reduced file size to minimum
- Applicable for grayscale (1-band) and RGB (3-band) images only
ZLib
- Deflate compression except value.
PackBits
- Default lossless compression with RGB color space.
Deflate
- Lossless compression (same as LZW)
- Use for maintain quality of image not for compression
EXIF JPEG
- Regular JPEG compressed image
TIFF_NO_COMPRESSION
- TIFF with no compression.

Main Advantages and Disadvantage:
Advantages:
- Lossless Compression
- Platform independent
- Good compression types
- Less space required for storage
Disadvantages:
- Difficult to store
- Large file format
- Ambiguity in some compression types (e.g. JPEG compression)

Reference:
- For TIFF Specification, TIFF Registration and TIFF developer resources:
http://partners.adobe.com/public/developer/tiff/index.html
- LibTIFF Home Page: http://www.remotesensing.org/libtiff/
- For future development: http://www.adobe.com


Note: Please fill free to comment on this topic. Suggestions and questions from your side are always welcome.