Sign in to follow this  
Followers 0
Werty

Imagemagick pic in memory (Blob) ?

9 posts in this topic

Does anyone know how I can get imagemagick to create a Blob (pic in memory) from a _ScreenCapture_CaptureWnd() ?

I have read ALL 218 threads about imagemagick, and only two of them have relations to putting a pic into an array, but one doesnt work (also says so in the thread), and the other thread has been edited (by smashly) and content and examples removed. :P

I have also read around the web, seen an ASP example that uses imagemagick BLOB like this....

Set img = CreateObject("ImageMagickObject.MagickImage.1")
Dim myArray(0)
myArray(0)="JPG:"
Response.contentType="image/JPEG"
l=img.convert ("logo:","-resize","250X250","-quality","1",myArray)
response.binaryWrite myArray

...and another similar example I cant find right now.

The only official example that comes with imagemagick in the "imagemagickobjectdll" folder is this...

Option Explicit

'On Error Resume Next
Const ERROR_SUCCESS = 0

Dim img
Dim myarray(1)
Dim output(1)
Dim persist(2)
Dim info
Dim msgs
Dim elem
Dim sMsgs

'While 1
'
' This is a complex example of how to work with images as blobs
' as well as how to do lossless embedding of textual information
' into an existing JPEG image.
'
Set img = CreateObject("ImageMagickObject.MagickImage.1")
'
' Writing an image out to a VBSCRIPT array as a blob requires a
' way to tell IM what image format to use. The way this is done
' is to stuff the magick type into the array that will be used
' to store the results.
'
myarray(0)="8BIM:"
'
' This command says to take a null input image and load some 8BIM
' format text data into it as a profile. Then just send the null
' image to the output as 8BIM binary format. Pretty funky stuff I
' admit.
'
msgs = img.Convert("null:","-profile","8BIMTEXT:iptctext.txt",myarray)
'If Err.Number <> ERROR_SUCCESS Then ShowError: WScript.Quit
MsgBox "array: " & (ubound(myarray) - lbound(myarray) + 1)
'
' Now that we have the binary 8BIM data in our array as a blob we
' can stuff it into a JPEG. You could just do that with the normal
' convert -profile commmand, but if the input image is a JPEG, it
' would decompress the JPEG and recompress is, which is a quality
' hit. To avoid that we use a special feature and load both our
' text info as well as out input JPEG into another NULL image as
' profiles. The special APP1JPEG profile tells IM to embed the text
' into the JPEG losslessly. We then store the result into another
' output array marked as APP1. This essentially just send the data
' stored in the APP1 profile out untouched. The net result is a
' completely unharmed JPEG with new text data embedded in it.
'
output(0)="APP1:"
msgs = img.Convert("null:","-profile",myarray,"-profile","APP1JPEG:bill_meets_gorilla_screen.jpg",output)
'If Err.Number <> ERROR_SUCCESS Then ShowError: WScript.Quit
MsgBox "output: " & (ubound(output) - lbound(output) + 1)
'
' Last we want to save our output array into a disk file, which we
' could do with standard VBS file techniques, but we can also do it
' with convert directly - again using the APP1 profile type to both
' read the data and also to write it out to disk. This step is here
' to show how to force convert to use a specific image type for a
' blob. Normally convert would automatically detect the type and it
' would notice that this is a JPEG and decompress it. We don't want
' that in this case.
'
persist(0)="APP1:"
persist(1)=output
msgs = img.Convert("null:","-profile",persist,"APP1:bill_meets_gorilla_screen_iptc.jpg")
'
' The following statements are the sequence you would need to free
' the memory being used by this sequence. It is not really needed
' by this example, but if you are writing some kind of loop were a
' number of images are being processed, it becomes very important to
' free memory, or you will leak and eventually crash - or worse just
' degrade the resources of the rest of the system.
Set img=Nothing
Erase persist
myArray = Empty
Redim myarray(1)
output = Empty
Redim output(1)
'Wend
WScript.Quit(0)

Sub ShowError
  sMsgs = ""
  If BasicError(Err.Number) > 5000 Then
    msgs = img.Messages
    If isArray(msgs) Then
      For Each elem In msgs
        sMsgs = sMsgs & elem & vbCrLf
      Next
    End If
  End If
  WScript.Echo Err.Number & ": " & Err.Description & vbCrLf & sMsgs
End Sub

Function BasicError(e)
  BasicError = e And &HFFFF&
End Function

...which is the only thing the imagemagick.org admin have to say about the subject, when people ask for examples using blob, "Go look in the "TestArray.vbs" file he says...

Yeah right, a whole 3 complicated things in 1, very easy to understand for a n00b that just wants an example on how to hold one pic in memory, do something to it, and then save it to disk. :

I have imagemagick working fine and it's awesome, but I'm doing alot of pics, so my script writes and reads from disk hundreds of times with large files, I would really like to use memory instead of disk.

The following works (just using disk ofcourse :blink: )...

(Not complete code as you can see, for easy reading)

