Browse the code

Revision log Information on the revision Clone the sources
Revision 11

 

Show the differences
release VizHash4j v0.1 You can get the sources via Subversion.
code

 

Download this file

 

/* Copyright 2011 Edouard Garnier de Labareyre
 *
 * This file is part of ViszHash4j
 * Visual Hash implementation library in java
 * This is free software under the zlib/libpng licence
 * http://www.opensource.org/licenses/zlib-license.php
 *
 * Widely inspired from VizHash_GD php code (http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd)
 * Thanks to Sebastien Sauvage for this piece of code
 */
 
 
package net.inouire.vizhash4j;
 
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.security.MessageDigest;
import java.util.ArrayList;
import javax.swing.JPanel;
 
/**
 * This class is a JPanel that computes and display the VizHash picture for a given message String
 * The obtained picture aims to be similar to those generated by VizHash_GD (http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd)
 
 * @author Edouard de Labareyre
 */
public class VizHashPanel extends JPanel{
 
  
    private String message_hash="";
    
    private ArrayList<Integer>  values = new ArrayList<Integer>();
    private int values_index=0;
    
    private int width,height;
 
    public static String VERSION="0.1";
    private boolean VERBOSE=false;
    
    public VizHashPanel(boolean verbose){
        VERBOSE=verbose;
        if(VERBOSE){
            System.out.println("VizHash4j v"+VERSION);
        }
 
    }
 
    /**
     * This function computes the values array from hashsum of the given String
     * @param message the message to compute
     * @return false if a problem is encoutered during computation
     */
    public boolean setValue(String message){
        try{
            //compute hash String
            String md5_hash = convertToHex(MessageDigest.getInstance("MD5").digest(message.getBytes("UTF8")));
            String sha1_hash = convertToHex(MessageDigest.getInstance("SHA1").digest(message.getBytes("UTF8")));
            message_hash=sha1_hash+md5_hash+new StringBuffer(sha1_hash+md5_hash).reverse().toString();
 
            //build int values array
            values = new ArrayList<Integer>();
            values_index=0;
            for(int i=0; i<message_hash.length();i+=2){
                int dec = Integer.parseInt(message_hash.substring(i,i+2),16);
                values.add(dec);
            }
 
            if(VERBOSE){
                System.out.println("Hashed message for string \""+message+"\":");
                System.out.println("    "+message_hash);
            }
 
            //paint component with this new value
            repaint();
        }catch(Exception e){
            System.out.println("Error while hashing string \""+message+"\":");
            e.printStackTrace();
            return false;
        }
        return true;
        
    }
 
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(256,256);
    }
 
    @Override
    public void paintComponent(Graphics g) {
        
        values_index=0;
        width=this.getWidth();
        height=this.getHeight();
        
        Graphics2D g2 = (Graphics2D)g;
        RenderingHints rh = new RenderingHints(
        RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHints(rh);
        super.paintComponent(g);
 
        int red0 = getInt();
        int green0 = getInt();
        int blue0 = getInt();
 
        int red=red0;
        int green=green0;
        int blue=blue0;
        
        Color bg0 = new Color(red0,green0,blue0);
 
        //paint horizontal or vertical gradient in background
        GradientPaint bg = new GradientPaint(0,0,bg0,0, height,Color.BLACK);
        if(getInt()%2==0){
            bg = new GradientPaint(0,0,bg0,width,0,Color.BLACK);
        }
        g2.setPaint(bg);
        g2.fillRect(0, 0, width,height);
 
        //draw 7 or less shapes, in a similar color theme than background
        int action;
        Color color;
        for(int i=0;i<7;i++){
            action = getInt();
            color = new Color(red,green,blue);
            red=(red0+getInt()/25)%256;
            green=(green0+getInt()/25)%256;
            blue=(blue0+getInt()/25)%256;
            red0=red;
            green0=green;
            blue0=blue;
            drawShape(g,action,color);
        }
        //draw a new shape with a (potentially completely) different color
        color = new Color(getInt(),getInt(),getInt());
        drawShape(g,getInt(),color);             
    }
 
    /**
     * This function paints a filled shape which can be a rectangle, an ellipse, a polygon or an arc
     * @param g the graphic where to paint
     * @param action an integer between 0 and 255
     * @param color the color of the shape to paint
     */
    public void drawShape(Graphics g,int action,Color color){
 
        int w,h;
        
        g.setColor(color);
 
        switch(action%7){
            case 0:
                //rectangle
                int[] r = {getXCoordinate(),getYCoordinate(),getXCoordinate(),getYCoordinate()};//order of call of getInt() is important to stay the same as VizHash_GD
                int x0=Math.min(r[0],r[2]);
                int y0=Math.min(r[1],r[3]);
                int x1=Math.max(r[0],r[2]);
                int y1=Math.max(r[1],r[3]);
                g.fillRect(x0,y0,x1-x0,y1-y0);
                break;
            case 1:
            case 2:
                //ellipse
                int xc=getXCoordinate();
                int yc=getYCoordinate();
                w=getXCoordinate();
                h=getYCoordinate();
                g.fillOval(xc-(w/2),yc-(h/2),w,h);
                break;
            case 3:
                //polygon
                int[] p = {getXCoordinate(),getYCoordinate(),
                           getXCoordinate(),getYCoordinate(),
                           getXCoordinate(),getYCoordinate(),
                           getXCoordinate(),getYCoordinate()};
                int[] xPoints={p[0],p[2],p[4],p[6]};
                int[] yPoints={p[1],p[3],p[5],p[7]};
                g.fillPolygon(xPoints, yPoints, 4);
                break;
            case 4:
            case 5:
            case 6:
                //arc
                int as=getInt()*360/256;
                int ae=as+((getInt()*180)/256);
                int start=-as;
                int angle=as-ae;
                int cx=getXCoordinate();
                int cy=getYCoordinate();
                w=getXCoordinate();
                h=getYCoordinate();
                g.fillArc(cx-(w/2), cy-(h/2), w, h, start, angle);
                break;
        }
    }
 
    /**
     * This function returns the next int from the values array
     * @return an int from the values array
     */
    private int getInt(){
        int v = values.get(values_index);
        values_index++;
        values_index%=values.size();
        return v;
    }
 
    /**
     * Same as getInt but normalized to component width
     * @return
     */
    private int getXCoordinate(){
        return width*getInt()/256;
    }
 
    /**
     * Same as getInt but normalized to component height
     * @return
     */
    private int getYCoordinate(){ 
        return height*getInt()/256;
    }
 
     /**
     * This function converts the byte array in hexadecimal String
     * (snippet found on pastebin http://pastebin.com/air8WKN5)
     * @param data
     * @return
     */
    private static String convertToHex(byte[] data) {
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < data.length; i++) {
            int halfbyte = (data[i] >>> 4) & 0x0F;
            int two_halfs = 0;
            do {
                if ((0 <= halfbyte) && (halfbyte <= 9))
                    buf.append((char) ('0' + halfbyte));
                else
                    buf.append((char) ('a' + (halfbyte - 10)));
                halfbyte = data[i] & 0x0F;
            } while(two_halfs++ < 1);
        }
        return buf.toString();
    } 
    
}