A Flash Developer Resource Site

Results 1 to 7 of 7

Thread: [RESOLVED] [CS3] Reading screen pixels.

  1. #1
    Senior Member AzraelKans's Avatar
    Join Date
    May 2002
    Location
    Hell... with frequent access to heaven ;)
    Posts
    409

    resolved [RESOLVED] [CS3] Reading screen pixels.

    Im converting a image into a linear 1 bit array is this the fastest way to it?

    btw Sprite.sensibleResult is a threeshold number. Like 0x505050

    Code:
    		public function imgToArray() {
    			var c:int;
    			var rx:int;
    			var ry:int;
    			aimage=new Array(imageSize);
    			for (rx=0; rx<imageWidth; rx++) {
    				bitmap.lock();
    				for (ry=0; ry<imageHeight; ry++) {
    
    					//aimage[(ry*imageWidth)+rx]= 
    					if (bitmap.getPixel(rx,ry)>sprite.sensibleResult) {
    
    						aimage[(ry*imageWidth)+rx]=true;
    						//bitmap.setPixel(rx,ry,0xFFFFFF);
    					} else {
    						aimage[(ry*imageWidth)+rx]=false;
    						//bitmap.setPixel(rx,ry,0x000000);
    					}
    					//trace(aimage[(ry*imageWidth)+rx]);
    
    				}
    				bitmap.unlock();
    			}
    		}

  2. #2
    Senior Member hatu's Avatar
    Join Date
    Jan 2007
    Posts
    480
    I do the reading pretty much exactly in the same way. I don't get the idea of your array but I don't think that changes anything.

    One question, what does bitmap.lock() do? Just make sure nothing can access it while you're reading it?

    edit: also don't you need to convert the data from getPixel to base16?

    Here's my code if you want to compare
    PHP Code:
    public function ReadBitmap(mapTexture:Texture):void {
        var 
    bitWidth:int mapTexture.bitmap.width;
        var 
    bitHeight:int mapTexture.bitmap.height;
                
                
        for (var 
    k:int 0bitWidthk++) {
            for (var 
    l:int 0bitHeightl++){
                
    pixelValue mapTexture.bitmap.getPixel(kl);
                
    pixel pixelValue.toString(16);
                
    setMap(klpixel);
            }
        }

    By the way this returns somewhat weird values, ff is fe and it leaves any 0's out if theres nothing before them. But I'm lazy so I haven't figured a way to fix it.

    0000ff = fe (blue)
    ff0000 = fe0000 (red)
    Last edited by hatu; 02-12-2008 at 04:51 PM.

  3. #3
    Senior Member AzraelKans's Avatar
    Join Date
    May 2002
    Location
    Hell... with frequent access to heaven ;)
    Posts
    409
    edit: also don't you need to convert the data from getPixel to base16?
    Oh no, actually I would recommend against using it since toString(16) uses up to 32 milliseconds or so I used to do it that way too.

    What you get from getPixel is a uint number, if you want to convert r, g, b to that format just do this:

    Code:
    newPixel=(r<< 16)+(g<< 8)+(b));
    and similarly you can get the values back by doing this

    Code:
    r=(newPixel & 0xFF0000)>>16
    g=(newPixel & 0x00FF00)>>8
    b=(newPixel & 0x0000FF)
    The reason why im storing the Image in an array is because that way I can check the image array without using getpixel. (or getByte from a byteArray)

    One question, what does bitmap.lock() do? Just make sure nothing can access it while you're reading it?
    Exactly! changes to the image are discarted until you unlock it again. Although to be honest I havent noticed any speed increase using it.
    Last edited by AzraelKans; 02-12-2008 at 05:29 PM.

  4. #4
    Senior Member hatu's Avatar
    Join Date
    Jan 2007
    Posts
    480
    Ok so this way it turns it into
    blue: 0,0,254

    Which is right but how do I make the uint into a hex then?

  5. #5
    Senior Member AzraelKans's Avatar
    Join Date
    May 2002
    Location
    Hell... with frequent access to heaven ;)
    Posts
    409
    sorry for not answering sooner:

    Hatu;
    you dont need to use the hex value by using the functions described before, however if you need it for whatever reason all you have to do is to use toString16() in the uint number you got. like this.

    Code:
    hexNumberString=myPixel.toString(16)
    Just remember that "number" is actually a string.

    p.s.

    just for the record for those who've read this thread thinking Im not using the obvious solution, I dont need a "byteArray" (which I could get with getPixels) I need a bitArray which only has false and true in it, what for? for fast image shape recognition. The problem is the above method is pretty slow about 50 ms for a 320 x 240 image.

    Also the reason why Im using a linear Array instead of a multidimensional array is because myArray[320*x+y] is faster to access than myArray[x][y] try it. thats because the memory navigation required to find the address where the value is located is easier for the cpu to calculate one mul and an add instead.

  6. #6
    Senior Member AzraelKans's Avatar
    Join Date
    May 2002
    Location
    Hell... with frequent access to heaven ;)
    Posts
    409
    Resolved!

    Well, I tried to use the byteArray just to see what happens (and some profiling as well) and the results are amazing, the original code used up to 1000 ms, by using getPixel to read each pixel in the screen, in comparison gePixels for the entire screen took 11 ms! analyzing that however takes 300-400 ms. But it is still twice as fast. Unless I find a faster (and precise) way to analyze the bytearray data, this is the code Im using from now on.

    So kids eat your byteArrays they are good for you.

    heres the code:
    Code:
    		public function imgToArray() {
    			var ms:int=getTimer();
    			var ba:ByteArray;
    			var rgb:Array=new Array(4);
    			var counter:int=0;
    			var pcounter=0;
    			var myPixel:uint;
    			var byte:uint;
    			
    			aimage=new Array(imageSize);
    			bitmap.lock();
    			ba=bitmap.getPixels(new Rectangle(0,0,imageWidth,imageHeight));
    			
    			trace("-----------ImgToArray MS:" + (getTimer() - ms).toString());			
    			ba.position=0;
    			while (true) {
    				try {
    					byte=ba.readUnsignedByte();
    					rgb[counter]=byte;
    					counter++
    					if (counter>3){
    						
    						myPixel=((rgb[1]<< 16)+(rgb[2]<< 8)+(rgb[3]));
    						if (myPixel<sprite.sensibleResult) {
    							aimage[pcounter]=true;
    						}
    						else {
    							aimage[pcounter]=false;
    						}
    						pcounter++;
    						counter=0;
    					}
    				} catch (e:EOFError) {
    					break;
    				}
    			}
    			trace("-----------ImgToArray MS:" + (getTimer() - ms).toString());
    
    		}

  7. #7
    Senior Member AzraelKans's Avatar
    Join Date
    May 2002
    Location
    Hell... with frequent access to heaven ;)
    Posts
    409
    Nope, wrong again this is even faster, it ticks around 200ms in a crappy machine
    Code:
    		public function imgToArray() {
    			var c:int;
    			var rx:int;
    			var ry:int;
    			var ms:int=getTimer();
    			var ba:ByteArray;
    			var rgb:Array=new Array(4);
    			var counter:int=0;
    			var pcounter=0;
    			var myPixel:uint;
    			var byte:uint;
    			var bcounter:int=0
    			
    			aimage=new Array(imageSize);
    			bitmap.lock();
    			ba=bitmap.getPixels(new Rectangle(0,0,imageWidth,imageHeight));
    			trace("-----------ImgToArray MS:" + (getTimer() - ms).toString());			
    		
    			for (pcounter=0;pcounter<imageSize;pcounter++){
    				    bcounter=pcounter*4
    					myPixel=((ba[bcounter+1]<< 16)+(ba[bcounter+2]<< 8)+(ba[bcounter+3]));
    					aimage[pcounter]=myPixel<sprite.sensibleResult;
    			}
    			trace("-----------ImgToArray MS:" + (getTimer() - ms).toString());
    			trace("pix:"+myPixel.toString(16));
    		}

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center