ReadPixels Problem
Monkey Targets Forums/Android/ReadPixels Problem
| ||
A user of my game BallerBurg has a problem on his device. The castle looks wrong: The device is a Samsung GT-S-5830i with Android 2.3.6. The castle is a png with alpha transparency. To get a INT-array for manipulating it later I paint it on a fresh Cls screen, then immediately capture it back with this function: Method GrabBurg:Void() Cls SetColor 255,255,255 DrawImage BurgImage,0,0 Original= New Int[240*240] ReadPixels(Original,0,0,240, 240,0) ' recover Alpha For Local i%=0 To 240*240-1 If Original[i]=-16777216 Original[i]=0 Endif Next BurgImage = CreateImage(240,240) BurgImage.WritePixels(Original, 0, 0, 240,240) End Could it be that my idea of recovering the alpha, does not work on all devices, because the result of a "black pixel" is not always -16777216? |
| ||
it's entirely possible. Sometimes textures are stored internally in 5-bit compressed format on certain devices to save space, and if I were to take an educated guess, this sorta thing can also affect matting knockout code that doesn't have a threshold greater than the banding amount. Was just looking at this crap today actually, for a module I'll be announcing soon.... Until then, maybe you can try using GetImagePixels to grab texture data directly instead? http://monkeycoder.co.nz/Community/posts.php?topic=6087 |
| ||
is it dithering? i suspect some devices force dithering if it is not specified. Monkey does not specify (targets/android/native/androidgame.java)BitmapFactory.Options opts=new BitmapFactory.Options(); opts.inPreferredConfig=Bitmap.Config.ARGB_8888; opts.inPurgeable=true; we would need to add: opts.inDither=false; |
| ||
Looks like dithering of some kind, you can see the pattern. You could always include the alpha separately as a greyscale image. |
| ||
Or split the Original[i] comparison into R,G and B as I did in this thread: http://www.monkeycoder.co.nz/Community/posts.php?topic=6209 and compare against a more than less than value... But this slows things down... |
| ||
You could find *approximately* black pixels quickly by using blackish:Bool = ( rgbVal & $00FEFEFE ) = 0, and only then do a more exact test. [In point of fact, if dithering is involved that might be about as exact as you can get anyway...] |
| ||
@nobuyuki sorry, my english is not good enough... What do you mean with "...this sorta thing can also affect matting knockout code that doesn't have a threshold greater than the banding amount." *** EDIT **** The "no Dithering" workaround (AdamRedwoods) did not bring any improvement. |
| ||
@Midimaster It means that dithering could cause problems with the code you use to "knock out" the black color. If the threshold (wiggle amount) is lower than the amount of change created by dithering, then artifacts will still show through. By the way... I released the module that I mentioned I would be announcing earlier. It has a few improvements over the other code I linked to. Perhaps it will work for you? (No HTML5 canvas support or Flash, unfortunately!) http://monkeycoder.co.nz/Community/posts.php?topic=7702 |
| ||
@Nobuyki I could add your method of reading the pixel informations direct form the file. Thank you for that, it works. But there is a error message: Method GrabWithoutDither:Int[](FileName$) Local data:Int[], info%[2] #If TARGET="android" Local db:DataBuffer = LoadImageData("monkey://data/" + FileName, info) Print "DATA BUFFER LENGTH= " + db.Length Local timeSpent:Int = Millisecs() 'Copy the data buffer into an array. data = data.Resize(db.Length / 4) '32-bits = 4 bytes 'We need to swap bytes of R and B channels around. For Local i:Int = 0 Until db.Length Step 4 Local j:Int = db.PeekInt(i) data[i / 4] = (j & $ff000000) | ((j & $00ff0000) Shr 16) | (j & $0000ff00) | ((j & $000000ff) Shl 16) Next Print "Operation took " + (Millisecs() -timeSpent) + "ms" #Endif Return data End |
| ||
You're getting nullpo but without the precompiled java code it is impossible to tell where exactly. Have you made sure to 1. wait until the first update loop to attempt to grab pixels? 2. wait until the surface is valid before rendering? (Updates and rendering occur asynchronously; you need a check to make sure the renderloop doesn't attempt to access a null surface) |