Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat
Get pixel information from Bitmap or Texture - Gideros Forum

Get pixel information from Bitmap or Texture

totebototebo Member
edited November 2015 in General questions
Is there a way to access pixel information in Gideros? Something along the lines of:
local pixel = Texture:getPixel(x,y)
My Gideros games: www.totebo.com


  • ar2rsawseenar2rsawseen Maintainer
    Accepted Answer
    There are 2 ways
    1) using media plugin:
    local media = Media.new(imagePath)
    media:getPixel(x, y)
    media:setPixel(x, y, 255, 0, 0, 0.5)
    2) using hidden Dib class (I don't know if it still works though)

    Likes: totebo

    +1 -1 (+1 / -0 ) Share on Facebook
  • I had never heard of Dib! Regrettably it crashes the player without an error.
    My Gideros games: www.totebo.com
  • So probably it is not usable anymore, due to recent changes in graphical API
  • totebototebo Member
    edited September 2016
    Trying out the new RenderTarget:getPixel(). It's really slow, even with a RenderTarget of 1x1 pixel. I seem to remember reading this is expected, but can't find it in the forum.

    Is there an efficient way of getting the colour of a pixel nowadays?
    My Gideros games: www.totebo.com
  • hgy29hgy29 Maintainer
    Yes, it is slow because texture data is stored in GPU memory, and is not directly accessible by CPU. What is your use case ?
    If you need to access Bitmap data, that is something that shouldn't change, then you get grab all pixels once in a lua array (with RenderTarget:getPixels()) and look them up at will afterwise.
  • My use-case isn't entirely straightforward, but since you asked! :)

    1. Load tilemap
    2. Merge all passive tiles into one background layer
    3. Get pixel from background layer to determine which sound to play when walking on surface
    My Gideros games: www.totebo.com
  • You should pre-calculate these and have an array the same as the map with the tile detail data.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
  • hgy29hgy29 Maintainer
    Since you use a tilemap, then why not just looking up in the tilemap and map sounds on a tile by tile basis instead of per pixel ?
  • Yeah, that would work. Thanks guys!

    Likes: SinisterSoft

    My Gideros games: www.totebo.com
    +1 -1 (+1 / -0 ) Share on Facebook
  • keszeghkeszegh Member
    edited August 2017
    per-pixel image manipulation does work still via media class or is there now some other method?

    i guess shaders would also work (i want to morph/warp the image). any other method?
  • any recommendations about best way to edit pixels of an image/morph an image?
  • fyi i decided to use shaders to morph images.
    +1 -1 (+2 / -0 ) Share on Facebook
  • guys, can you tell me how to get the color of a specific pixel on screen in the latest gideros version (as of 2018.10)? thanks
  • for your information i did it the following way:
    local _backgroundcolor=0
    function colorPicker(x,y)
    if not rtColorPicker then rtColorPicker=RenderTarget.new(1,1) end
    local col=rtColorPicker:getPixel(0,0)      
    return col

    Likes: Apollo14

    +1 -1 (+1 / -0 ) Share on Facebook
  • perrochonperrochon Member
    edited June 2020
    Is there a way to do this without writing the file back? I currently have a red Samurai in a file, and want to make him green. I have the following code based on the accepted answer above and the example in Github gmedia

    An easier way that doesn't require media would work, too. The reason I need bitmaps at the end is that I actually have a Samurai animation, and I add them to a MovieClip
        local media = Media.new("images/Samurai_02.png")
        for x = 0, media:getWidth() do
            for y = 0, media:getHeight() do
    			local r,g,b,a = media:getPixel(x,y)
                media:setPixel(x, y, g, r, b, a) -- note order change, switch red and green
        path = media:getPath()
        local greenSamurai = Bitmap.new(Texture.new(path, true))
  • hgy29hgy29 Maintainer
    edited June 2020
    Make you samurai white (gray scale) then use setColorTransform on your sprite. That way you use the same texture for all your samurais
  • hgy29hgy29 Maintainer
    Or you could use a shader to swizzle color components on the GPU at render time
  • Yeah, i wasn't specific enough. I have an existing asset with red armor, and I just want the armor to turn green. I tried ColorTransform first. Problem was the face turned green, too, and I couldn't figure out how not make him look sick. Sword, etc all turn green, too.

    My current heuristic is slightly more complicated, I don't change all colors, only strong reds (r>120, b<120). I can create a little separate lua project that generates all these assets and then copy them over, but it inflates the assets directory. Plan B.

    I could learn how to use shaders... Any good pointers on where to start? Maybe this is Plan A.

    PS: I don't have access to the original art files to recreate, and it's a pain to change 80 frames for multiple characters. Would be better to start from scratch, which I might eventually, but it's a bit of a cost issue, as I'd outsource it. That is plan C. Would still be neat to change uniform color on the fly, instead of duplicating raster assets.
  • plan D, separate the armor from the body and apply settransformcolor on the armor?
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • keszeghkeszegh Member
    edited June 2020
    @MoKaLux 's idea is the most natural but if you already have your assets fixed then a simple shader will be easier to use. try out the blur shader example in gideros and change the fShader.glsl to:
    uniform lowp sampler2D fTexture;
    uniform int fRad;
    uniform mediump vec4 fTexelSize;
    varying mediump vec2 fTexCoord;
    void main() {
     lowp vec4 frag=vec4(0,0,0,0); 
     	frag=texture2D(fTexture, fTexCoord);
      if ((abs(frag.r-255.0/255.0)<0.05) && (abs(frag.g-146.0/255.0)<0.05) && (abs(frag.b-53.0/255.0)<0.05)) {frag.r=0.0; frag.g=1.0; frag.b=0.0;}
     gl_FragColor = frag;
    i think from this you will get how it works. note that the blur example has an input fRad which you can modify so that there you can input which color you want to replace to etc. also you don't need complicated range checks as i did, only equality. in the provided texture no single color appeared many times, so i had to do it this way so that you see what happens.
  • Wow, thanks @keszegh that is helping a lot. I see it work, so this is a reasonable way to go, and it's only a few lines of code I can play with. Time to read up on shaders.

    Likes: MoKaLux

    +1 -1 (+1 / -0 ) Share on Facebook
  • Yes, you can use most of the shader related code as a blackbox.
  • In case someone else finds this threads and wants to go down this path: If found this tutorial to be extremely helpful: https://github.com/mattdesl/lwjgl-basics/wiki/Shaders

    The following is helpful to play around with colors: https://thebookofshaders.com/06/

    After spending some time on better and better heuristics, I don't think it's the way to solve my problem. But thanks for usual incredibly quick turn around on my question and the shader example code.

    (My source full res artwork is high resolution and cartoon style with only a few actual colors. But reducing the resolution increases colors. If I swizzle the reduced size asset I get artifacts. I can do even better heuristics, but it's pretty much on a per asset base. I achieve much better results swizzling the few colors on the original asset and pre-compute new assets. Plan B it is. Until I splurge on new artwork. At that point, I could do plan D. I would have to do the animations on the fly, then, instead of precomputing. That seems like a lot more involved. At that point I probably want to go to 3D, too :-))

    Likes: SinisterSoft

    +1 -1 (+1 / -0 ) Share on Facebook
Sign In or Register to comment.