[Closed] Read alpha channel from bitmap
Does maxscript allow to check the color of the pixel (black or white) of a bitmap’s alpha?
I couldn’t find informations about it on the help. You can actually verify if the bitmap has an alpha or not (with “hasalpha” property) but that’s not what I want.
What I want to do is this.
Locate the bitmap
Reach its alpha channel
See if it’s all white or not (maybe with getpixels?)
You can check each pixel for its .r or .g or .b color value.
You can check pixel’s .a for its alfa color value.
Read Color Values topic in maxscript help file.
Thanks Miauu. That did the trick. But…it’s the slowest script in history. I don’t know why but getpixels is so slow. So at the end it does the job but is unusable (even in a 1024×1024 bitmap).
Here’s the script (if it finds a black pixel in the alpha channel, it outputs a string):
obj = $
map1 = obj.material.diffuseMap.bitmap /*get the bitmap selection*/
widthm = map1.width
heightm = map1.height
pixel_alfa = #()
for l = 1 to heightm do /*declare to cycle through all bitmap height*/
(
p = getpixels map1 [0,l] widthm /*get the pixels of the row */
for i=1 to p.count do
(
append pixel_alfa p[i] /* append each pixel to pixel_data array */
if p[i].a != 255 255 255 do ( /* if the pixel is black warn me*/
format "Got a black pixel"
)
)
)
You have to check each pixel in the map for its color, so – bigger image = more time.
If you want to know if there are at least one black pixel in the alpha channel you can stop the loop when the first black pixel is found.
Why you store pixels in the pixel_alfa(pixel_data) array?
While detecting a black pixel and stopping can be an option, it would be useless when the black pixel appears at the bottom of the image (I had to force out of Max because it was taking too long, after 5 minutes of waiting).
I’ve noticed that getpixels overwrites the array on every line(in my case, 1024 rgb values for each row) , so I needed another array to store incrementally every line.
So: first line: 1024 values
second line: 2048 values
third line: 3072 values
and so forth.
What is the time without storing the pixels color to an array – only Alfa color comparison?
Timestamp gives me a little less than one second per row(without storing my personal array). Means more or less ten minutes for a 512px texture.
Wait a moment, I was printing each iteration for debugging purposes. The process without print is ten time faster. May still be a little slow but it’s way better. I’ll try. Thanks for now Miauu.
Unfortunately, it was not that easy. Now I’ve fixed errors(alpha doesn’t have rgb), got rid of array and print messages.
Anyway if the height of the image is more than 400 (width set to 1024) Max hangs.
If the height is minor than 200px is pretty usable.
If it’s not possible to do better, at this point I’m accepting a compromise.
The following function takes around ~600ms on my end to parse a full 1024×1024 image (all alpha set to white). If the image has any value different than white in the alpha channel then the function will take less, depending on the pixel location.
(
fn GetBitmapHasAlphaBlackPixel img =
(
width = img.width
height = img.height
for y = 0 to height-1 do
(
row = getPixels img [0,y] width
for x = 1 to width where row[x].alpha != 255 do
(
format "Pixel:% Alpha:%
" [x-1,y] row[x].alpha
return true
)
/* -- This loop is a bit faster if you don't need to know the pixel location
for x in row where x.alpha != 255 do
(
format "Black Pixel in Alpha Channel found.
"
return true
)
*/
)
return false
)
gc()
img = openBitMap @"C: est.tif"
st = timestamp()
GetBitmapHasAlphaBlackPixel img
format "time:%
" (timestamp()-st)
close img
)
In .Net it would be much faster than that.
Here is a much faster and memory friendly function.
The function returns “true” if the passed bitmap has any pixel with a value different than 255 in the alpha channel.
I haven’t fully tested it, but it seems to work.
fn GetBitmapHasAlphaBlackPixel img =
(
if img.hasalpha do
(
img2 = bitmap img.width img.height
pastebitmap img img2 [0,0] [0,0] type:#blend
pastebitmap img img2 [0,0] [0,0] type:#blend
return not (comparebitmaps img img2 0 0)
)
return false
)
Test for 1024×1024 bitmap:
time:94ms ram:808L