Image.java :  » Game » minime » minime » Java Open Source

Java Open Source » Game » minime 
minime » minime » Image.java
/**
 * Copyright (c) 2006-2008 MiniMe. Code released under The MIT/X Window System
 * License. Full license text can be found in license.txt
 */
package minime;


import javax.microedition.lcdui.Graphics;

import minime.core.ResourceManager;

/**
 * The Image class is used to hold graphical image data. It can create image by
 * image id, or a source javax.microedition.lcdui.Image instance,or image uri.If
 * create image by image id, it will get image data from image resource file
 * using ResourceManager file.
 * 
 * @author aaa
 * 
 */
public class Image //extends Resource
{
    private javax.microedition.lcdui.Image nativeImage;
    int rscId ;
    int majorColor = -1;
    static final Logger LOG = Logger.getLogger( "minime.Image" );

    /**
     * Creates an image object from a source image.
     * 
     * @param image
     */
    public Image(javax.microedition.lcdui.Image image)
    {
        nativeImage = image;
        rscId = -1 ;
    }

    /**
     * Create an instance image, it accesses ResourceManager to get the image
     * data from resource file(.bin) based on image resource id.
     * 
     * @param imRscId
     *            the image resource id
     */
    public Image(int imRscId)
    {
        rscId = imRscId ;
        nativeImage = null;
    }
    /**
     * Create am instance image empty with a specific size.
     * @param width of the Image
     * @param height of the Image
     */
    public Image(int width,int height)
    {
      nativeImage = javax.microedition.lcdui.Image.createImage(width, height);
      rscId = -1 ;
    }
    /**
     * Create am instance image empty with from a byte array
     * @param imageData the array of image data in a supported image format
     * @param imageOffset the offset of the start of the data in the array
     * @param imageLength the length of the data in the array
     */
    public Image(byte[] imageData, int imageOffset, int imageLength)
    {
      nativeImage = javax.microedition.lcdui.Image.createImage(imageData, imageOffset, imageLength);
      rscId = -1 ;
    }
    public Image()
    {
      
    }
    /**
     * Checks if the native image is null.
     * 
     * @return true if the image is not null, false otherwise
     */
    public boolean realized()
    {
        return nativeImage != null;
    }

    /**
     * Purges the native image to null.
     */
    public void purge()
    {
        nativeImage = null;
    }
    
    public int getRscId()
    {
      return rscId;
    }
    public void setRscId(int rscId)
    {
      this.rscId=rscId;
    }
    
    /**
     * Gets the height of the native image in pixels. The value returned must
     * reflect the actual height of the image when rendered.
     * 
     * @return height of the image
     */
    public int getHeight()
    {
        if (nativeImage == null && !realize())
        {
            return -1;
        }

        return nativeImage.getHeight();
    }

    /**
     * Gets the width of the native image in pixels. The value returned must
     * reflect the actual width of the image when rendered.
     * 
     * @return width of the image
     */
    public int getWidth()
    {
        if (nativeImage == null && !realize())
        {
            return -1;
        }

        return nativeImage.getWidth();
    }

    /**
     * Draws the image at x,y coordinates.The anchor point for positioning the
     * image is Graphics.TOP | Graphics.LEFT
     * 
     * @param gc
     *            the Graphics object to be used for rendering image
     * @param x
     *            the x coordinate of the anchor point
     * @param y
     *            the y coordinate of the anchor point
     */
    public void draw(Graphics gc, int x, int y)
    {
        if (nativeImage == null && !realize())
        {
            return;
        }

        gc.drawImage(nativeImage, x, y, Graphics.TOP | Graphics.LEFT);
    }

    /**
     * Renders a series of RGB+transparency values in a specified region
     * 
     * @param gc
     *            the Graphics object to be used for rendering image
     * @param x
     *            the x coordinate of the anchor point
     * @param y
     *            the y coordinate of the anchor point
     * @param alf
     *            the value of alpha
     */
    public void drawAlf(Graphics gc, int x, int y, int alf)
    {
        if (nativeImage == null && !realize())
        {
            return;
        }

        int argb[] = new int[nativeImage.getWidth() * nativeImage.getHeight()];
        nativeImage.getRGB(argb, 0, nativeImage.getWidth(), 0, 0, nativeImage.getWidth(), nativeImage.getHeight());
        for (int i = 0; i < argb.length; i++)
        {
            argb[i] = (alf << 24) | (argb[i] & 0x00FFFFFF);
        }

        gc.drawRGB(argb, 0, nativeImage.getWidth(), x, y, nativeImage.getWidth(), nativeImage.getHeight(), true);
    }

