Trim transparent borders of a picture

Hi,

I want to crop a picture and remove its transparent borders. Does somebody have a good idea how to do this?
I found that ImageMagick has an option to trim images, but maybe there is a way to do this in Xojo too?
http://www.imagemagick.org/Usage/crop/#trim_color

Best regards

Fabian

First define what a transparent pixel is by making a method that returns true or false. Actually, later on it’s more convenient to define what opaque is. You might want to consider certain colors or a range or something to be ‘transparent’, here it’s just anything close to Alpha 255.

Function isOpaque(c As Color) As boolean return c.Alpha < 250 End Function

Then the trimming method just has to scan the picture and find where the first opaque pixels are from the top, bottom, left and right.

[code]Function trimPic(pic As Picture) As Picture
//init
dim surf As RGBSurface = pic.RGBSurface

dim cTop, cBottom, cLeft, cRight As integer = -1

dim x, y, xlast, ylast As integer
xlast = pic.Width - 1
ylast = pic.Height - 1

//find top
for y = 0 to ylast
for x = 0 to xlast
if isOpaque(surf.Pixel(x, y)) then
cTop = y
exit for y
end
next
next

if cTop = -1 then return nil //pic is all transparent

//find bottom
for y = ylast downto 0
for x = 0 to xlast
if isOpaque(surf.Pixel(x, y)) then
cBottom = y
exit for y
end
next
next

//find left
for x = 0 to xlast
for y = 0 to ylast
if isOpaque(surf.Pixel(x, y)) then
cLeft = x
exit for x
end
next
next

//find right
for x = xlast downto 0
for y = 0 to ylast
if isOpaque(surf.Pixel(x, y)) then
cRight = x
exit for x
end
next
next

//create cropped picture
dim result As new Picture(cRight - cLeft, cBottom - cTop)
result.Graphics.DrawPicture(srcPic, -cLeft, -cTop)

return result
End Function[/code]

This trimming algorithm isn’t very smart because the same pixel may be tested multiple times. Also there may be off-by-one errors in calculating the result width/height and/or the drawpicture offset. You’ll have to check those if you don’t find another algorithm :slight_smile:

To test this add properties srcPic and destPic as Picture to a Window and a button with this code

[code]Sub Action()
srcPic = new Picture(300, 300)
srcPic.Graphics.ForeColor = &c00FF00
srcPic.Graphics.FillOval(47, 47, 92, 92)
srcPic.Graphics.FillOval(240, 200, 23, 23)

destPic = trimPic(srcPic)

Canvas1.Invalidate
End Sub[/code]

and a large Canvas with this Paint

[code]Sub Paint(g As Graphics, areas() As REALbasic.Rect)
if srcPic <> nil and destPic <> nil then
g.ForeColor = &c000000

g.DrawPicture srcPic, 1, 1
g.DrawRect(0, 0, srcPic.Width+2, srcPic.Height+2)

g.DrawPicture destPic, 1, srcPic.Height+9
g.DrawRect(0, srcPic.Height+8, destPic.Width+2, destPic.Height+2)

end
End Sub[/code]

Hi Will,

thank you thousand times for your help. Works great.

Have a nice weekend