By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,680 Members | 2,123 Online
Bytes IT Community
Submit an Article
Got Smarts?
Share your bits of IT knowledge by writing an article on Bytes.

Play with image A Technique in Java - Search image, Convert image to text , Hide data

Debadatta Mishra
P: 1
Introduction

In this article I will provide you an approach to manipulate an image file. This article gives you an insight into some tricks in java so that you can conceal sensitive information inside an image, hide your complete image as text ,search for a particular image inside a directory, minimize the size of the image. However this is not a new concept, there is a concept called Steganography which enables to conceal your secret information inside an image. For this concept many very sophisticated softwares are available to manipulate the images. But as a java developer we can also
achieve it to an extent.

Normally many people keep all the personal images in a particular directory and others view the images by searching as *.jpg .
It hampers the privacy of your photos and images. In this article I will show you how you can convert your pictures, photos and images into text file to increase more privacy. Others can view your text file but can not understand what it is. There are occasions many users put all their secret and sesitive information like several bank details, credit card numbers ,email password details etc in a text file so that they can login specific applications easily. But it creates a problem when other others use the systems where these information are there . In this article I will show you how you can hide your personal details inside an image and you can retrieve the details as and when required. Let us go into the techincal details as I do not want to prolong my description.

Technicalities
It is very easy in Java to read an image and you can store the image contents as flat file. To achieve this, read the image file using ImageIO class in Java and convert the array of bytes into String using Base64Encoder . Here your major work is over, now you have manipulate the String in any manners. Let us have look into the cases.

Case – 1 : Hide you photos as text files
In this case you can hide all your photos or images into text files and rename the files in a such manner that other users will consider as system files or logs. In my class “ImageAnalyzerUtil”, there is a method which will convert an image into text file. The method name is “convertImageToText()”. In this method the image file is read as String using “Base64Encoder” and finally it written into a text file.

Case – 2 : Get back your original image from the text file
In the class “ImageAnalyzerUtil” there is a method called “convertTextToImage()” which will convert the text file into image. However all the text files will not be converted into images. Only those text files which have been converted from image files will create the image. In this case the converted text file is read and converted into array of byte using “Base64Decoder” and finally the array of bytes is written into file.

Case – 3 : Hide your sensitive information inside an image
In this case there is a method called “hideTextDataInsideImage()” in the class “ImageAnalyzerUtil”. Here an extra string is added to the image file with the other data so that data can be retrieved easily.

Case – 4 : Retrieve your sesitive information from an image
For this purpose there is a method called “getHiddenDataFromImage()” in the class “ImageAnalyzerUtil”. In this case the entire image is read as String and the sensitive information is separated and displayed.

Case – 5 : Minimize the image size
While working on this program, I found that while reverting the original image from the text file, the size of the image is reduced. There is no loss of image data but there may be a loss of some extra data which OS provides.

