Slick Forums

Discuss the Slick 2D Library
It is currently Sat May 25, 2013 10:26 pm

All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Sun May 20, 2012 1:22 pm 
Offline

Joined: Sun May 20, 2012 1:16 pm
Posts: 4
Hello. I'm using the following code to construct an animated image, slicing one big image to parts:


Code:
package core.main.graphics;

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;

import core.main.Player;

public class AnimatedImage implements Drawable{
   
   private Image sourceImg;
   private Image img;
   
   private Image animated[];
   private Image tcolored[][];
   private int length, count, width, height;
   private int animNum, colorNum;

   public AnimatedImage(Image img, Image teamcolor, int width, int height){
      try{
         animNum = 0;
         colorNum = 0;
         int clength = Player.playerColors.length + 1;
         sourceImg = img;
         length = (int) (img.getWidth() / width);
         count = (int) (img.getHeight() / height);
         animated = new Image[count * length + count];
         tcolored = new Image[clength][animated.length];
         this.width = width;
         this.height = height;
         
         for(int i = 0; i < count; i++)
            for(int j = 0; j < length; j++){
               Image bi = new Image(width, height);
               Graphics g = bi.getGraphics();
               g.drawImage(img, -j * width, -i * height, null);
               g.destroy();
               animated[length * i + j] = bi;
               for(int k = 0; k < clength; k++){
                  bi = new Image(width, height);
                  g = bi.getGraphics();
                  g.drawImage(teamcolor, -j * width, -i * height, null);
                  if (k > 0){
                     Color rec = Player.playerColors[k - 1];
                     for(int l = 0; l < width; l++)
                        for(int n = 0; n < height; n++){
                           Color cur = new Color(bi.getColor(l, n));
                           java.awt.Color ncur = new java.awt.Color(cur.r, cur.g, cur.b, cur.a);
                           if (ncur.getRGB() < -0xFFFFFF)
                              continue;
                           int rc = Math.min(255, cur.getRed() + rec.getRed()),
                              gc = Math.min(255, cur.getGreen() + rec.getGreen()),
                              bc = Math.min(255, cur.getBlue() + rec.getBlue());
                           Color nc = new Color(rc, gc, bc);
                           g.setColor(nc);
                           g.drawRect(l, n, 0, 0);
                        }
                  }
                  g.destroy();
                  tcolored[k][length * i + j] = bi;
               }
            }
         this.img = animated[0];
      } catch(Exception e){
         e.printStackTrace();
      }
   }

   public void draw(Graphics g, double x, double y){
      if (img == null){
         Color cdef = g.getColor();
         g.setColor(Color.red);
         g.fillRect((int) x, (int) y, 4, 4);
         g.setColor(cdef);
      } else {
         int dx = (int) (x - img.getWidth() / 2.),
            dy = (int) (y - img.getHeight() / 2.);
         g.drawImage(img, dx, dy, null);
         g.drawImage(tcolored[colorNum][animNum], dx, dy, null);
      }
   }
   
   public void setAnimation(int num, int step){
      animNum = num * length + step;
      img = animated[animNum];
   }
   
   public void setTeamColor(int clr){
      colorNum = clr + 1;
   }
   
   public int getLength(){
      return length;
   }
}



And it takes over 20 seconds to construct one animated animated image from 320x96 png image, where one piece is 32x32. In pure java this operation is instant. So I can't even test my application normally because of extremely long loading time. What should I do?


Last edited by DoctorGester on Mon May 21, 2012 7:11 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Mon May 21, 2012 2:04 am 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1469
Please use the code tags for code... :)

A few things:
  • Slick2D tries to emulate Java2D's architecture for familiarity, but behind the scenes they are very different, so you shouldn't expect it to translate 1:1.
  • OpenGL textures are not free; they are limited by the user's GPU (in quantity and size; e.g. 2048x2048). Your code creates numerous textures in each iteration:
    Code:
    bi = new Image(width, height); // <-- new texture created here

    There is also a bug/limitation with Slick's getGraphics architecture that creates an OpenGL texture when you do this:
    Code:
    bi.getGraphics(); // <-- new texture created here

    More info here and here (dev branch includes temp workaround).
  • You should try to share and reuse offscreen images as much as possible, instead of creating and then immediately destroying them.

You might want to look into Slick's Animation class, and Image's getSubImage (which returns a shallow copy; i.e. it's very fast). If you let us know exactly what you're going for (maybe show pictures of before/after), we could provide alternative ways that would be more efficient.


Top
 Profile  
 
PostPosted: Sun May 27, 2012 12:09 am 
Offline

Joined: Sun May 20, 2012 1:16 pm
Posts: 4
Ok. I've found the way to do my image operations faster.
I'm now doing all stuff with pure java and BufferedImage and converting it into slick image with this code:

Code:
public static Image toSlick(BufferedImage img){
   int width = img.getWidth(),
      height = img.getHeight();
   ImageBuffer ib = new ImageBuffer(width, height);
   Raster r = img.getRaster();
   for(int x = 0; x < width; x++)
      for(int y = 0; y < height; y++){
         int clr[] = new int[4];
         r.getPixel(x, y, clr);
         ib.setRGBA(x, y, clr[0], clr[1], clr[2], clr[3]);
      }
   return ib.getImage();
}


It just manually writes pixels from BufferedImage to Slick ImageBuffer and then returns an Image.


Top
 Profile  
 
PostPosted: Sun May 27, 2012 6:23 am 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1469
Maybe that is a little better, but you will still suffer a lot since it requires copying data from BufferedImage to ImageBuffer, and then creating a new Slick Image every time.

If you are doing this a lot and need better performance, you might be interested in the PixelData utility I'm working on:
http://slick.cokeandcode.com/wiki/doku. ... ta_utility

The basic gist of it: write your pixel data once, then "apply" the pixels to your texture(s). This way, you could efficiently modify texture data every frame (or as needed) and reuse the same texture as much as possible, rather than creating a new one each time.


Top
 Profile  
 
PostPosted: Sun May 27, 2012 11:23 am 
Offline

Joined: Sun May 20, 2012 1:16 pm
Posts: 4
> Maybe that is a little better, but you will still suffer a lot since it requires copying data from BufferedImage to ImageBuffer, and then creating a new Slick Image every time.

If I will, I'll use your class. But for now loading images is just as fast as in pure java.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group