-
Senior Member
[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();
}
}
-
Senior Member
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 = 0; k < bitWidth; k++) { for (var l:int = 0; l < bitHeight; l++){ pixelValue = mapTexture.bitmap.getPixel(k, l); pixel = pixelValue.toString(16); setMap(k, l, pixel); } } }
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.
-
Senior Member
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.
-
Senior Member
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?
-
Senior Member
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.
-
Senior Member
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());
}
-
Senior Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|