The complete program is given below with all revelent testharness program.
Expand|Select|Wrap|Line Numbers
  1. package com.ddsoft.tornado.core.image;
  2. import java.awt.image.BufferedImage;
  3. import java.io.BufferedOutputStream;
  4. import java.io.BufferedReader;
  5. import java.io.ByteArrayOutputStream;
  6. import java.io.DataInputStream;
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.FileNotFoundException;
  10. import java.io.FileOutputStream;
  11. import java.io.IOException;
  12. import java.io.InputStream;
  13. import java.io.InputStreamReader;
  14. import java.io.OutputStream;
  15. import java.io.OutputStreamWriter;
  16.  
  17. import javax.imageio.ImageIO;
  18.  
  19. /**
  20.  * This class contains the following utility methods.
  21.  * <p>
  22.  * <li> Utility Method to read converted image text file </li>
  23.  * <li> Utility method to write the image as text file </li>
  24.  * <li> Utility method to get the image contents as String </li>
  25.  * <li> Utility method hide the text data inside an image </li>
  26.  * <li> Utility method get the hidden data from an image </li>
  27.  * <li> Utility method to search a particular image inside a directory </li>
  28.  * <li> Utility method to search and to obtain the full path of an image </li>
  29.  * <li> Utility method to convert an image into a text file </li>
  30.  * <li> Utility method to convert a text back into image </li>
  31.  * @author Debadatta Mishra(PIKU)
  32.  *
  33.  */
  34. public class ImageAnalyzerUtil 
  35. {
  36.     /**
  37.      * String type constant to define the image type.
  38.      */
  39.     private static String IMAGE_TYPE = "jpg";
  40.     /**
  41.      * An extra String that separates the image data and the secret information data
  42.      */
  43.     private static String extraStr = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@";
  44.  
  45.     /**
  46.      * This method is used to read the contents of a text( converted from image ) file
  47.      * and provides byte[].
  48.      * @param imageTextFilePath of type String indicating the path of the text file
  49.      * @return an array of bytes
  50.      * @author Debadatta Mishra(PIKU)
  51.      */
  52.     public static byte[] readImageTextFile( String imageTextFilePath )
  53.     {
  54.         byte[] dataFile = null;
  55.         try
  56.         {
  57.             StringBuffer textData = new StringBuffer();
  58.             FileInputStream fstream = new FileInputStream(imageTextFilePath);
  59.             DataInputStream in = new DataInputStream(fstream);
  60.             BufferedReader br = new BufferedReader(new InputStreamReader(in));
  61.             String srtData;
  62.             while ((srtData = br.readLine()) != null) {
  63.                 textData.append(srtData);
  64.             }
  65.             br.close();
  66.             fstream.close();
  67.             in.close();
  68.             dataFile = new sun.misc.BASE64Decoder().decodeBuffer(textData.toString());
  69.         }
  70.         catch( Exception e )
  71.         {
  72.             e.printStackTrace();
  73.         }
  74.         return dataFile;
  75.     }
  76.  
  77.     /**
  78.      * This method is used to write the contents of an image into a text file.
  79.      * @param filePath of type String indicating the path of the text file
  80.      * @param imageContents of type String indicating the image contents as String
  81.      * @author Debadatta Mishra(PIKU)
  82.      */
  83.     public static void writeImageAsTextFile( String filePath , String imageContents )
  84.     {
  85.         FileOutputStream fout=null;
  86.         OutputStreamWriter osw = null;
  87.         OutputStream bout = null;
  88.         try
  89.         {
  90.             fout = new FileOutputStream (filePath);
  91.             bout= new BufferedOutputStream(fout);
  92.             osw = new OutputStreamWriter(bout, "utf-8");
  93.             osw.write(imageContents);
  94.             bout.close();
  95.             osw.close();
  96.             fout.close();
  97.         }
  98.         catch( Exception e )
  99.         {
  100.             e.printStackTrace();
  101.         }
  102.     }
  103.  
  104.     /**
  105.      * This method is used to get the image contents as String.
  106.      * @param imagePath of type String indicating the path of image file
  107.      * @return a String of image contents
  108.      * @author Debadatta Mishra(PIKU)
  109.      */
  110.     public static String getImageAsString( String imagePath )
  111.     {
  112.         String imageString = null;
  113.         try
  114.         {
  115.             File f = new File(imagePath);
  116.             BufferedImage buffImage = ImageIO.read(f);
  117.             ByteArrayOutputStream os= new ByteArrayOutputStream();
  118.             ImageIO.write(buffImage, IMAGE_TYPE, os);
  119.             byte[] data= os.toByteArray();
  120.             imageString = new sun.misc.BASE64Encoder().encode(data);
  121.         }
  122.         catch( FileNotFoundException fnfe )
  123.         {
  124.             fnfe.printStackTrace();
  125.             System.out.println("Image is not located in the proper path.");
  126.         }
  127.         catch (IOException e) 
  128.         {
  129.             e.printStackTrace();
  130.             System.out.println("Error in reading the image.");
  131.         }
  132.         return imageString;
  133.     }
  134.  
  135.     /**
  136.      * This method is used to hide the data contents inside the image.
  137.      * @param srcImagePath of type String indicating the path of the source image
  138.      * @param dataContents of type String containing data
  139.      * @author Debadatta Mishra(PIKU)
  140.      */
  141.     public static void hideTextDataInsideImage( String srcImagePath , String dataContents )
  142.     {
  143.         try 
  144.         {
  145.             dataContents = new sun.misc.BASE64Encoder().encode(dataContents.getBytes());
  146.             extraStr = new sun.misc.BASE64Encoder().encode(extraStr.getBytes());
  147.             FileOutputStream fos = new FileOutputStream( srcImagePath , true );
  148.             fos.write(new sun.misc.BASE64Decoder().decodeBuffer(extraStr.toString()));
  149.             fos.write( dataContents.getBytes() );
  150.             fos.close();
  151.         }
  152.         catch( FileNotFoundException fnfe )
  153.         {
  154.             fnfe.printStackTrace();
  155.         }
  156.         catch (IOException e)
  157.         {
  158.             e.printStackTrace();
  159.         }
  160.         catch( Exception e )
  161.         {
  162.             e.printStackTrace();
  163.         }
  164.     }
  165.  
  166.     /**
  167.      * This method is used to get the hidden data from an image.
  168.      * @param imagePath of type String indicating the path of the image
  169.      * which contains the hidden data
  170.      * @return the String containing hidden data inside an image
  171.      * @author Debadatta Mishra(PIKU)
  172.      */
  173.     public static String getHiddenDataFromImage( String imagePath )
  174.     {
  175.         String dataContents = null;
  176.         try
  177.         {
  178.             File file = new File( imagePath );
  179.             byte[] fileData = new byte[ (int)file.length()];
  180.             InputStream inStream = new FileInputStream( file );
  181.             inStream.read(fileData);
  182.             inStream.close();
  183.             String tempFileData = new String(fileData);
  184.             String finalData = tempFileData.substring(tempFileData
  185.                     .indexOf(extraStr)
  186.                     + extraStr.length(), tempFileData.length());
  187.             byte[] temp = new sun.misc.BASE64Decoder().decodeBuffer(finalData);
  188.             dataContents = new String(temp);
  189.         }
  190.         catch( Exception e )
  191.         {
  192.             e.printStackTrace();
  193.         }
  194.         return dataContents;
  195.     }
  196.  
  197.     /**
  198.      * This method is used to search a particular image in a image directory.
  199.      * In this method, it will search for the image contents for the image
  200.      * you are passing.
  201.      * @param imageToSearch of type String indicating the file name of the image
  202.      * @param imageFolderToSearch of type String indicating the name of the directory
  203.      * which contains the images
  204.      * @return true if image is found else false
  205.      * @author Debadatta Mishra(PIKU)
  206.      */
  207.     public static boolean searchImage( String imageToSearch , String imageFolderToSearch )
  208.     {
  209.         boolean searchFlag = false;
  210.         try
  211.         {
  212.             String searchPhotoStr = getImageAsString(imageToSearch);
  213.             File files = new File( imageFolderToSearch );
  214.             File[] photosFiles = files.listFiles();
  215.             for( int i = 0 ; i < photosFiles.length ; i++ )
  216.             {
  217.                 String photoFilePath = photosFiles[i].getAbsolutePath();
  218.                 String photosStr = getImageAsString(photoFilePath);
  219.                 if( searchPhotoStr.equals(photosStr))
  220.                 {
  221.                     searchFlag = true;
  222.                     break;
  223.                 }
  224.                 else
  225.                 {
  226.                     continue;
  227.                 }
  228.             }    
  229.         }
  230.         catch( Exception e )
  231.         {
  232.             e.printStackTrace();
  233.         }
  234.         return searchFlag ;
  235.     }
  236.  
  237.     /**
  238.      * This method is used to search for a particular image found in a directory
  239.      * and it will return the full path of the image found. Sometimes it is required
  240.      * to find out the particular image and the path of the image so that the path
  241.      * String can be used for further processing.
  242.      * @param imageToSearch of type String indicating the file name of the image
  243.      * @param imageFolderToSearch of type String indicating the name of the directory
  244.      * which contains the images
  245.      * @return the full path of the image
  246.      * @author Debadatta Mishra(PIKU)
  247.      */
  248.     public static String searchAndGetImageName( final String imageToSearch , final String imageFolderToSearch )
  249.     {
  250.         String foundImageName = null;
  251.         try
  252.         {
  253.             String searchPhotoStr = ImageAnalyzerUtil.getImageAsString(imageToSearch);
  254.             File files = new File( imageFolderToSearch );
  255.             File[] photosFiles = files.listFiles();
  256.             for( int i = 0 , n = photosFiles.length; i < n ; i++ )
  257.             {
  258.                 final String photoFilePath = photosFiles[i].getAbsolutePath();
  259.                 final String photosStr = ImageAnalyzerUtil.getImageAsString(photoFilePath);
  260.                 if( searchPhotoStr.equals(photosStr))
  261.                 {
  262.                     foundImageName = photosFiles[i].getAbsolutePath();
  263.                     break;
  264.                 }
  265.                 else
  266.                 {
  267.                     continue;
  268.                 }
  269.             }    
  270.         }
  271.         catch( Exception e )
  272.         {
  273.             e.printStackTrace();
  274.         }
  275.         return foundImageName;
  276.     }
  277.  
  278.     /**
  279.      * This method is used to convert an image into a text file.
  280.      * @param imagePath of type String indicating the path of the image file
  281.      * @author Debadatta Mishra(PIKU)
  282.      */
  283.     public static void convertImageToText( String imagePath )
  284.     {
  285.         File file = new File( imagePath );
  286.         String fileName = file.getAbsolutePath();
  287.         String textFilePath = new StringBuilder(fileName.substring(0, fileName
  288.                 .lastIndexOf("."))).append(".txt").toString();
  289.         writeImageAsTextFile(textFilePath, getImageAsString(imagePath));
  290.         /*
  291.          * There may be requirement to delete the original image,
  292.          * write the code here for this purpose.
  293.          */
  294.     }
  295.  
  296.     /**
  297.      * This method is used to convert the text file into image.
  298.      * However all text files will not be converted into images.
  299.      * Those text files which have been converted from images files
  300.      * will be converted back into image.
  301.      * @param imageTextFilePath of type String indicating the converted text file
  302.      * from image file.
  303.      * @author Debadatta Mishra(PIKU)
  304.      */
  305.     public static void convertTextToImage( String imageTextFilePath )
  306.     {
  307.         try
  308.         {
  309.             File file = new File( imageTextFilePath );
  310.             String fileName = file.getAbsolutePath();
  311.             String imageFilePath = new StringBuilder(fileName.substring(0, fileName
  312.                     .lastIndexOf("."))).append(".").append(IMAGE_TYPE).toString();
  313.             OutputStream out = new FileOutputStream( imageFilePath );
  314.             byte[] imageBytes = readImageTextFile(imageTextFilePath);
  315.             out.write(imageBytes);
  316.             out.close();
  317.         }
  318.         catch( Exception e )
  319.         {
  320.             e.printStackTrace();
  321.         }
  322.     }
  323.  
  324. }
  325.  