    /**
     * Copies a region of the native image to a location within the destination.
     * 
     * @param gc
     *            the Graphics object to be used for rendering image
     * @param srcX
     *            the x coordinate of the upper left corner of the region within
     *            the native image to copy
     * @param srcY
     *            the Y coordinate of the upper left corner of the region within
     *            the native image to copy
     * @param srcW
     *            the width of the region to copy
     * @param srcH
     *            the height of the region to copy
     * @param x
     *            the x coordinate of the upper left corner of the destination
     *            drawing area
     * @param y
     *            the y coordinate of the upper left corner of the destination
     *            drawing area
     */
    public void draw(Graphics gc, int srcX, int srcY, int srcW, int srcH, int x, int y)
    {
        if (nativeImage == null && !realize())
        {
            return;
        }

        gc.drawRegion(nativeImage, srcX, srcY, srcW, srcH, 0, x, y, Graphics.TOP | Graphics.LEFT);
    }

    /**
     * Creates native image instance(javax.microedition.lcdui.Image)
     * 
     * @return false if failed. true if successful.
     */
    private boolean realize()
    {
        if(rscId!=-1)
        nativeImage = ResourceManager.getImage(rscId);
        return (null!=nativeImage) ;
    }

  public javax.microedition.lcdui.Image getNativeImage() {
        if (nativeImage == null && !realize())
        {
            return null;
        }
    return nativeImage;
  }
  
  public Image scaleBresenham(int newWidth, int newHeight, boolean bgTrans)
    {       
        if (nativeImage == null && !realize())
        {
            return null;
        }
        
        if(newWidth == 0 || newHeight ==0 )
          return null;
        
        int[] rawInput = new int[nativeImage.getHeight() * nativeImage.getWidth()];
        nativeImage.getRGB(rawInput, 0, nativeImage.getWidth(), 0, 0, nativeImage.getWidth(), nativeImage.getHeight());
        
        int[] rawOutput = new int[newWidth*newHeight];        

        // YD compensates for the x loop by subtracting the width back out
        int YD = (nativeImage.getHeight() / newHeight) * nativeImage.getWidth() - nativeImage.getWidth(); 
        int YR = nativeImage.getHeight() % newHeight;
        int XD = nativeImage.getWidth() / newWidth;
        int XR = nativeImage.getWidth() % newWidth;        
        int outOffset= 0;
        int inOffset=  0;
        
        for (int y= newHeight, YE= 0; y > 0; y--) {            
            for (int x= newWidth, XE= 0; x > 0; x--) {
                rawOutput[outOffset++]= rawInput[inOffset];
                inOffset+=XD;
                XE+=XR;
                if (XE >= newWidth) {
                    XE-= newWidth;
                    inOffset++;
                }
            }            
            inOffset+= YD;
            YE+= YR;
            if (YE >= newHeight) {
                YE -= newHeight;     
                inOffset+=nativeImage.getWidth();
            }
        }               
        return new Image(javax.microedition.lcdui.Image.createRGBImage(rawOutput, newWidth, newHeight, bgTrans));        
    }

