Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (487)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (553)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Colouring a grayscale image  (Read 3051 times)
0 Members and 1 Guest are viewing this topic.
Offline zammbi

JGO Coder


Medals: 4



« Posted 2008-06-12 13:49:14 »

I'm now using grayscale alpha images for particles in my basic particle generator but I'm not sure how I'm meant to colour these right also need the fastest way  Wink.
Can anyone help?

Current project - Rename and Sort
Offline trembovetski

Senior Member




If only I knew what I'm talking about!


« Reply #1 - Posted 2008-06-12 17:28:30 »

Why do you use images for particles? Couldn't you use fillRect, for example?

Anyway, to be honest I'm not so familiar with particle generation - it would
be useful if you showed some piece of code (or just a simple explanation of
how it is done and why images were used)..

Dmitri
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 783
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #2 - Posted 2008-06-12 17:51:45 »

I think he just want an image multiplied by a color, like you can do in OpenGL with textures.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline noblemaster

JGO Ninja


Medals: 20
Projects: 10


Age of Conquest makes your day!


« Reply #3 - Posted 2008-06-12 18:26:44 »

You could create a Composite class for colors.

Here is something similar, that darkens an image:
http://www.koders.com/java/fid9AD328238C12CCB6A7500C98D20EC1622412BABB.aspx?s=rgbcomposite

I actually created a composite class not too long ago, that takes a color and transforms all the non-transparent parts. Not sure if that works in your case? I could probably post the code...

Offline zammbi

JGO Coder


Medals: 4



« Reply #4 - Posted 2008-06-13 00:27:42 »

Well I can post code if you wish, but its not pretty yet...

This is generator code, which has a array of particles(which hold x,y,creation time). As you can see the old code is commented out that used fill but that wasn't getting the effect I wanted and by reading other particle posts I it seems that images were faster.
I was just wondering if there was just a basic method that could just simply color the particles.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
   public void render(final Graphics2D g){
      if(stop){
         return;
      }
     
      final long currentTime = System.currentTimeMillis();
      int i =0;
      final long leftOver = currentTime - lastUpdateTime;

      Particle currentParticle;
      final Random randomNumber = new Random();
      int partX, partY,partAngle, alpha, newSize;
      long age;
      float percentLifeLeft;
      while(i < particles.size()){
         currentParticle = particles.get(i);
         age = currentTime - currentParticle.getCreationTime();
         if(age > aliveTime){
            particles.remove(i);
            continue;
         }
         
         percentLifeLeft = (float)age/(float)aliveTime;
         if(startSize == finishSize){
            newSize = startSize;
         }
         newSize = (int)(startSize - startSize*percentLifeLeft);
         
         if(newSize == 0){
            particles.remove(i);
            continue;
         }
         
         
         partX = currentParticle.getX();
         partY = currentParticle.getY();
         
         
         partAngle = currentParticle.getAngle();
         alpha = (int)(255 -255 * percentLifeLeft);
         
         //if(alpha < 255 - ALPHACUTOFFRANGE){
        //   g.setColor(new Color(0,0,255,alpha));
        //}
        //else{
        //   g.setColor(new Color(0,0,255));
        //}
       
         //g.fillRect(partX, partY, newSize, newSize);
       
         
         g.drawImage(particleImage, partX, partY,newSize,newSize, null);
         //g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
        if(leftOver > 1000){
            currentParticle.setX((int)(partX + Math.sin(partAngle)*speed));
            currentParticle.setY((int)(partY + Math.cos(partAngle)*speed));
         }
         i++;

      }

      if(leftOver > 1000){
         if(particles.size() <= maxParticles){
            for(int j = 0; j< particlesPerSec; j++){
               particles.add(new Particle(x,y,randomNumber.nextInt(360),currentTime));
            }
         }
         lastUpdateTime = currentTime - (leftOver-1000);
      }

   }

Current project - Rename and Sort
Offline noblemaster

JGO Ninja


Medals: 20
Projects: 10


Age of Conquest makes your day!


