/** * Copyright 2014 Comcast Cable Communications Management, LLC * * This file is part of CATS. * * CATS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CATS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with CATS. If not, see <http://www.gnu.org/licenses/>. */ package com.comcast.cats.imageutility; import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorConvertOp; import java.io.IOException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.comcast.cats.imageutility.ImageType; /** * * This class provides utility methods for performing image enhancement * functions to increase the readability of OCR. * * @author Sijil CV * @author Manesh Thomas * */ public class ImageEnhance { private static Logger logger = LoggerFactory.getLogger( ImageEnhance.class ); /** * Image Enhancement function to increase the readability of OCR. * * @param image * - the image to be enhanced. * @param target * - target location at which the image needs to be saved. * @param coordinate1 * Top X coordinate * @param coordinate2 * Top Y coordinate * @param coordinate3 * Bottom X coordinate * @param coordinate4 * Bottom Y coordinate * @param imagetype * - 1)dark background with light foreground ( dl ) 2)light * background with dark foreground ( ld ) 3)dark background with * dark foreground ( dd ) 4)light background with light * foreground ( ll ) 5)complex image (special case) ( sc ) * 6)light red image types ( my ) * * @param zoomscale * - how much zoomed o/p is needed * @param volume * - enhancing for volume check or not * @param urlpath * @param mode * @throws ImageUtilityException * @throws IOException */ public static void enhance( BufferedImage image, String target, int coordinate1, int coordinate2, int coordinate3, int coordinate4, String imagetype, int zoomscale, boolean volume, boolean urlpath, int mode ) throws ImageUtilityException, IOException { if ( zoomscale <= 0 ) { logger.error( " Zoom Value should be greater than Zero" ); throw new ImageUtilityException( "Zoom Value can't be Zero/Negative" ); } logger.info( "Starting Image enhance operation " + "with " + imagetype + " Type." ); int zoom = 1; boolean fullMode = false; float scale = 1f; float offset = 1f; // Set the scale and offset values based on image type. switch ( ImageType.getValue( imagetype ) ) { case LD: scale = 1f; offset = 20f; break; case DL: scale = 1f; offset = 1f; break; case LL: scale = 9f; offset = 1.5f; break; case DD: scale = 1.5f; offset = 20f; break; case SC: scale = 1f; offset = -20f; break; case MY: scale = .813799f; offset = 15f; break; default: logger.error( " Invalid Image type " ); throw new ImageUtilityException( " Invalid Image type " ); } // Full image processing. if ( ( coordinate1 == 0 ) & ( coordinate2 == 0 ) & ( coordinate3 == 0 ) & ( coordinate4 == 0 ) ) { fullMode = true; image = processFullImage( image, imagetype, zoomscale, scale, offset ); } else { image = processSubImage( image, coordinate1, coordinate2, coordinate3, coordinate4, imagetype, zoom, scale, offset ); } // Sharp image generation image = ImageUtility.generateSharpImage( image ); image = ImageUtility.generateBlurImage( image ); // image to gray scale ColorConvertOp colorConvert = new ColorConvertOp( ColorSpace.getInstance( ColorSpace.CS_GRAY ), null ); image = colorConvert.filter( image, null ); // Black and White Image generation image = ImageUtility.genBlackAndWhiteImage( image ); float zscale = ( 1f / zoom ); if ( fullMode == true ) { image = ImageUtility.zoom( image, 0.5f * zoomscale, 0.5f * zoomscale ); } else { image = ImageUtility.zoom( image, zscale * zoomscale, zscale * zoomscale ); } if ( target != null ) { ImageUtility.saveImageAsPNG( image, target ); } } /** * Process sub image. * * @throws ImageUtilityException */ private static BufferedImage processSubImage( BufferedImage image, int coordinate1, int coordinate2, int coordinate3, int coordinate4, String imagetype, int zoom, float scale, float offset ) throws ImageUtilityException { int width = Math.abs( coordinate3 - coordinate1 ); int height = Math.abs( coordinate4 - coordinate2 ); try { image = image.getSubimage( coordinate1, coordinate2, width, height ); } catch ( java.awt.image.RasterFormatException io ) { logger.error( "Invalid x y cordinate. Coordinate1: " + coordinate1 + "coordinate2: " + coordinate2 + "width: " + width + "height : " + height ); throw new ImageUtilityException( "Invalid x y cordinate" ); } // invert Image if ( !( imagetype.equals( ImageType.DD.getImageTypeString() ) ) ) // for dark background and foreground image. ImageUtility.invertImage( image ); // Inversion not needed ZoomedImage zoomedImage = zoomInMultipleTimes( zoom, image ); image = ImageUtility.performRescaleOperation( zoomedImage.getImage(), scale, offset ); zoomedImage = zoomInMultipleTimes( zoom, image ); image = zoomedImage.getImage(); return image; } /** * Process Full Image. * * @throws ImageUtilityException */ private static BufferedImage processFullImage( BufferedImage image, String imagetype, int zoomscale, float scale, float offset ) throws ImageUtilityException { if ( image.getWidth() >= 1600 && image.getHeight() >= 1200 ) { logger.error( "Image Size is Too large To Enhance. Reduce the Image Width * Height" ); throw new ImageUtilityException( "Image Size is Too large To Enhance. Reduce the Image Width * Height" ); } if ( zoomscale * image.getWidth() >= 2400 && zoomscale * image.getHeight() >= 1600 ) { logger.error( "Image Size is Too large To Enhance. Reduce the Image Width * Height" ); throw new ImageUtilityException( "Image Size is Too large To Enhance. Reduce the Image Width * Height" ); } if ( !( imagetype.equals( ImageType.DD.getImageTypeString() ) ) ) { // invert Image ImageUtility.invertImage( image ); } image = ImageUtility.zoom( image, 2f, 2f ); image = ImageUtility.performRescaleOperation( image, scale, offset ); return image; } /** * Perform zoom in multiple times. * * @param zoom * zoom scale. * @param image * input image * @return Zoomed image * @throws ImageUtilityException */ private static ZoomedImage zoomInMultipleTimes( int zoom, BufferedImage image ) throws ImageUtilityException { ZoomedImage zoomedImage = null; int initialWidth = image.getWidth(); image = ImageUtility.zoom( image, 4f, 4f ); if ( image.getWidth() != initialWidth ) { zoom = zoom * 4; } else { image = ImageUtility.zoom( image, 2f, 2f ); if ( image.getWidth() != initialWidth ) { zoom = zoom * 2; } } zoomedImage = new ZoomedImage( zoom, image ); return zoomedImage; } }