Change color in a sprite

Home Forums Monkey 2 Programming Help Change color in a sprite

This topic contains 17 replies, has 6 voices, and was last updated by  ArtemKuchin 1 week, 3 days ago.

Viewing 15 posts - 1 through 15 (of 18 total)
  • Author
    Posts
  • #10322

    ArtemKuchin
    Participant

    hello!

    I am very new to Monkey. I learned the languages Prtty easy (i already have C,ASM,C++,C#,perl,php etc… in my work, so, this is nothing new), but i am not good with graphics. Mostly done data processing all my life.

    So, i need to have several sprites, mostluy monochrome, but some can have several colors. And before drawng them i need to change a certain color to other one in a sprite. I have no clue where to start for this task. Everything is strictly 2d.

    For exaple, i need to draw 50 monochrome sprites. I load them from file Then i need to change thge color of a sprte to some other color. For example, there are white by default and i change to red. Then draw 50 red sprites. The colro is actually user selectable, if it matters.

    #10325

    Hezkore
    Participant

    Just draw the sprites as normal, and when you want to switch colour you do canvas.color=Color.Red or whatever and draw all the red sprites.
    You can also do canvas.color=New Color( r:float, g:float, b:float) to set your own custom colour.

    I don’t have Monkey 2 installed right now, so the syntax is bound to be incorrect, but the general idea will work.

    #10329

    nerobot
    Participant

    Also there is an Image.Color property.

    #10333

    ArtemKuchin
    Participant

    Thank you

    I tried mojotest app from bananas

     

    did this:

    image=Image.Load( “asset::RedbrushAlpha.png” ) image=Image.Load( “asset::RedbrushAlpha.png” ) image.Color=Color.Grey

    The result is strange. Seems .color does not replacem pixel colors, but mixes with pixels in image.

    See attached file.

     

    Also, this way i do not have any way to choose what color to replace. But it is secondary task.

    #10335

    nerobot
    Participant

    Yes, colors mixes. To get clean custom color your source image should be white.

    #10336

    ArtemKuchin
    Participant

    Aha, found this in image class description

     

      <li class=”mx2docs”>Color – when rendering an image to a canvas, this property is multiplied by the current canvas color and the result is multiplied by actual image pixel colors to achieve the final color to be rendered.

    So, color does not do it.

    I guess i need a way to directly manipulate pixels in image or on canvas in ARGB fomat.

    I don’t see anyt ReadPixels/WritePixels in mojo2 for images and buffers.

    Is it possible?

    #10339

    abakobo
    Participant

    For exaple, i need to draw 50 monochrome sprites. I load them from file Then i need to change thge color of a sprte to some other color. For example, there are white by default and i change to red. Then draw 50 red sprites. The colro is actually user selectable, if it matters.

    If you start with white images you can use the .Color stuff because white multiplied by a color is the color…
    I made a small sample (attached zip) that shows that the white dot is always getting the correct color.

    I don’t see anyt ReadPixels/WritePixels in mojo2 for images and buffers.

    There’s something with Image.Texture and Pixmaps.GetPixel but I don’t remember and the link to Texture in the docs is broken.. Can’t find the example I made at the time.

    I made a small sample (attached zip) that shows that the white dot is always getting the correct color.

    EDIT: Texture is hidden from docs.. At the time I did some modifications to play around with monkey2 itself so I don’t really know how you can “extract” the pixmap of an Image. Maybe create a new Canvas with the Image then myCanvas.CopyPixmap then myPixmap.Getpixel. But this is so complicated. Image.GetPixel would be nicer..

    Attachments:
    1. sprite_color.zip
    #10341

    abakobo
    Participant

    here’s an Image Extension that will do Image.GetPixel (very slow!). There’s also an Image.GetPixmap (faster to scan the whole image (untested)) but i’m not quite sure how the resource will be managed..

    I’m not sure it’s the right/good way to do it though! It’s so complex for such a simple thing…

    #10343

    TomToad
    Participant

    You could always keep a copy of the image in a pixmap, then you can alter the pixmap with pixmap.SetPixel() when you need to and use New Image(pixmap) to transfer the altered pixmap to an image for rendering

    #10345

    nerobot
    Participant

    Or you can write own fragment shader to process images.

    Little more info: http://monkeycoder.co.nz/forums/topic/image-with-texture-mask/

    My idea is

    • pass R1 G1 B1 /  R2 G2 B2 (to get by-component control) integer parameters into shader using Image.Material.SetInt( “R1”,200 ) method,
    • inside of shader get color components, translate them into integers (color has ‘float vec4’ type in shader) and compare with your R1 G1 B1
    • if there is a match – replace color with R2 G2 B2, converted back to float
    #10347

    abakobo
    Participant

    You could always keep a copy of the image in a pixmap

    To me the problem is more how to get the pixmap out of a loaded .png image. Once you have the pixmap you can use Pixmap.Getpixel() or GetARGBpixel().

    Nerobot’s solution is of course top performance but needs more work/knowledge.

    #10351

    ArtemKuchin
    Participant

    aha, so i neex pixelmap, not image

    pixelmap has load  method which load from png and save which saves to png

    that’s very good, i will play with it

    #10353

    abakobo
    Participant

    pixelmap has load method

    how can I have missed that!

    #10354

    ArtemKuchin
    Participant

    Okay, i have done it. See code below. HOWEVER one thing i don’t understand. if ALPHA channel is ZERO i can still the color. To fully hide pixel i need to set ALPHA to zero and RGB to zero also. This i don’t understand.

     

    Attachments:
    #10356

    Mark Sibly
    Keymaster

    if ALPHA channel is ZERO i can still the color. To fully hide pixel i need to set ALPHA to zero and RGB to zero also.

    This is because image rendering uses pre-multiplied alpha. This is a technique where image colors are assumed to be pre-multiplied by image alpha – more information here (and much more via goggle):

    Premultiplied alpha

    You can premultiply pixmap data like this by setting the pmAlpha parameter of Pixmap.Load to true when loading a pixmap, or using the Pixmap.PremultiplyAlpha method.

    Note that Image.Load is really just a ‘wrapper’ around something like this:

    If you want to modify  image pixels when loading, the best way to do it is to use Pixmap.Load as above, modify the pixmap, then use New Image to create  anew image with the modified pixmap.

    Image are not really intended to be ‘read’ by the CPU. In fact, the more HW evolves, the harder this gets – in Open GL ES there aren’t even any commands for reading texture data, so you need to render and then copy from the backbuffer! The has the potential to lose lots of precision along the way, as textures/backbuffers masy be in a crappy format behind the scenes on some taregets and texture data may be compressed etc etc.

    The only way to guarantee ‘clean’ pixele data is by using Pixmap.Load and using the pixel data *before* it reaches the image/texture. Once things reach the GPU, they should ideally only be read by the GPU – which includes shaders, which can easily access texture data (although again it may not be exactly the same as the original pixmap data on some targets).

Viewing 15 posts - 1 through 15 (of 18 total)

You must be logged in to reply to this topic.