 public Image scaleBresenhamSelf(int newWidth, int newHeight, boolean bgTrans)
  {       
      if (nativeImage == null && !realize())
      {
          return null;
      }
      
      if(newWidth == 0 || newHeight ==0 )
        return null;
      
      int[] rawInput = new int[nativeImage.getHeight() * nativeImage.getWidth()];
      nativeImage.getRGB(rawInput, 0, nativeImage.getWidth(), 0, 0, nativeImage.getWidth(), nativeImage.getHeight());
      
      int nativeHeight=nativeImage.getHeight();
      int nativeWidth=nativeImage.getWidth();
      
      Image newImage=null;
      
      int[] rawOutput = new int[newWidth*newHeight];        

      // YD compensates for the x loop by subtracting the width back out
      int YD = (nativeHeight / newHeight) * nativeWidth - nativeWidth; 
      int YR = nativeHeight % newHeight;
      int XD = nativeWidth / newWidth;
      int XR = nativeWidth % newWidth;        
      int outOffset= 0;
      int inOffset=  0;
      
      for (int y= newHeight, YE= 0; y > 0; y--) {            
          for (int x= newWidth, XE= 0; x > 0; x--) {
              rawOutput[outOffset++]= rawInput[inOffset];
              inOffset+=XD;
              XE+=XR;
              if (XE >= newWidth) {
                  XE-= newWidth;
                  inOffset++;
              }
          }            
          inOffset+= YD;
          YE+= YR;
          if (YE >= newHeight) {
              YE -= newHeight;     
              inOffset+=nativeWidth;
          }
      }     
      
      rawInput=null;
      
      newImage=new Image(javax.microedition.lcdui.Image.createRGBImage(rawOutput, newWidth, newHeight, bgTrans));  
      
      rawOutput=null;
      
      return newImage;
  }
  