The above is a generic program to achieve the functionalities with the images. I provide below the test case in support of this above program.

The following test program provides the details of converting an into text file and vice versa.
Expand|Select|Wrap|Line Numbers
  1. package com.ddsoft.tornado.image.test;
  2.  
  3. import com.ddsoft.tornado.core.image.ImageAnalyzerUtil;
  4.  
  5.  
  6. /**
  7.  * This is a test harness class to test the
  8.  * image conversion utility.
  9.  * @author Debadatta Mishra(PIKU)
  10.  *
  11.  */
  12. public class ConvertImageTest 
  13. {
  14.     public static void main(String[] args) 
  15.     {
  16.         String sourceImagePath = "data/IMG_2526.JPG";
  17.         //Convert the image into text file
  18.         ImageAnalyzerUtil.convertImageToText(sourceImagePath);
  19.  
  20.         //Convert the image text file back into actual image file
  21.         ImageAnalyzerUtil.convertTextToImage("data/IMG_2526.txt");
  22.     }
  23.  
  24. }
  25.  
The following testharness program demonstrates how to hide data inside an image.
Expand|Select|Wrap|Line Numbers
  1. package com.ddsoft.tornado.image.test;
  2.  
  3. import com.ddsoft.tornado.core.image.ImageAnalyzerUtil;
  4.  
  5. /**
  6.  * This is a testharness class to hide the information inside an image
  7.  * @author Debadatta Mishra(PIKU)
  8.  *
  9.  */
  10. public class HideDataTest 
  11. {
  12.     public static void main(String[] args)
  13.     {
  14.         String secretData = "It contains all my secret materials and my bank information details";
  15.         String destinationImathPath = "data/secretImage.jpg";
  16.         //Hide the information inside the image
  17.         ImageAnalyzerUtil.hideTextDataInsideImage(destinationImathPath,
  18.                 secretData);
  19.         //Get back the data hidden inside an image
  20.         String hiddenData = ImageAnalyzerUtil
  21.         .getHiddenDataFromImage(destinationImathPath);
  22.         System.out.println(hiddenData);
  23.     }
  24.  
  25. }
  26.  
