GetPixel(x, y)
Monkey Forums/Monkey Programming/GetPixel(x, y)
| ||
Heres some extern code for HTML5, Flash, GLFW and Android to get RGB pixel at a coordinate: Monkey Code: Extern #If LANG="cpp" Then Function GetColorPixel:Int(x:Int, y:Int)="diddy::getPixel" #Else Function GetColorPixel:Int(x:Int, y:Int)="diddy.getPixel" #End Public Function GetPixel:Int[](x:Int, y:Int) Local colorArr:Int[4] Local color:Int = GetColorPixel(x, y) 'Print color colorArr[0] = (color Shr 16) & $ff colorArr[1] = (color Shr 8) & $ff colorArr[2] = color & $ff colorArr[3] = (color Shr 24) & $ff Return colorArr End HTM5: var diddy = new Object(); diddy.getPixel=function(x, y){ var tcanvas=document.getElementById("GameCanvas").getContext("2d") if (tcanvas==null) return 0; var img = tcanvas.getImageData(x, y, 1, 1); var pix = img.data; return (pix[3]<<24) | (pix[0]<<16) | (pix[1]<<8) | pix[2]; }; Android: class diddy { static int getPixel(int x, int y) { ByteBuffer pixelBuffer = ByteBuffer.allocateDirect(4); pixelBuffer.order(ByteOrder.LITTLE_ENDIAN); GL11 gl = MonkeyGame.app.graphics.gl; if (gl!=null) { gl.glReadPixels((int)x, (int)MonkeyGame.app.graphics.height - y, 1, 1, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, pixelBuffer); int red = pixelBuffer.get(0) & 0xff; int green = pixelBuffer.get(1) & 0xff; int blue = pixelBuffer.get(2) & 0xff; int alpha = pixelBuffer.get(3) & 0xff; // returning ARGB return (alpha<<24) | (red<<16) | (green<<8) | blue; } return 0; } } GLFW: class diddy { public: static int getPixel(int x, int y) { unsigned char pix[4]; glReadPixels(x, app->graphics->height-y ,1 ,1 ,GL_RGBA ,GL_UNSIGNED_BYTE ,pix); return (pix[3]<<24) | (pix[0]<<16) | (pix[1]<<8) | pix[2]; } } Flash: class diddy { static public function getPixel(x:int, y:int):int{ var alpha:Number = 0; var red:Number = 0; var green:Number = 0; var blue:Number = 0; var bmd:BitmapData = new BitmapData(1, 1); var matrix:Matrix = new Matrix(); matrix.translate(-x, -y); bmd.draw(game.stage, matrix); var pixel:uint = bmd.getPixel(0, 0); alpha = pixel >> 24 & 0xFF; red = pixel >> 16 & 0xFF; green = pixel >> 8 & 0xFF; blue = pixel & 0xFF; return pixel; } } For some reason the Flash version returns a slightly darker colour?! Best using this within OnRender... in Android it will only work with OnRender! Usage: Field pixel:Int[3] Method OnRender:Int() If MouseDown() pixel = GetPixel(MouseX(), MouseY()) Print "Red = " + pixel[0] Print "Green = " + pixel[1] Print "Blue = " + pixel[2] End End |
| ||
This is great i was just thinking about how i could achieve this thanks. |
| ||
And if you didn't guess its been added to Diddy ;) |
| ||
Can I ask why the flash version has all that extra code that never gets used? |
| ||
I was trying to work out why it returns a darker shade... |
| ||
I see. Good stuff tho. |
| ||
I can't test this right now... but I wonder if getPixel32 might fix the Flash issue: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/BitmapData.html?filter_flash=cs5&filter_flashplayer=10.2&filter_air=2.6#getPixel32%28%29 |
| ||
getPixel32 didnt fix the issue... its either a Monkey issue or a Flash issue: http://www.monkeycoder.co.nz/Community/posts.php?topic=1861 And I give up on XNA for GetPixel... no idea how to do it for this platform... :( |
| ||
For iOS this might work:static int getPixel(int x, int y) { unsigned char pix[4]; glReadPixels(x, app->graphics->height-y ,1 ,1 ,GL_RGBA ,GL_UNSIGNED_BYTE ,pix); return (pix[3]<<24) | (pix[0]<<16) | (pix[1]<<8) | pix[2]; } (its the same as the GLFW c++ code)... Untested! |
| ||
Samah pointed me to some MSDN code for XNA: http://msdn.microsoft.com/en-us/library/bb197089.aspx Which I've tried but it returns {R:0 G:0 B:0 A:0} :( public static int getPixel(int x, int y) { if ((x > 0 && y > 0 && x < gxtkApp.game.app.graphics.Width()) && (y < gxtkApp.game.app.graphics.Height())) { Texture2D backBufferData = new Texture2D( gxtkApp.game.app.graphics.device, gxtkApp.game.app.graphics.Width(), gxtkApp.game.app.graphics.Height()); Rectangle sourceRectangle = new Rectangle(x, y, 1, 1); Color[] retrievedColor = new Color[1]; backBufferData.GetData<Color>( 0, sourceRectangle, retrievedColor, 0, 1); bb_std_lang.Print("x="+x+",y="+y+" col="+retrievedColor[0].ToString()); } return 0; } Any XNA experts in the house? |
| ||
This is more of a guess. It might be the last two parameters? > Texture2D.GetData (Int32, Nullable<Rectangle>, T[], Int32, Int32) Gets > a copy of 2D texture data, specifying a mipmap level, source rectangle, > start index, and number of elements. So maybe use this overload instead? Color[] colors1DArray = new Color[backBufferData.Width * backBufferData .Height]; Color[,] color2DArray = backBufferData.GetData(colors1DArray); Like I said, not sure, only a guess :) |
| ||
Thanks Tibit, just tried it but it didn't work - worth a go :) It seems if Monkey was using XNA 3 it would be pretty straight forward to do... I've been messing around with RenderTarget2D and I can actually get it to return a colour! Shame it clears the screen to do it and it returns that colour (the default xna purple) ;) GraphicsDevice device = gxtkApp.game.app.graphics.device; int w = device.PresentationParameters.BackBufferWidth; int h = device.PresentationParameters.BackBufferHeight; RenderTarget2D screenshot = new RenderTarget2D(device, w, h, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8); device.SetRenderTarget(screenshot); gxtkApp.game.app.graphics.Flush(); device.SetRenderTarget(null); Color[] data = new Color[w * h]; screenshot.GetData<Color>(data); bb_std_lang.Print("x="+x+",y="+y+" col="+data[x*y].ToString()); |
| ||
Very cool. I can't help thinking about how amazing it would be if this was a method of mojo.graphics.Image. While working on quick projects using frameworks other than Monkey, sometimes I like to store static array data (like 2D maps, where each pixel represents a tile and different colors represent different classifications of tiles) using bitmaps -- just to make editing the data simple and fun. I believe Markus Persson is known for doing this while participating in 48-hour game jams. ;) |
| ||
That's exactly what I'd like to do: Store level-data in an image. For that, I'd need a "getpixel" that can actually return an image's pixel rgb value, not the canvas. Any idea? |
| ||
can you get a pixel from an image. say i want to scan a png image and determan its borders. so i can create a poly frame for the image. thats the goal.. for box2d purposes.. cheers |
| ||
For getting a pixel from an image without drawing it you need to alter mojo's graphics.monkey so that the Surface class is public (remove Private from line 35) and the surface field from Image (remove Private line 118). Then you can do something like this for HTML5: Extern Function GetImageColorPixel:Int(image:Surface, x:Int, y:Int)="diddy.getImagePixel" Public Function GetImagePixel:Int[](image:Image, x:Int, y:Int) Local colorArr:Int[4] Local color:Int = GetImageColorPixel(image.surface, x, y) colorArr[0] = (color Shr 16) & $ff colorArr[1] = (color Shr 8) & $ff colorArr[2] = color & $ff colorArr[3] = (color Shr 24) & $ff Return colorArr End And the javascript code: diddy.getImagePixel=function(surface, x, y) { if (!bb_app_device.graphics.tmpCanvas) { bb_app_device.graphics.tmpCanvas=document.createElement( "canvas" ); } var tgc=bb_app_device.graphics.tmpCanvas.getContext( "2d" ); tgc.drawImage( surface.image , x, y, 1, 1, x, y, 1, 1); var imgData=tgc.getImageData( x, y , 1, 1); var pix = imgData.data; return (pix[3]<<24) | (pix[0]<<16) | (pix[1]<<8) | pix[2]; } This is very slow... I looped thru a 16x16 image getting all the pixels and it took 477ms. So it is doable but you need to hack mojo. |
| ||
thanks therevills ill give it a shot. |
| ||
A fast putPixel(x,y, r,g,b) would be very nice as well... |
| ||
look at this therevills After I capture one Pixle is there a way to know if its empty or not. I mean is there a way to know the Image weight. if so.. problem solved for scanning. |
| ||
Weight? Do you mean height and width? I really don't know what you are trying to do with that code sample... In Monkey you can do image.Width() and image.Height()... |
| ||
what i did in this code is just taking a pixel from the image. i thought maybe with one pixel there is a way to know if its an empty pixel or not somehow without sampeling its color. |
| ||
Ahhh gotcha! Did you see that the Monkey code GetImagePixel returns an array of 4 values, one for red, green, blue and alpha. So using this you can change your GrabImagePix to be this: Then you can test pixel[3], if it is 0 (zero) it is an empty pixel. |
| ||
Did the iOS version work? I guess iOS doesn't want you to work like this, but it still would have great benefit for users. |
| ||
Not sure... I havent had chance to test it, it should work though... |
| ||
theevills this is my code file Extern Function GetImageColorPixel:Int(image:Surface, x:Int, y:Int)="diddy.getImagePixel" Public Function GetImagePixel:Int[](image:Image, x:Int, y:Int) Local colorArr:Int[4] Local color:Int = GetImageColorPixel(image.surface, x, y) colorArr[0] = (color Shr 16) & $ff colorArr[1] = (color Shr 8) & $ff colorArr[2] = color & $ff colorArr[3] = (color Shr 24) & $ff Return colorArr End Function GrabImagePix:Void(anImage:Image) Local w:Int = anImage.Width() Local h:Int = anImage.Height() Local pix:Image Local pixel:Int[4] Local start% = Millisecs() If w>0 And h>0 Then For Local i:Int = 0 Until w For Local j:Int = 0 Until h pix = anImage.GrabImage(i, j, 1, 1) pixel = GetImagePixel(pix, i, j) Print(i+","+j+" = "+ pixel[0]+","+pixel[1]+","+pixel[2]+" a="+pixel[3]) Next Next End Local fin% = Millisecs() Print "Time = "+(fin-start) End why do i get this error? Error : Field Image.surface:Surface is private i did import diddy and mojo whats missing... |
| ||
you could go into the source code and remove the private keyword, its probably just there so people dont access it who dont know what they are doing the source file is modules/mojo/graphics.monkey i think |
| ||
hehe like me :p tnx |
| ||
How can I get Getpixel to work in mojo without using Diddy? |
| ||
Create your own extern file and just copy the code... |
| ||
Thanks therevills, I've got my own minified version of 'diddy' working now! |