« Reply #5 - Posted 2008-06-13 05:04:18 »

I attached you the composite classes (copy them somewhere into your project). The bold code sample below colors all non-transparent areas with the color requested (also works for translucent images):

Color color = ...
Composite oldComposite = g2.getComposite();
g2.setComposite(new ColorComposite(1.0f, color);
g2.drawImage(image, 0, 0, null);
g2.setComposite(oldComposite);

 
Please note that my ColorComposite class ignores the alpha value! It works well, it just could have been implemented better. Let me know if you have questions...

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
/**
 * Color Composite.
 *
 * @author Christoph Aschwanden
 * @since June 9, 2008
 */

public final class ColorComposite extends RGBComposite {

  /** The color. */
  private Color color;
 
 
  /**
   * Constructor.
   *
   * @param alpha  The alpha level.
   * @param color  The color.
   */

  public ColorComposite(float alpha, Color color) {
    super(alpha);
    this.color = color;
  }

  /**
   * Creates the context.
   *
   * @param srcColorModel  The source color model.
   * @param dstColorModel  The destination color model.
   * @param hints  The rendering hints.
   * @return The context.
   */

  public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) {
    return new Context(extraAlpha, color, srcColorModel, dstColorModel);
  }

  /**
   * The context.
   */

  static class Context extends RGBCompositeContext {

    /** The color. */
    private int color;
   
   
    /**
     * Constructor for context.
     *
     * @param alpha  The alpha level.
     * @param color  The color.
     * @param srcColorModel  The source color model.
     * @param dstColorModel  The destination color model.
     */

    public Context(float alpha, Color color, ColorModel srcColorModel, ColorModel dstColorModel) {
      super(alpha, srcColorModel, dstColorModel);
     
      // save color
     this.color = color.getRGB() & 0x00ffffff;
    }

    /**
     * The composing function.
     *
     * @param srcRGB  The source RGB.
     * @param dstRGB  The pre-destination RGB.
     * @param alpha  The alpha level in the range [0, 1].
     * @return  The compbined destination RGB.
     */

    @Override
    public int composeRGB(int srcRGB, int dstRGB, float alpha) {
      int opacity = (srcRGB >> 24) & 0xff;
      if (opacity > 0) {
        int r0 = (this.color >> 16) & 0xff;
        int g0 = (this.color >> 8) & 0xff;
        int b0 = (this.color) & 0xff;    
        r0 = r0 * opacity / 255;
        g0 = g0 * opacity / 255;
        b0 = b0 * opacity / 255;
       
        int r1 = (dstRGB >> 16) & 0xff;
        int g1 = (dstRGB >> 8) & 0xff;
        int b1 = (dstRGB) & 0xff;    
        int revertOpacity = 255 - opacity;
        r1 = r1 * revertOpacity / 255;
        g1 = g1 * revertOpacity / 255;
        b1 = b1 * revertOpacity / 255;

        return 0xff000000 | ((r0 + r1) << 16) | ((g0 + g1) << 8) | (b0 + b1);
      }
      else {
        // was fully transparent...
       return dstRGB;
      }
    }
  }
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
/**
 * Color Composite. Based on code by "Jerry Huxtable".
 *
 * @author Christoph Aschwanden
 * @since June 9, 2008
 */

public abstract class RGBComposite implements Composite {

  /** The extra alpha value. */
  protected float extraAlpha;

  /**
   * Constructor.
   */

  public RGBComposite() {
    this(1.0f);
  }

  /**
   * Constructor.
   *
   * @param alpha  The alpha level.
   */

  public RGBComposite(float alpha) {
    if (alpha < 0.0f || alpha > 1.0f) {
      throw new IllegalArgumentException("RGBComposite: alpha must be between 0 and 1");
    }
    this.extraAlpha = alpha;
  }

  /**
   * Returns alpha.
   *
   * @return  Alpha level.
   */

  public float getAlpha() {
    return extraAlpha;
  }

  /**
   * Returns the hash code.
   *
   * @return  The hash code.
   */

  public int hashCode() {
    return Float.floatToIntBits(extraAlpha);
  }

  /**
   * True if equal.
   *
   * @param object  The other object to compare this to.
   * @return  True for equal.
   */

  public boolean equals(Object object) {
    if (!(object instanceof RGBComposite)) {
      return false;
    }
    RGBComposite c = (RGBComposite)object;

    if (extraAlpha != c.extraAlpha) {
      return false;
    }
    return true;
  }

  /**
   * The context.
   */

  public abstract static class RGBCompositeContext implements CompositeContext {

    /** The alpha level. */
    private float alpha;
    /** The source model. */
    private ColorModel srcColorModel;
    /** The destination model. */
    private ColorModel dstColorModel;
   
   
    /**
     * Constructor for context.
     *
     * @param alpha  The alpha level.
     * @param srcColorModel  The source color model.
     * @param dstColorModel  The destination color model.
     */

    public RGBCompositeContext(float alpha, ColorModel srcColorModel, ColorModel dstColorModel) {
      this.alpha = alpha;
      this.srcColorModel = srcColorModel;
      this.dstColorModel = dstColorModel;
    }

    /**
     * Dispose function.
     */

    public void dispose() {
      // not used
   }

    /**
     * The composing function.
     *
     * @param srcRGB  The source RGB.
     * @param dstRGB  The pre-destination RGB.
     * @param alpha  The alpha level.
     * @return  The compbined destination RGB.
     */

    public abstract int composeRGB(int srcRGB, int dstRGB, float alpha);

    /**
     * Composer.
     *
     * @param src  The source.
     * @param dstIn  The destination in.
     * @param dstOut  The destination out.
     */

    public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
      float alpha = this.alpha;

      int x0 = dstOut.getMinX();
      int x1 = x0 + dstOut.getWidth();
      int y0 = dstOut.getMinY();
      int y1 = y0 + dstOut.getHeight();

      for (int x = x0; x < x1; x++) {
        for (int y = y0; y < y1; y++) {
          int srcRGB = srcColorModel.getRGB(src.getDataElements(x, y, null));
          int dstInRGB = dstColorModel.getRGB(dstIn.getDataElements(x, y, null));
          int dstOutRGB = composeRGB(srcRGB, dstInRGB, alpha);
          dstOut.setDataElements(x, y, dstColorModel.getDataElements(dstOutRGB, null));
        }
      }  
    }
  }
}

