[Closed] Fastest way to get transparent image bounding box
Hi guys!
I have many PNG 24bits with transparency that have different graphic in it, circle, box, etc.
I need a method to get the first pixel that is not transparent in all 4 directions.
So that way I know where in the image the element start and end.
The getPixels do not return the transparency information.
Regards,
OZRay
24bits means no transparency (only RGB).
Only 32bit PNGs can have transparency (RGBA).
And if they do, getPixels does return an RGBA color value.
You can access the alpha value using the .a property.
Yes sorry this is a 32bits PNG.
Where do you get the .a property?
When Im doing this:
img = openbitmap @"C:\Temp\Asterix_Test.png"
h = getPixels img [10,10] 1
It gives me black that is the background behind the transparency.
thanks
Sorry got it…
img = openbitmap @"C:\Temp\Asterix_Test.png"
h = getPixels img [10,10] 1
h[1].a
thanks
Humm it’s easy and fast to find the Y from the top and the Y from the bottom because as soon that I get a value other then 0.0 in the alpha of getPixels img [0.0] img.width I stop there.
But it’s a more complicated to find it in X cause I have to scan the complet image to get the first transparent pixel in X and the last one…
yes, you do.
fn getTrimmedCoords thebmp =
(
local tTop = tBottom = tLeft = tRight = -1
local coords = #()
for i = 1 to thebmp.height do append coords (getPixels theBmp [0,i-1] thebmp.width)
for top = 1 to coords.count while tTop==-1 do
for c in coords[top] do if c.a != 0 do tTop=top
if tTop == -1 do tTop = 1
for bottom = coords.count to tTop by -1 while tBottom == -1 do
for c in coords[bottom] do if c.a != 0 do tBottom = bottom
if tBottom == -1 do tBottom = theBmp.height
for left = 1 to coords[1].count while tLeft == -1 do
for c = tTop to tBottom do if coords[c][left].a != 0 do tLeft = left
if tLeft == -1 do tLeft = 1
for right = coords[1].count to tLeft by -1 while tRight == -1 do
for c = tTop to tBottom do if coords[c][right].a != 0 do tRight = right
if tRight == -1 do tRight = theBmp.width
#(tTop, tBottom, tLeft, tRight)
)
the [b]pastebitmap [/b]with function might be faster... not dramatically. my guess is ~15-20% faster.
EDITED:
i was wrong… LO’s method is algorithmically optimized and not going through all pixels. so it’s much faster than pasteBitmap which is processing every pixel… if you want to see the difference:
fn getTrimmedCoords thebmp =
(
local tTop = tBottom = tLeft = tRight = -1
local coords = #()
for i = 1 to thebmp.height do append coords (getPixels theBmp [0,i-1] thebmp.width)
for top = 1 to coords.count while tTop==-1 do
for c in coords[top] do if c.a != 0 do tTop=top
if tTop == -1 do tTop = 1
for bottom = coords.count to tTop by -1 while tBottom == -1 do
for c in coords[bottom] do if c.a != 0 do tBottom = bottom
if tBottom == -1 do tBottom = theBmp.height
for left = 1 to coords[1].count while tLeft == -1 do
for c = tTop to tBottom do if coords[c][left].a != 0 do tLeft = left
if tLeft == -1 do tLeft = 1
for right = coords[1].count to tLeft by -1 while tRight == -1 do
for c = tTop to tBottom do if coords[c][right].a != 0 do tRight = right
if tRight == -1 do tRight = theBmp.width
#([tLeft,tTop], [tRight, tBottom])
)
fn getBitmapAlphaBBox bmp =
(
bbox = #([1e9,1e9],[-1e9,-1e9])
fn getMinMax c p _c _p bbox:bbox =
(
if c.a != 0 do
(
if p.x < bbox[1].x do bbox[1].x = p.x
if p.y < bbox[1].y do bbox[1].y = p.y
if p.x > bbox[2].x do bbox[2].x = p.x
if p.y > bbox[2].y do bbox[2].y = p.y
)
c
)
pasteBitmap bmp bmp [0,0] [0,0] type:#function function:getMinMax
bbox
)
(
bmp = openbitmap <any_texture_file_with_alpha>
t1 = timestamp()
m1 = heapfree
bb = getTrimmedCoords bmp
format "1 >> size:% bbox:% time:% memory:%
" [bmp.width,bmp.height] bb (timestamp() - t1) (m1 - heapfree)
t1 = timestamp()
m1 = heapfree
bb = getBitmapAlphaBBox bmp
format "2 >> size:% bbox:% time:% memory:%
" [bmp.width,bmp.height] bb (timestamp() - t1) (m1 - heapfree)
)
If performance is critical in your scenario, you might want to change all the loops to check every 2nd or 3rd pixel.
There are insanely few cases where the function will give a wrong result due to this, and if you are padding an extra 5-10% for your trimmed bitmap, it will matter even less.