The follwoing test program shows how to search image inside a directory of images.
Expand|Select|Wrap|Line Numbers
  1. package com.ddsoft.tornado.image.test;
  2.  
  3. import com.ddsoft.tornado.core.image.ImageAnalyzerUtil;
  4.  
  5. /**
  6.  * This is a testharness class to search for an image
  7.  * @author Debadatta Mishra(PIKU)
  8.  *
  9.  */
  10. public class ImageSearchTest 
  11. {
  12.     public static void main(String[] args) 
  13.     {
  14.         try
  15.         {
  16.             String photoPath = "photos";
  17.             String searchPhotoPath = "data/PhotoToSearch.JPG";
  18.             //Search the image inside the directory of images
  19.             boolean searchFlag = ImageAnalyzerUtil.searchImage(searchPhotoPath, photoPath);
  20.             if( searchFlag )
  21.                 System.out.println("Image Found");
  22.             else
  23.                 System.out.println("Specified Image Not Found");
  24.             //Search and get the full path of the image inside a directory of images
  25.             System.out.println("Found Image Name----->"+ImageAnalyzerUtil.searchAndGetImageName(searchPhotoPath, photoPath));
  26.  
  27.         }
  28.         catch( Exception e )
  29.         {
  30.             e.printStackTrace();
  31.         }
  32.     }
  33.  
  34. }
  35.  