Offline zammbi

JGO Coder


Medals: 4



« Reply #6 - Posted 2008-06-13 05:50:46 »

Thanks so much I'll give it a try and tell how it goes tonight.

Current project - Rename and Sort
Offline noblemaster

JGO Ninja


Medals: 20
Projects: 10


Age of Conquest makes your day!


« Reply #7 - Posted 2008-06-13 05:52:09 »

Let me know if you run into problems. It works great for my by the way  Grin

Offline zammbi

JGO Coder


Medals: 4



« Reply #8 - Posted 2008-06-13 07:59:53 »

Double checking, I add this in my generator render method:
1  
2  
3  
4  
Composite oldComposite = g2.getComposite();
g2.setComposite(new ColorComposite(1.0f, color);
g2.drawImage(image, 0, 0, null);
g2.setComposite(oldComposite);


When I do this, my cpu shoots up to 99 (from 2-3)and only see 1-2 particles on screen.

Current project - Rename and Sort
Offline noblemaster

JGO Ninja


Medals: 20
Projects: 10


Age of Conquest makes your day!


« Reply #9 - Posted 2008-06-13 09:33:01 »

Sorry, I forgot to mention: it's NOT fast.

Let me make a suggestion: don't use the color composite in each rendering loop. Just create a copy of the original image the first time you show a new color. I assume you do not need to change the image in each loop, just keep 1 or several copies of the original image with the different colors you are planning to render with. I assume your particles are rather small, so having 20-50 particle images cached doesn't really use much memory?

EDIT: If you are using Java2D, there is no silver bullet for fast rendering to my knowledge. There are other techniques you could use such as a flood fill but it's probably going to be even slower...

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline zammbi

JGO Coder


Medals: 4



« Reply #10 - Posted 2008-06-13 12:21:14 »

Ah I see. I guess I have a few options.
Depending how much I step though the alpha/colours would depend on how many images I need. Though I guess it wouldn't be large in the ram...
Otherwise I keep with the circles, which are not that great on top of each other.
Or could have a option for both Smiley

Though would thought there would be a easier way to colour a image. Since there's easy and fast way to make a colour image to grayscale.

Current project - Rename and Sort
Offline zoto

Senior Member


Medals: 4



« Reply #11 - Posted 2008-06-21 13:36:15 »

Heres some code I wrote a few months ago.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
   /**
    * Create a new BufferedImage that is a color version of the original grayscale image.
    *
    * @param grayscaleImg The source image to be colored.
    * @param newColor The color to use for the coloring of the image.
    * @return The new color image.
    */

   static public BufferedImage colorImage(BufferedImage grayscaleImg, Color newColor){
      int [] pixels = grabPixels(grayscaleImg);
      if (pixels==null || newColor == null)
         return grayscaleImg;
      int r, g, b, a, shade, red, green, blue, color;
      red = (0x00FF0000 & newColor.getRGB()) >> 16;
      green = (0x0000FF00 & newColor.getRGB()) >> 8;
      blue = (0x000000FF & newColor.getRGB());
      for (int i=0; i<pixels.length;i++){
         a = pixels[i] >> 24;
      if(a!=0){
         shade = (0x000000FF & pixels[i]);
         r = (red*shade/255);
         g = (green*shade/255);
         b = (blue*shade/255);
         a <<= 24;
         r <<= 16;
         g <<= 8;
         //b <<= 0;
        color = a|r|g|b;
         pixels[i] = color;
      }
      }
      return makeImage(pixels, grayscaleImg.getWidth(), grayscaleImg.getHeight());
   }


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
   /**
    * This function creates an integer array from the pixel colors of the image passed into it.
    *
    * @param img The source image.
    * @return An integer array containing the color information. The 4 bytes of the integer are used for each color attribute, the first byte is the alpha information and the last 3 are the RGB(Red Green Blue) values.
    */

   static public int[] grabPixels(BufferedImage img) {
      int w = img.getWidth();
      int h = img.getHeight();
      int[] pixels = new int[w * h];
      try {
         img.getRGB(0,0,w,h,pixels, 0, w);
      } catch (Exception e) {
         System.err.println("interrupted waiting for pixels!");
         return null;
      }
      return pixels;
   }

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
   /**
    * Create a new BufferedImage from the information provided.
    *
    * @param pixels The color information stored as an integer. The 4 bytes of the integer are used for each color attribute, the first byte is the alpha information and the last 3 are the RGB(Red Green Blue) values.
    * @param sizeX The width in pixels of the image.
    * @param sizeY The height in pixels of the image.
    * @return A new image created from the information.
    */

   static public BufferedImage makeImage(int[] pixels, int sizeX, int sizeY) {
      BufferedImage img = new BufferedImage(sizeX, sizeY, BufferedImage.TYPE_INT_ARGB);
      img.setRGB(0,0,sizeX, sizeY, pixels, 0, sizeX);
      return img;
   }
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CopyableCougar4 (23 views)
2014-08-22 19:31:30

atombrot (34 views)
2014-08-19 09:29:53

Tekkerue (30 views)
2014-08-16 06:45:27

Tekkerue (28 views)
2014-08-16 06:22:17

Tekkerue (18 views)
2014-08-16 06:20:21

Tekkerue (27 views)
2014-08-16 06:12:11

Rayexar (65 views)
2014-08-11 02:49:23

BurntPizza (41 views)
2014-08-09 21:09:32

BurntPizza (32 views)
2014-08-08 02:01:56

Norakomi (42 views)
2014-08-06 19:49:38
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!