$img = ObjCreate("ImagemagickObject.MagickImage.1)
_ScreenCapture_CaptureWnd(@ScriptDir & "capture1.png", $gui, $x, $y, $width, $height)
$convert = $img.Convert("capture1.png","capture1.bmp")
$convert2 = $img.Convert("capture1.bmp","capture1.gif")

...which I would like to use memory blob instead of all the file writes/reads.

I tried....

Local $capture[1]
$img = ObjCreate("ImagemagickObject.MagickImage.1)
$capture = _ScreenCapture_CaptureWnd("", $gui, $x, $y, $width, $height)
$capture[0]="PNG:"
$convert = $img.Convert($capture,"capture1.bmp")
$convert2 = $img.Convert("capture1.bmp","capture1.gif")

...which obviously doesnt work as it only gets a handle.

...so I tried...

Local $capture[1]
$img = ObjCreate("ImagemagickObject.MagickImage.1)
$capture = _ScreenCapture_CaptureWnd("", $gui, $x, $y, $width, $height)
$blob = _GDIPlus_CreateBitmapFromHBITMAP($capture)  ;i know gdi startup is missing, no need to include here
$capture[0]=$blob
$convert = $img.Convert($capture,"capture1.bmp")
$convert2 = $img.Convert("capture1.bmp","capture1.gif")

..which doesnt work either for some reason.

Can someone please help with this problem ? mostly getting imagemagick to work with blob, but optimally also putting the screencap in a blob that IM understands :nuke:

(yes, I'm tired ;) )

Share this post


Link to post
Share on other sites



Well, atleast now I got some error codes out of it, like...

"Catastropic Failure"

"Variable type something.."

"Conversion of parameters failed".

I'll post some examples tommorrow that triggers those errors, right now I need sleep.

Hopefully you guys have figured it out before I get out of bed :blink:

Share this post


Link to post
Share on other sites

Hi,

Sorry I've never used or worked with imagemagic, so none of my scrapped topics would have helped for what your after.

For screen capture, simple picture conversions from one format to another, adding text to pictures and resizing pictures I've used GDI/GDI+ with AutoIt.

If your just after to do a screen capture and add some text and resize it and output the edited capture to file using GDI+ then I could probably help.

If your after more advanced options of editing pictures then then I'm not much help to you with imagemagic.

Cheers

Share this post


Link to post
Share on other sites

Thanks smashly :blink:

Though, I really need imagemagick, the above useless example was just for easy understanding.

I'm working with grayscale height maps and need to do it in 16bit PGM format, which GDI doesnt support (afaik).

Winapi bitblt also looks interesting as it can stack(merge) pictures, what I currently use IM for, but still, in

the end I need IM anyway, and havent found a way around it.

I'll post the promised examples later, just got out of bed, anxiously checking this thread, before shower and coffee ;)

Share this post


Link to post
Share on other sites

Did you find any solution to your problem?

Thanks

Share this post


Link to post
Share on other sites

I kinda found a workaround, but still not optimal.

IM can send a picture to the clipboard like so...

Img.Convert("image.jpg","clipboard:")

...then you can work with it from there.

So far I have only managed to get info about the image into a variable like so...

$details=Img.Convert("image.jpg","info:")

..but still missing getting a picture into a variable, but the clipboard comes in handy.

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Study this function that I use in my IMageMagick library:

Func IM_Extension($this, Const $image)
    Switch FileExists($image)
        Case 1
            Return $this.IMObj.Identify("-format", "%[extension]", "-:", $image)
        Case 0
            Return SetError(-1)
    EndSwitch
EndFunc   ;==>IM_Extension

The part that might be what you need is "-:".

Or this one might be better...

Func IM_ClipBoard($this)
    $this.IMObj.Convert("logo:", "clipboard:")

    Local Const $gui = GUICreate("blobtest", 640, 480)
    GUISetState()

    Local $image, $hbitmap, $hgraphic

    For $loop = 1 To 10
        _ClipBoard_Open(WinGetHandle(AutoItWinGetTitle()))
        $image = _ClipBoard_GetDataEx($CF_BITMAP)
        _ClipBoard_Close()

        _GDIPlus_Startup()
        $hbitmap = _GDIPlus_BitmapCreateFromHBITMAP($image)
        $hgraphic = _GDIPlus_GraphicsCreateFromHWND($gui)
        _GDIPlus_GraphicsDrawImage($hgraphic, $hbitmap, 0, 0)
        _GDIPlus_Shutdown()

        $this.IMObj.Convert("clipboard:", "-implode", $loop, "clipboard:")

        Sleep(100)
    Next
EndFunc   ;==>IM_ClipBoard
Edited by LaCastiglione

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Study this function that I use in my IMageMagick library:

Func IM_Extension($this, Const $image)
    Switch FileExists($image)
        Case 1
            Return $this.IMObj.Identify("-format", "%[extension]", "-:", $image)
        Case 0
            Return SetError(-1)
    EndSwitch
EndFunc   ;==>IM_Extension

The part that might be what you need is "-:".

Or this one might be better...

Func IM_ClipBoard($this)
    $this.IMObj.Convert("logo:", "clipboard:")

    Local Const $gui = GUICreate("blobtest", 640, 480)
    GUISetState()

    Local $image, $hbitmap, $hgraphic

    For $loop = 1 To 10
        _ClipBoard_Open(WinGetHandle(AutoItWinGetTitle()))
        $image = _ClipBoard_GetDataEx($CF_BITMAP)
        _ClipBoard_Close()

        _GDIPlus_Startup()
        $hbitmap = _GDIPlus_BitmapCreateFromHBITMAP($image)
        $hgraphic = _GDIPlus_GraphicsCreateFromHWND($gui)
        _GDIPlus_GraphicsDrawImage($hgraphic, $hbitmap, 0, 0)
        _GDIPlus_Shutdown()

        $this.IMObj.Convert("clipboard:", "-implode", $loop, "clipboard:")

        Sleep(100)
    Next
EndFunc   ;==>IM_ClipBoard

Yes, that's what I posted in your thread

But we never got it to work with an autoit variable, unless you have figured out how. (notice the date of this thread aug.2010)

But maybe you were talking to adolfito :)

Edited by Werty

Share this post


Link to post
Share on other sites

Yes, that's what I posted in your thread

But we never got it to work with an autoit variable, unless you have figured out how. (notice the date of this thread aug.2010)

Oh, right, I forgot about that! I knew I was forgetting something. I haven't worked on that library in a minute though.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0