  public Image scaleBilinear(int newWidth, int newHeight) {
     
    int orgWidth = nativeImage.getWidth();
    int orgHeight = nativeImage.getHeight();
    int orgLength = orgWidth * orgHeight;
    int orgMax = orgLength - 1;
 
    int[] rawInput = new int[orgLength];
    nativeImage.getRGB(rawInput, 0, orgWidth, 0, 0, orgWidth, orgHeight);
 
    int newLength = newWidth * newHeight;
 
    int[] rawOutput = new int[newLength];
 
    int yd = (orgHeight / newHeight - 1) * orgWidth;
    int yr = orgHeight % newHeight;
    int xd = orgWidth / newWidth;
    int xr = orgWidth % newWidth;
    int outOffset = 0;
    int inOffset = 0;
    
    // Whole pile of non array variables for the loop.
    int pixelA, pixelB, pixelC, pixelD;
    int xo, yo;
    int weightA, weightB, weightC, weightD;
    int redA, redB, redC, redD;
    int greenA, greenB, greenC, greenD;
    int blueA, blueB, blueC, blueD;
    int red, green, blue;
    
    for (int y = newHeight, ye = 0; y > 0; y--) {
      for (int x = newWidth, xe = 0; x > 0; x--) {
 
        // Set source pixels.
        pixelA = inOffset;
        pixelB = pixelA + 1;
        pixelC = pixelA + orgWidth;
        pixelD = pixelC + 1;
 
        // Get pixel values from array for speed, avoiding overflow.
        pixelA = rawInput[pixelA];
        pixelB = pixelB > orgMax ? pixelA : rawInput[pixelB];
        pixelC = pixelC > orgMax ? pixelA : rawInput[pixelC];
        pixelD = pixelD > orgMax ? pixelB : rawInput[pixelD];
        
        // Calculate pixel weights from error values xe & ye.
        xo = (xe << 8) / newWidth;
        yo = (ye << 8) / newHeight;
        weightD = xo * yo;
        weightC = (yo << 8) - weightD;
        weightB = (xo << 8) - weightD;
        weightA = 0x10000 - weightB - weightC - weightD;
        
        // Isolate colour channels.
        redA = pixelA >> 16;
        redB = pixelB >> 16;
        redC = pixelC >> 16;
        redD = pixelD >> 16;
        greenA = pixelA & 0x00FF00;
        greenB = pixelB & 0x00FF00;
        greenC = pixelC & 0x00FF00;
        greenD = pixelD & 0x00FF00;
        blueA = pixelA & 0x0000FF;
        blueB = pixelB & 0x0000FF;
        blueC = pixelC & 0x0000FF;
        blueD = pixelD & 0x0000FF;
 
        // Calculate new pixels colour and mask.
        red = 0x00FF0000 & (redA * weightA + redB * weightB + redC * weightC + redD * weightD);
        green = 0xFF000000 & (greenA * weightA + greenB * weightB + greenC * weightC + greenD * weightD);
        blue = 0x00FF0000 & (blueA * weightA + blueB * weightB + blueC * weightC + blueD * weightD);
 
        // Store pixel in output buffer and increment offset.
        rawOutput[outOffset++] = red + (((green | blue) >> 16));
        
        // Increment input by x delta.
        inOffset += xd;
        
        // Correct if we have a roll over error.
        xe += xr;
        if (xe >= newWidth) {
          xe -= newWidth;
          inOffset++;
        }
      }
      
      // Increment input by y delta.
      inOffset += yd;
      
      // Correct if we have a roll over error.
      ye += yr;
      if (ye >= newHeight) {
        ye -= newHeight;
        inOffset += orgWidth;
      }
    }
    return new Image(javax.microedition.lcdui.Image.createRGBImage(rawOutput, newWidth, newHeight, false));
  }

  
  public Image zoomImage(int desW, int desH,
      boolean isBackgroundTrans, boolean isTrans) {
        if (nativeImage == null && !realize())
        {
            return null;
        }
    Image desImg = null;
    int srcW = nativeImage.getWidth(); // source image width
    int srcH = nativeImage.getHeight(); // source image height
    int[] srcBuf = new int[srcW * srcH]; // source image pixel
    nativeImage.getRGB(srcBuf, 0, srcW, 0, 0, srcW, srcH);
    // compute interpolation table
    int[] tabY = new int[desH];
    int[] tabX = new int[desW];
    int sb = 0;
    int db = 0;
    int tems = 0;
    int temd = 0;
    int distance = srcH > desH ? srcH : desH;
    for (int i = 0; i <= distance; i++) { /* vertical direction */
      tabY[db] = sb;
      tems += srcH;
      temd += desH;
      if (tems > distance) {
        tems -= distance;
        sb++;
      }
      if (temd > distance) {
        temd -= distance;
        db++;
      }
    }
    sb = 0;
    db = 0;
    tems = 0;
    temd = 0;
    distance = srcW > desW ? srcW : desW;
    for (int i = 0; i <= distance; i++) { /* horizontal direction */
      tabX[db] = (short) sb;
      tems += srcW;
      temd += desW;
      if (tems > distance) {
        tems -= distance;
        sb++;
      }
      if (temd > distance) {
        temd -= distance;
        db++;
      }
    }
    // set transparence
    // if(isTrans){
    // int a= 100;//set the transparence of pixel 100
    // for(int i=0;i<srcBuf.length;i++){
    // if(srcBuf[i]==0x00FFFFFF)continue;
    // srcBuf[i]=(a<<24) | (srcBuf[i] & 0x00FFFFFF);// modify the highest 2
    // value
    // }
    // }

    // formation enlarge and shorten buffer pixel
    int[] desBuf = new int[desW * desH];
    int dx = 0;
    int dy = 0;
    int sy = 0;
    int oldy = -1;
    for (int i = 0; i < desH; i++) {
      if (oldy == tabY[i]) {
        System.arraycopy(desBuf, dy - desW, desBuf, dy, desW);
      } else {
        dx = 0;
        for (int j = 0; j < desW; j++) {
          desBuf[dy + dx] = srcBuf[sy + tabX[j]];
          dx++;
        }
        sy += (tabY[i] - oldy) * srcW;
      }
      oldy = tabY[i];
      dy += desW;
    }
    if (isTrans) {
      // int a= 100;//set the transparence of pixel 100
      for (int i = 0; i < desBuf.length; i++) {
        if (desBuf[i] == 0x00FFFFFF)
          continue;
        int alpha = ((desBuf[i] & 0xff000000) >>> 24) == 0 ? 0 : 100;
        desBuf[i] = ((alpha + 1) << 24) | (desBuf[i] & 0x00FFFFFF);// modify
                                      // the
                                      // highest
                                      // 2
                                      // value
      }
    }
    if (isBackgroundTrans) {
      desImg = new Image(javax.microedition.lcdui.Image.createRGBImage(desBuf, desW, desH, true));
    } else {
      desImg = new Image(javax.microedition.lcdui.Image.createRGBImage(desBuf, desW, desH, false));
    }

    return desImg;
  }
  /**
   * get the major color of the image, you can consider major color as the average color of an icon.
   * @return
   */
  public int getMajorColor() {
    if(majorColor != -1)
      return majorColor;
//    LOG.error("getMajor color");
      javax.microedition.lcdui.Image image=getNativeImage();
//      LOG.error("image="+image);
      int width=image.getWidth();
    int height=image.getHeight();
      int []color=new int[width*height];
    image.getRGB(color, 0, width, 0, 0, width,height);
//    clearAlpha(color);
//    LOG.error("color length:"+color.length);
//    majorColor = getAverageColor(color);
    majorColor = color[25*width+25];
    return majorColor;
  } 
  private void clearAlpha(int[] color)
  {
    for(int i=0; i<color.length; i++)
    {
      color[i]=color[i] & 0x00FFFFFF;
    }
  }
  private int getAverageColor(int [] color)
  {
//    LOG.error("getAverageColor");
    int average = average(color);
//    LOG.error("average="+average);
    color = filter(color, average, 100);
    average = average(color);
//    color = filter(color, average, 100);
//    average = average(color);
//    LOG.error("after filter average="+average);
    return average;
  }
  /**
   * filter the color, remove the ones which more than distance.
   * @param color
   * @param average
   * @param distance
   * @return
   */
  private int[] filter(int [] color, int average, int distance)
  {
    int [] temp = new int[color.length];
    int index=0;
    for(int i=0; i<color.length; i++)
    {
      double dist = distance(color[i], average);
      if( dist < distance){
        LOG.debug("dist="+dist);
        temp[index++] = color[i];
      }
    }
    if(index == 0)
      return new int[1];
    int [] ret = new int[index-1];
    for(int i=0; i<index-1; i++)
    {
      ret[i] = temp[i];
    }
    return temp;
  }
  /**
   * calculate the average of the color array.
   * @param color
   * @return
   */
  private int average(int [] color)
  {
    if(color == null)
      throw new IllegalStateException("color array can't be null");
    int sum_a = 0;
    int sum_r = 0;
    int sum_g = 0;
    int sum_b = 0;
    
    for(int i=0; i<color.length; i++)
    {
      sum_a += getA(color[i]);
      sum_r += getR(color[i]);
      sum_g += getG(color[i]);
      sum_b += getB(color[i]);
    }
    int ave = ((sum_a/color.length)<<24)+((sum_r/color.length)<<16) + ((sum_g/color.length)<<8) + (sum_b/color.length);
    return ave;
  }
  /**
   * calculate the distance of two colors
   * @param color1
   * @param color2
   * @return
   */
  private double distance(int color1, int color2)
  {
    int s = square(getA(color1)-getA(color2))+ 
          square(getR(color1)-getR(color2))+
            square(getG(color1)-getG(color2))+
              square(getB(color1)-getB(color2));
    s = s/4;
    return Math.sqrt(s);
  }
  private double distance2(int color1, int color2)
  {
    int r = Math.abs(getR(color1)-getR(color2));
    int g = Math.abs(getG(color1)-getG(color2));
    int b = Math.abs(getB(color1)-getB(color2));
    int d = Math.max(Math.max(r, g), b);
    return d;
  }
  private int getA(int color)
  {
    return ( color & 0xff000000)>>>24;
  }
  private int getR(int color)
  {
    return ( color & 0xff0000)>>>16;
  }
  private int getG(int color)
  {
    return ( color & 0xff00)>>>8;
  }
  private int getB(int color)
  {
    return ( color & 0xff);
  }
  private int square(int x)
  {
    return x*x;
  }
  /**
   * Access Graphics class to be able to draw in the Image
   * @return Graphics class of the image
   */
  public javax.microedition.lcdui.Graphics getGraphics()
  {
    return nativeImage.getGraphics();
  }
  /**
   * Check if this image is mutable. 
   * Mutable images can be modified by rendering to them through a 
   * Graphics object obtained from the getGraphics() method of this object.
   * @return true if mutable false otherwise
   */
  public boolean isMutable()
  {
    return nativeImage.isMutable();
  }
  public static void main(String[] args) {
//    int[] color={769 ,3 ,3};
////    Color c = new Color();
//    int ave = c.getAverageColor(color);
//    System.out.print("ave="+ave);
//    System.out.println("G="+c.getG(769));
  }
  
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.