Get the top of a paint image

Anything beyond the basics in using the LiveCode language. Share your handlers, functions and magic here.

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

Post Reply
jmburnod
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2729
Joined: Sat Dec 22, 2007 5:35 pm
Contact:

Get the top of a paint image

Post by jmburnod » Sun May 17, 2009 6:30 pm

Hi All,

I want know the top of a paint image (the first pixel with a color <> "255,255,255")

I try a method by the mousecolor function like that :

Code: Select all

on tTopOfpaint n -- (n= short name of an image)
 put the ticks into old
   put the rect of image n into Lar
   put item 1 of LaR into LaG
   put item 3 of LaR into LaD
   put item 2 of LaR into LeT
   put item 4 of Lar into LeB
   put 0 into bufTop
   repeat until bufTop <> 0
      repeat with i = LaG to LaD
        put i & "," &LeT into LeP
         set the screenMouseLoc to globalLoc(LeP)
         put the mousecolor into LaMC
         wait 1 milliseconds -- to watch the progress
         if LaMC <> "255,255,255" then
            put LeP&LaMC &return into bufTop
            choose browse tool
            dansmes LeT&&   the ticks - old 
            exit tTopOfpaint
         end if
      end repeat
      add 1 to LeT
   end repeat
end tTopOfpaint

on DansMes t
   put t
end DansMes
I think someone know a better way.

Thanks for your comments

Jean-Marc

Janschenkel
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 977
Joined: Sat Apr 08, 2006 7:47 am
Contact:

Post by Janschenkel » Mon May 18, 2009 6:27 am

This approach would only work if nothing was overlapping the image - including other application windows. You're better off looking at the imageData property of the image control.

Code: Select all

function TopOfPaint pImage
  put the imageData of image pImage into tImageData
  put the width of image pImage into tWidth
  put the height of image pImage into tHeight
  put empty into tTopBuffer
  put 1 into tByteIndex
  put binaryEncode("CCCC",0,255,255,255) into tComparePixelData
  repeat with tRow = 1 to tHeight
    repeat with tColumn = 1 to tWidth
      put byte tByteIndex to tByteIndex + 3 of tImageData into tPixelData
      if tPixelData is not tComparePixelData then
        local tAlpha, tGreen, tRed, tBlue
        get binaryDecode("CCCC",tPixelData,tAlpha,tRed,tGreen,tBlue)
        put tRow, tColumn, tRed, tGreen, tBlue into tTopBuffer
        return tTopBuffer
      end if
    end repeat
  end repeat
  return empty
end TopOfPaint
Not tested but it should be pretty close.

HTH,

Jan Schenkel.
Quartam Reports & PDF Library for LiveCode
www.quartam.com

jmburnod
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2729
Joined: Sat Dec 22, 2007 5:35 pm
Contact:

Get the top of a paint image

Post by jmburnod » Mon May 18, 2009 8:48 am

Thanks Jan,

Yes, the approach by mousecolor dont work if an other object is over the image.

I'm not again friendly with imagedata, by i think it is a better way and your comment help me to know it

I tested your TopOfpaint one time :

The result is empty for my image
(a simple line black made with the brush)

Jean-Marc

Janschenkel
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 977
Joined: Sat Apr 08, 2006 7:47 am
Contact:

Post by Janschenkel » Tue May 19, 2009 5:22 am

I think I found the culprit: I forgot to increment the tByteOffset variable.

Code: Select all

function TopOfPaint pImage 
  put the imageData of image pImage into tImageData 
  put the width of image pImage into tWidth 
  put the height of image pImage into tHeight 
  put empty into tTopBuffer 
  put 1 into tByteIndex 
  put binaryEncode("CCCC",0,255,255,255) into tComparePixelData 
  repeat with tRow = 1 to tHeight 
    repeat with tColumn = 1 to tWidth 
      put byte tByteIndex to tByteIndex + 3 of tImageData into tPixelData 
      if tPixelData is not tComparePixelData then 
        local tAlpha, tGreen, tRed, tBlue 
        get binaryDecode("CCCC",tPixelData,tAlpha,tRed,tGreen,tBlue) 
        put tRow, tColumn, tRed, tGreen, tBlue into tTopBuffer 
        return tTopBuffer 
     end if
     add 4 to tByteOffset
    end repeat 
  end repeat 
  return empty 