The following test program provides the way to minimize the image size.
package com.ddsoft.tornado.image.test;

Expand|Select|Wrap|Line Numbers
  1. import com.ddsoft.tornado.core.image.ImageAnalyzerUtil;
  2.  
  3. /**
  4.  * This is a testharness class to check the converted image size
  5.  * @author Debadatta Mishra(PIKU)
  6.  *
  7.  */
  8. public class MinimizeImageSizeTest 
  9. {
  10.     public static void main(String[] args) throws Exception
  11.     {
  12.         String originalImageSrcPath = "data/IMG_2542.JPG";
  13.         ImageAnalyzerUtil.convertImageToText(originalImageSrcPath);
  14.         ImageAnalyzerUtil.convertTextToImage("data/IMG_2542.txt");
  15.     }
  16. }
  17.  
Test Case detailsI have tested the above program in the following conditions.
OS Name : Windows Vista
Files of type : .jpg
Java : 1.6.0_16
Java Editor : Eclipse 3.2

Conclusion
I hope that you will enjoy my article. This article does not bear any commercial significance , it is only meant for learning. There may be many limitations in this program, I have given it as trick and twik in Java. You can download the full source code . In case of any problem or errors , feel free to contact me in the email debadatta.mishra@gmail.com .
Attached Files
File Type: zip imageanalysis.zip (4.6 KB, 637 views)
Dec 5 '09 #1
Share this Article
Share on Google+