Imaging Functions
Moderator: Klaus
-
- Posts: 48
- Joined: Tue Aug 30, 2011 2:24 pm
Imaging Functions
Does LiveCode have a way to get and set pixel values? About 10 years ago I wrote a drawing program in Director called PixelToolbox (still available free and downloaded thousands of times a month just from my site) that I would like to translate to LiveCode & develop further. It seems to me that LiveCode has some basic imaging functionality but not enough for something like PixelToolbox.
Re: Imaging Functions
Hi
Look at the 'imageData' property in the dictionary...
Dixie
Look at the 'imageData' property in the dictionary...
Dixie
Re: Imaging Functions
Hi Luisa,
have a look at what Wilhlem Sanke does with Livecode/Revolution
http://www.sanke.org/ImageDataArt/index.htm
especially the imageToolKit
and
http://www.sanke.org/PatternArt/index.htm
patternToolKit
or on RevOnline (which is also accessible from within Livecode (user samples)
http://revonline2.runrev.com/stack/470/ ... ker-Plugin
there is a lot you can do with imageData and alphaData in Livecode. As long as the images are small you get reasonable response times.
kind regards
Bernd
have a look at what Wilhlem Sanke does with Livecode/Revolution
http://www.sanke.org/ImageDataArt/index.htm
especially the imageToolKit
and
http://www.sanke.org/PatternArt/index.htm
patternToolKit
or on RevOnline (which is also accessible from within Livecode (user samples)
http://revonline2.runrev.com/stack/470/ ... ker-Plugin
there is a lot you can do with imageData and alphaData in Livecode. As long as the images are small you get reasonable response times.
kind regards
Bernd
Re: Imaging Functions
Hi Luisa,
RunRev is in fact currently rewriting the complete media/graphics engine, but we do not have a date for this now.
Best
Klaus
I'm afraid this is the case!Luisa Klose wrote:... It seems to me that LiveCode has some basic imaging functionality but not enough for something like PixelToolbox.
RunRev is in fact currently rewriting the complete media/graphics engine, but we do not have a date for this now.
Best
Klaus
-
- Posts: 48
- Joined: Tue Aug 30, 2011 2:24 pm
Re: Imaging Functions
Klaus, you will spoil the heck out of me if you make the new set of functions more thorough, easier to use, and faster than Director's functions. If you're not familiar with them, here are most of them:
By the way, I had to use an "Xtra" to save to several of the formats, and I was never able to find a way to load .ico and .cur files for editing. Could write them but couldn't read them.
If you need anyone to help you evaluate & test...
Thanks, Dixie and Bernd for your responses. Impressed by Wilhelm Sanke's work...
Code: Select all
copyPixels() - imageObject.copyPixels(sourceImageObject, destinationRect, sourceRect {, parameterList})
fill() - imageObject.fill(left, top, right, bottom, colorObjectOrParameterList)
crop() - imageObject.crop(rectToCropTo)
draw() - imageObject.draw(x1, y1, x2, y2, colorObjectOrParameterList)
image() - image(width, height, bitDepth {, alphaDepth} {, paletteSymbolOrMember})
duplicate() - imageObject.duplicate()
getPixel() - imageObject.getPixel(point(x, y) {, #integer})
setPixel() - imageObject.setPixel(x, y, integerValue)
color() - color(#rgb, redValue, greenValue, blueValue)
And several functions for dealing with alpha channels.
If you need anyone to help you evaluate & test...
Thanks, Dixie and Bernd for your responses. Impressed by Wilhelm Sanke's work...
Re: Imaging Functions
Most of those are built into the engine already.
copyPixels() - imageObject.copyPixels(sourceImageObject, destinationRect, sourceRect {, parameterList})
Not sure quite what this does, but it is trivial to copy an image. You can either script the copy and paste commands, or easier, use the "clone" command.
fill() - imageObject.fill(left, top, right, bottom, colorObjectOrParameterList)
Script the paint tools. Set the fillColor, choose the bucket tool, and "click at <coord>".
crop() - imageObject.crop(rectToCropTo)
Built into the language, see "crop" in the dictionary.
draw() - imageObject.draw(x1, y1, x2, y2, colorObjectOrParameterList)
Create a new graphic object. Set its points to a list of coordinates.
image() - image(width, height, bitDepth {, alphaDepth} {, paletteSymbolOrMember})
"create image", then set its width, height, and alphamask
duplicate() - imageObject.duplicate()
"clone image 1"
getPixel() - imageObject.getPixel(point(x, y) {, #integer})
You have to cheat for this, it's ugly, but: set the loc of the cursor and then get the mousecolor
setPixel() - imageObject.setPixel(x, y, integerValue)
You can do this with imagedata, but not so easy.
color() - color(#rgb, redValue, greenValue, blueValue)
I'm not sure what this does, but there are a variety of color properties you can set for objects.
And several functions for dealing with alpha channels
You can set an alpha mask on any image by setting its alphaData property.
copyPixels() - imageObject.copyPixels(sourceImageObject, destinationRect, sourceRect {, parameterList})
Not sure quite what this does, but it is trivial to copy an image. You can either script the copy and paste commands, or easier, use the "clone" command.
fill() - imageObject.fill(left, top, right, bottom, colorObjectOrParameterList)
Script the paint tools. Set the fillColor, choose the bucket tool, and "click at <coord>".
crop() - imageObject.crop(rectToCropTo)
Built into the language, see "crop" in the dictionary.
draw() - imageObject.draw(x1, y1, x2, y2, colorObjectOrParameterList)
Create a new graphic object. Set its points to a list of coordinates.
image() - image(width, height, bitDepth {, alphaDepth} {, paletteSymbolOrMember})
"create image", then set its width, height, and alphamask
duplicate() - imageObject.duplicate()
"clone image 1"
getPixel() - imageObject.getPixel(point(x, y) {, #integer})
You have to cheat for this, it's ugly, but: set the loc of the cursor and then get the mousecolor
setPixel() - imageObject.setPixel(x, y, integerValue)
You can do this with imagedata, but not so easy.
color() - color(#rgb, redValue, greenValue, blueValue)
I'm not sure what this does, but there are a variety of color properties you can set for objects.
And several functions for dealing with alpha channels
You can set an alpha mask on any image by setting its alphaData property.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com
HyperActive Software | http://www.hyperactivesw.com
-
- Posts: 48
- Joined: Tue Aug 30, 2011 2:24 pm
Re: Imaging Functions
Jacqueline, PixelToolbox's warp function works with copyPixels, as do many of the other functions. It's for copying a part of an image, (or the whole thing), into part of another image, with several parameters including transparency, ink, blend, etc. It's also a quick way to do gaussian blur, unsharp mask and other filters. Here is the Lingo code for the warp function:
Can you show me an application created with LiveCode that allows the user to pick an rgb color and paint in elegant (and responsive) airbrushed strokes (not the splatters of LiveCode's airbrush) ?
I'll be straightforward with you. If Adobe Director offered me a way to publish apps to the new mobile devices, I wouldn't be here. I like LiveCode a lot, and I can see that it's very powerful. But I can also see that it would be less than satisfying or succesful to tanslate PixeToolbox into LiveCode in its present state.
If RunRev wants to attract more developers, improving the graphics engine is a step in the right direction. I wouldn't make the same mistake that Adobe is making with Director though. It's focus on 3d game development is misguided, and its execution foolish.
Code: Select all
on toolWarp
-- set state 1 for undo/redo
member("state1 - " & gSize, gCast).image = member(gSize & "x" & gSize, gCast).image
-- draw & update preview
startPoint = point((((the mouseH - sprite(1).left ) * 2) / gVariable) / 2, (((the mouseV - sprite(1).top) * 2) / gVariable) / 2)
myCurrentImage = duplicate(member(gSize & "x" & gSize, gCast).image)
myStartImage = duplicate(myCurrentImage)
myCurrentPreview = duplicate(member("preview", gCast).image)
tLImage = image(startPoint.locH, startPoint.locV, member(gSize & "x" & gSize, gCast).depth, member(gSize & "x" & gSize, gCast).paletteRef)
tLImage.copyPixels(myCurrentImage, tLImage.rect, rect(0, 0, startPoint.locH, startPoint.locV))
tRImage = image(myCurrentImage.width - startPoint.locH, startPoint.locV, member(gSize & "x" & gSize, gCast).depth, member(gSize & "x" & gSize, gCast).paletteRef)
tRImage.copyPixels(myCurrentImage, tRImage.rect, rect(startPoint.locH, 0, myCurrentImage.width, startPoint.locV))
bLImage = image(startPoint.locH, myCurrentImage.height - startPoint.locV, member(gSize & "x" & gSize, gCast).depth, member(gSize & "x" & gSize, gCast).paletteRef)
bLImage.copyPixels(myCurrentImage, bLImage.rect, rect(0, startPoint.locV, startPoint.locH, myCurrentImage.height))
bRImage = image(myCurrentImage.width - startPoint.locH, myCurrentImage.height - startPoint.locV, member(gSize & "x" & gSize, gCast).depth, member(gSize & "x" & gSize, gCast).paletteRef)
bRImage.copyPixels(myCurrentImage, bRImage.rect, rect(startPoint.locH, startPoint.locV, myCurrentImage.width, myCurrentImage.height))
repeat while the mouseDown
myCurrentImage.copyPixels(myStartImage, myStartImage.rect, myStartImage.rect)
myCurrentImage.copyPixels(tLImage, [point(0, 0), point(startPoint.locH, 0), point((((the mouseH - sprite(1).left ) * 2) / gVariable) / 2, (((the mouseV - sprite(1).top) * 2) / gVariable) / 2), point(0, startPoint.locV)], tLImage.rect)
myCurrentImage.copyPixels(tRImage, [point(startPoint.locH, 0), point(myCurrentImage.width, 0), point(myCurrentImage.width, startPoint.locV), point((((the mouseH - sprite(1).left ) * 2) / gVariable) / 2, (((the mouseV - sprite(1).top) * 2) / gVariable) / 2)], tRImage.rect)
myCurrentImage.copyPixels(bLImage, [point(0, startPoint.locV), point((((the mouseH - sprite(1).left ) * 2) / gVariable) / 2, (((the mouseV - sprite(1).top) * 2) / gVariable) / 2), point(startPoint.locH, myCurrentImage.height), point(0, myCurrentImage.height)], bLImage.rect)
myCurrentImage.copyPixels(bRImage, [point((((the mouseH - sprite(1).left ) * 2) / gVariable) / 2, (((the mouseV - sprite(1).top) * 2) / gVariable) / 2), point(myCurrentImage.width, startPoint.locV), point(myCurrentImage.width, myCurrentImage.height), point(startPoint.locH, myCurrentImage.height)], bRImage.rect)
member(gSize & "x" & gSize, gCast).image.copyPixels(myCurrentImage, myCurrentImage.rect, myCurrentImage.rect)
updateStage
put (((the mouseH - sprite(1).left ) * 2) / gVariable) / 2 into field "location status X"
put (((the mouseV - sprite(1).top) * 2) / gVariable) / 2 into field "location status Y"
fnUpdatePreview
end repeat
end
I'll be straightforward with you. If Adobe Director offered me a way to publish apps to the new mobile devices, I wouldn't be here. I like LiveCode a lot, and I can see that it's very powerful. But I can also see that it would be less than satisfying or succesful to tanslate PixeToolbox into LiveCode in its present state.
If RunRev wants to attract more developers, improving the graphics engine is a step in the right direction. I wouldn't make the same mistake that Adobe is making with Director though. It's focus on 3d game development is misguided, and its execution foolish.
Re: Imaging Functions
Hi Luisa,
Colin Holgate and I wrote a proof of principle stack that lets you 'stamp' an image into an image, it was part of his presentation on Livecode, a streaming video presentation
the two parts of the presentation:
http://blog.livecode.tv/2011/04/172/
the sample stack "SimplePaint":
http://blog.livecode.tv/wp-content/uplo ... ePaint.zip
Colin wanted to use this as an iPad app.
Again this is probably not as elaborate an example as you would expect and frankly Livecode has a lot to be desired regarding image manipulation.
The SimplePaint stack just puts the imageData of an image into the imageData of the target image. If you drag the 'stamp' you paint the image repeatedly into the target image. No provisions for blending, transparency. Though one could script that it is a lot of scripting, could be done though. But the limiting step is: Livecode is slow in updating an image if it also has to update the alphaData, for live painting with transparencies I don't think Livecode is really up to that.
Actually it all depends on what size of image your want to work on, and what exactly it is you are doing. I can not test your PixelToolbox since I am on a Mac.
(once you load the image Colin provides in the folder the Reload Image button becomes active and you can erase what you painted, restoring the original image, if you press the shift-key then you erase also with the current paint image. You could load your own png images to paint with)
Kind regards
Bernd
Colin Holgate and I wrote a proof of principle stack that lets you 'stamp' an image into an image, it was part of his presentation on Livecode, a streaming video presentation
the two parts of the presentation:
http://blog.livecode.tv/2011/04/172/
the sample stack "SimplePaint":
http://blog.livecode.tv/wp-content/uplo ... ePaint.zip
Colin wanted to use this as an iPad app.
Again this is probably not as elaborate an example as you would expect and frankly Livecode has a lot to be desired regarding image manipulation.
The SimplePaint stack just puts the imageData of an image into the imageData of the target image. If you drag the 'stamp' you paint the image repeatedly into the target image. No provisions for blending, transparency. Though one could script that it is a lot of scripting, could be done though. But the limiting step is: Livecode is slow in updating an image if it also has to update the alphaData, for live painting with transparencies I don't think Livecode is really up to that.
Actually it all depends on what size of image your want to work on, and what exactly it is you are doing. I can not test your PixelToolbox since I am on a Mac.
(once you load the image Colin provides in the folder the Reload Image button becomes active and you can erase what you painted, restoring the original image, if you press the shift-key then you erase also with the current paint image. You could load your own png images to paint with)
Kind regards
Bernd
-
- Posts: 48
- Joined: Tue Aug 30, 2011 2:24 pm
Re: Imaging Functions
Hi, Bernd, very interesting. That is similar to how the soft brushes work in PixelToolbox, with a mask with an alpha channel.
After some tweaking, I was able to get a Shockwave version of PixelToolbox to work. Things that don't work:
Import
Revert
Save As
Save
Copy
Paste
Apply Wallpaper
Export Image
Open Windows Control Panels
Fonts
The Pattern Screen function doesn't work, but if you click on it's little icon, you can choose "Fast Weave" which does.
Since I wrote the program I developed a better airbrush (with some help) that hasn't been integrated.
The URL is: www axiomx com/temp/PixelToolbox htm
Edit to add link for PixelToolbox's pdf manual:
www axiomx com/PixelToolbox/PixelToolbox_guide pdf
After some tweaking, I was able to get a Shockwave version of PixelToolbox to work. Things that don't work:
Import
Revert
Save As
Save
Copy
Paste
Apply Wallpaper
Export Image
Open Windows Control Panels
Fonts
The Pattern Screen function doesn't work, but if you click on it's little icon, you can choose "Fast Weave" which does.
Since I wrote the program I developed a better airbrush (with some help) that hasn't been integrated.
The URL is: www axiomx com/temp/PixelToolbox htm
Edit to add link for PixelToolbox's pdf manual:
www axiomx com/PixelToolbox/PixelToolbox_guide pdf
Re: Imaging Functions
Hi Luisa,
that looks very good.
I am not shure you could replicate everything in Livecode, but I would try it with just small pieces of the PixelToolbox and see how it goes. Since you work on small images it could work. Not shure about the speed of the alpha channel.
Kind regards
Bernd
that looks very good.
I am not shure you could replicate everything in Livecode, but I would try it with just small pieces of the PixelToolbox and see how it goes. Since you work on small images it could work. Not shure about the speed of the alpha channel.
Kind regards
Bernd
-
- Posts: 48
- Joined: Tue Aug 30, 2011 2:24 pm
Re: Imaging Functions
Thanks, Bernd, I will take your advice. Perhaps I'll do the "fast weave" as a stack to share with the community.
And thanks for inspiring me to do a Shockwave version of PixelToolbox
I like your idea of using an image to paint with in the place of a color. PixelToolbox doesn't have that, and I hope you don't mind if I add it as a new brush. I especially like the idea of painting with a sphere.
And thanks for inspiring me to do a Shockwave version of PixelToolbox

I like your idea of using an image to paint with in the place of a color. PixelToolbox doesn't have that, and I hope you don't mind if I add it as a new brush. I especially like the idea of painting with a sphere.
Re: Imaging Functions
HI Luisa,
I thought you might like this:
I made a stack that makes a color gradient by code. You can also click on a colorwheel and move the mouse to do the gradient dynamically. It is a bit of code to show how imageData in Livecode can be used to "paint".
Kind regards
Bernd
Edit: I deleted the attachement, it is replaced by a stack below.
I thought you might like this:
I made a stack that makes a color gradient by code. You can also click on a colorwheel and move the mouse to do the gradient dynamically. It is a bit of code to show how imageData in Livecode can be used to "paint".
Kind regards
Bernd
Edit: I deleted the attachement, it is replaced by a stack below.
Last edited by bn on Fri Sep 02, 2011 9:25 pm, edited 1 time in total.
-
- VIP Livecode Opensource Backer
- Posts: 10043
- Joined: Sat Apr 08, 2006 7:05 am
- Contact:
Re: Imaging Functions
Nicely done, Bernd. Very smooth performance.bn wrote:I made a stack that makes a color gradient by code. You can also click on a colorwheel and move the mouse to do the gradient dynamically. It is a bit of code to show how imageData in Livecode can be used to "paint".
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
Re: Imaging Functions
@ Richard, thank you.
@ Luisa and all:
unfortunately there were bugs in the color libraries that convert RGB values to HSV values and the inverse. They concerned greyscale and white. I corrected the libraries. Now it seems to work nicely, even with greyscale / white /black values.
I upload the corected version, some more comments added to the code too.
Kind regards
Bernd
I will delete the previous version "makeGradient_3"
@ Luisa and all:
unfortunately there were bugs in the color libraries that convert RGB values to HSV values and the inverse. They concerned greyscale and white. I corrected the libraries. Now it seems to work nicely, even with greyscale / white /black values.
I upload the corected version, some more comments added to the code too.
Kind regards
Bernd
I will delete the previous version "makeGradient_3"
-
- Posts: 48
- Joined: Tue Aug 30, 2011 2:24 pm
Re: Imaging Functions
Wow, friends, the more I see, the more impressed I am with LiveCode, and with the community.
Bernd, I'm going to download the new version of your gradient demonstration and check it out in a little while.
I was able to do a little something to share. My introduction to imaging in LiveCode. After I post it here, I'm going to find out what "Share This Stack..." entails.
Warm regards,
Luisa
Bernd, I'm going to download the new version of your gradient demonstration and check it out in a little while.
I was able to do a little something to share. My introduction to imaging in LiveCode. After I post it here, I'm going to find out what "Share This Stack..." entails.
Warm regards,
Luisa
- Attachments
-
- PixelToolbox_PatternWeaver.zip
- (5.15 KiB) Downloaded 400 times