end TopOfPaint
That ought to do the trick.

Jan Schenkel.
Quartam Reports & PDF Library for LiveCode
www.quartam.com

jmburnod
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2729
Joined: Sat Dec 22, 2007 5:35 pm
Contact:

Get the top of a paint image

Post by jmburnod » Tue May 19, 2009 9:23 am

Hi Jan,
If you increment tByteindex and not tByteOffset :)
TopOfPaint return the color of the first pixel <> 255,255,255 but not the location of the pixel (tRow and tColumn still = 1)

Code: Select all

function TopOfPaint pImage
  put the imageData of image pImage into tImageData
  put the width of image pImage into tWidth
  put the height of image pImage into tHeight
  put empty into tTopBuffer
  put 1 into tByteIndex
  put binaryEncode("CCCC",0,255,255,255) into tComparePixelData
  repeat with tRow = 1 to tHeight
    repeat with tColumn = 1 to tWidth
      put byte tByteIndex to tByteIndex + 3 of tImageData into tPixelData
      if tPixelData is not tComparePixelData then
        local tAlpha, tGreen, tRed, tBlue
        get binaryDecode("CCCC",tPixelData,tAlpha,tRed,tGreen,tBlue)
        put tRow, tColumn, tRed, tGreen, tBlue into tTopBuffer
        return tTopBuffer
     end if
     add 4 to tByteIndex
    end repeat
  end repeat
  return empty
end TopOfPaint
All the best

Jean-Marc

Janschenkel
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 977
Joined: Sat Apr 08, 2006 7:47 am
Contact:

Post by Janschenkel » Tue May 19, 2009 8:40 pm

Aargh, silly computer - do as I think, not as I say ;-)
You're right, I meant to increment tByteIndex; however, in my tests, it does return the row and column correctly. You can always set a breakpoint and debug to see what's in there when it has found a different color.

Jan Schenkel.
Quartam Reports & PDF Library for LiveCode
www.quartam.com

jmburnod
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2729
Joined: Sat Dec 22, 2007 5:35 pm
Contact:

Get the top of a paint image

Post by jmburnod » Tue May 19, 2009 10:30 pm

YES jan,

I have an explanation for the result 1,1 for "tRow, tColumn,".

I confused white pixel and transparent pixel :shock:

TopOfPaint work well but if i want the first pixel <> transparent i need the number of transparent color.

I search in the doc but if found nothing (at the moment...)

many thanks for your help

Jean-Marc

Janschenkel
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 977
Joined: Sat Apr 08, 2006 7:47 am
Contact:

Post by Janschenkel » Wed May 20, 2009 5:42 am

In that case, you need to work with the alphaData property as well.
Whereas the imageData is comprised of 4 bytres per pixel, the alphaData is just one byte per pixel, so you can create a similar loop.

Jan Schenkel.
Quartam Reports & PDF Library for LiveCode
www.quartam.com

jmburnod
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 2729
Joined: Sat Dec 22, 2007 5:35 pm
Contact:

Get the top of a paint image

Post by jmburnod » Wed May 20, 2009 10:12 am

Yes one more Jan, :D

It work fine and very fast

Code: Select all

-- the location  of the first (top) pixel no transparent of an image. 0,0 = the topleft of the image
function TopOfPaintAlpha pImage 
   put the alphadata of image pImage into tAlphaData
   put the width of image pImage into tWidth
   put the height of image pImage into tHeight
   put empty into tTopBuffer
   put 1 into tByteIndex
   repeat with tRow = 1 to tHeight
      repeat with tColumn = 1 to tWidth
         put charToNum(char tByteIndex of  tAlphaData) into tPixelData
         if tPixelData is not 0 then
           put tRow, tColumn into tTopBuffer
            return tTopBuffer
         end if
         add 1 to tByteIndex
      end repeat
   end repeat
   return empty
end TopOfPaintAlpha
Jean-Marc

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4174
Joined: Sun Jan 07, 2007 9:12 pm

Post by bn » Wed May 20, 2009 11:37 am

Jean-Marc,

if you are working with images the alphadata can go from 0 to 255 to give shades of transparencies. If you want an index of complete transparency versus complete opacity the maskData gives you either 0 or 255, without the intermediate values of the alphaData. At times that can be useful. Otherwise the maskData is similar to the alphaData, one byte for each pixel.

regards
Bernd

Post Reply