Texture From Many Images

Hi, i'm quite new here, I would like to share this tiny but useful (I hope) class that compose many images in ony one.

The idea is to use it to compose the face of a pg using eyes, hairs etc etc, or to generate random trees, or grass.



have fun!

(and ask for any problems!!)


/*
 * @author Marco Servetto
 * @date 16/02/2008
 *
 * */

package base;

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.net.URL;

import javax.swing.ImageIcon;

import com.jme.image.Texture;
import com.jme.util.TextureManager;
/*
 * This class Generate a texture from a set of image and positions.
 * It uses a percentage representation for placing images on the texture.
 * For example
 *   add(i,1.0f,1.0f,0.5f,0.5f,0) cover the the texture all with i
 *   add(i,0.1f,0.1f,0.5f,0.5f,0) place i at the center of the texture, big as 1/10 of the texture size.
 *   add(i,0.2f,0.2f,0.1f,0.1f,0) place i near to the left top corner of the texture, big as 2/10 of the texture size.
 *   add(i,0.1f,0.1f,0.9f,0.9f,PI/2f) place i near to the right bottom corner of the texture, big as 1/10 of the texture size,with 90 degrees of rotation.
 *  
 * */
public class ProceduralTextureComposition {
  BufferedImage imgBuffer;
  Graphics2D g;
  /*
   * type can be BufferedImage.TYPE_INT_ARGB or
   * BufferedImage.TYPE_INT_RGB or
   *  other in the same family.
   * */
  public ProceduralTextureComposition(int width,int height,int type){
    imgBuffer = new BufferedImage(width,height,type);
   g=(Graphics2D)imgBuffer.getGraphics();
   }
  /* examples
   *   add(i,1.0f,1.0f,0.5f,0.5f,0) cover the the texture all with i
   *   add(i,0.1f,0.1f,0.5f,0.5f,0) place i at the center of the texture, big as 1/10 of the texture size.
   *   add(i,0.2f,0.2f,0.1f,0.1f,0) place i near to the left top corner of the texture, big as 2/10 of the texture size.
   *   add(i,0.1f,0.1f,0.9f,0.9f,PI/2f) place i near to the right bottom corner of the texture, big as 1/10 of the texture size,with 90 degrees of rotation.
   * */
  public void add(ImageIcon i,float scaleX,float scaleY,float posX,float posY,float alpha){
    place(imgBuffer,g,i,scaleX,scaleY,posX,posY,alpha);
   }
  /* examples
   *   add(i,1.0f,1.0f,0.5f,0.5f,0) cover the the texture all with i
   *   add(i,0.1f,0.1f,0.5f,0.5f,0) place i at the center of the texture, big as 1/10 of the texture size.
   *   add(i,0.2f,0.2f,0.1f,0.1f,0) place i near to the left top corner of the texture, big as 2/10 of the texture size.
   *   add(i,0.1f,0.1f,0.9f,0.9f,PI/2f) place i near to the right bottom corner of the texture, big as 1/10 of the texture size,with 90 degrees of rotation.
   * */
  public void add(URL url,float scaleX,float scaleY,float posX,float posY,float alpha){
    place(imgBuffer,g,new ImageIcon(url),scaleX,scaleY,posX,posY,alpha);
   }
  /*
   * Compute and return the texture. 
   * */   
  public Texture generateTexture(){
    g.dispose();
   return TextureManager.loadTexture(imgBuffer, Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR, true );
    }
  private static AffineTransform findPlace(double scaleX,double scaleY,double posX,double posY,double alpha,double sizeX,double sizeY,double imgX,double imgY){
    AffineTransform m=new AffineTransform();
   m.concatenate(AffineTransform.getTranslateInstance(posX,posY));   
   m.concatenate(AffineTransform.getRotateInstance(alpha));
   m.concatenate(AffineTransform.getScaleInstance(scaleX,scaleY));
   m.concatenate(AffineTransform.getTranslateInstance(-imgX/2d,-imgY/2d));
    return m;   
   }
  private static void place(BufferedImage imgBuffer,Graphics2D g,ImageIcon i,float scaleX,float scaleY,float posX,float posY,float alpha){
   double sizeX=imgBuffer.getWidth();
   double sizeY=imgBuffer.getHeight();
   double imgX=i.getIconWidth();
   double imgY=i.getIconHeight();
   double absScaleX=(sizeX/imgX)*scaleX;
   double absScaleY=(sizeY/imgY)*scaleY;
   double absPosX=sizeX*posX;
   double absPosY=sizeY*posY;
   double absAlpha=alpha;
   g.drawImage(i.getImage(),findPlace(absScaleX,absScaleY,absPosX,absPosY,absAlpha,sizeX,sizeY,imgX,imgY),null);
   }
  }


The follow is a running example


package base;

import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;

import com.jme.app.SimpleGame;
import com.jme.math.FastMath;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.TextureState;

public class TestImageIconComposition extends SimpleGame {
public static void main(String[]s){
   SimpleGame app=new TestImageIconComposition();
   app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
    app.start();
   
   
}

@Override
protected void simpleInitGame() {

    ProceduralTextureComposition p=new ProceduralTextureComposition(2500,2500,BufferedImage.TYPE_INT_ARGB);
   
    //p.add(EnchantedLoader.getResource("FOGLIEgmp4.png"),0.1f,0.1f,0.5f,0.5f,0);
    ImageIcon i=new ImageIcon(EnchantedLoader.getResource("FOGLIEgmp4.png"));
    for(int ii= 2000;ii>0;ii--){
      float scale=0.08f+FastMath.nextRandomFloat()/30f;
      p.add(i,scale,scale,FastMath.nextRandomFloat(),FastMath.nextRandomFloat(),FastMath.nextRandomFloat()*FastMath.PI);
    }
    Quad q=new Quad("prova",100,100);
    Quad q2=new Quad("prova2",100,100);
    q2.setLocalTranslation(0,0, -1);
    TextureState ts = display.getRenderer().createTextureState();
    ts.setEnabled(true);
    ts.setTexture(p.generateTexture());
    q.setRenderState(ts);
    Activate.alpha(q);
    rootNode.attachChild(q);
    rootNode.attachChild(q2);
   
}
}



and that is a screeenshot of the results

http://picasaweb.google.com/marco.servetto/JmeData/photo#5167646176588833506

and this is the starting leaf



http://picasaweb.google.com/marco.servetto/JmeData/photo#5167646180883800818

Can you imagin the result with better starting image, and more than one type of leaf? :)

Looks nice, thanks for sharing! :slight_smile:



(To really nitpick, shouldn't FastMath.TWO_PI be used for alpha when calling p.add in the example?)

Gathers said:

Looks nice, thanks for sharing! :)

(To really nitpick, shouldn't FastMath.TWO_PI be used for alpha when calling p.add in the example?)

Toh, tou are righth, i will fix it in my leaf generator :)
Naelh8 said:

Can you imagin the result with better starting image, and more than one type of leaf? :)


No, perhaps you should try it and post a screenie!  ;)