Building TclMagick

2004/12/16 sheila I've been attempting to produce minimal builds of TclMagick with support only for a bmp module. I'm going to collect thoughts here. I'm putting an outline here first. will flesh out more later.


Choose between GraphicsMagick and ImageMagick

In order to build TclMagick, you need to decide which libraries to use with it, ImageMagick or GraphicsMagick. (insert comparison of features and what motivates one to choose one over the other -- GraphicsMagick has smaller footprint vs. ImageMagick has more functions).

Choose Customization or Default

Do you want to take GraphicsMagick or ImageMagick as-is or do you want to customize modules (and insert here about multi vs single threaded and static vs dynamic)? If you don't need to customize, the quickest course of action is to grab a prebuilt distribution and install. (Make sure there isn't a problem with it not updating your path -- happened to me in a Windows environment)

If you do want to customize, download or check-out the source README and INSTALL files:

A Digression on Building in Windows

The VC++ VisualMagick stuff is way cool. Easy to use. (insert description of use). I haven't tried an alternate method. (insert how-to for alternate compilers). Do that, then tinker with the modules listed in the workspace. I deleted optional modules in the All project workspace, then went to sub-workspaces like CORE-magick and made sure to remove the correct dependencies. (Insert note about editing magick config file when using the VisualMagick configure comamnd). I can't remember if I edited static.c and static.h in the CORE-magick project or not (I think I tried both -- double check and revise this later).

At some point I also played around with editing configuration files. I got it to work when building with GraphicsMagick, but haven't successfully done this with ImageMagick. I'm still working on that. For example:

 (Debug) 5 % $w ReadImage diffbars.bmp
 UnableToOpenConfigureFile
 (Debug) 6 % $w ReadImage diffbars.bmp
 NoDecodeDelegateForThisImageFormat

Okay, well. I figured out that I was stuck in registry hell. (You can build with hardcoded paths if you want to, but I didn't).

Perhaps I'm digressing too much on my learning experience. I can come back and delete this later.

 Windows Registry Editor Version 5.00

 [HKEY_LOCAL_MACHINE\SOFTWARE\ImageMagick]

 [HKEY_LOCAL_MACHINE\SOFTWARE\ImageMagick\6.1.6]

 [HKEY_LOCAL_MACHINE\SOFTWARE\ImageMagick\6.1.6\Q:8]
 "BinPath"="C:\\yadda"
 "ConfigurePath"="C:\\yadda"
 "LibPath"="C:\\yadda"
 "CoderModulesPath"="C:\\yadda"
 "FilterModulesPath"="C:\\yadda"

 [HKEY_LOCAL_MACHINE\SOFTWARE\ImageMagick\Current]
 "BinPath"="C:\\yadda"
 "ConfigurePath"="C:\\yadda"
 "LibPath"="C:\\yaddab"
 "CoderModulesPath"="C:\\yadda"
 "FilterModulesPath"="C:\\yadda"

Mac OS X Digression

I used apt-get or fink (can't remember) and installed ImageMagick.

Now on to Building TclMagick

Fairly simple. Get a zip of the source, or check-out from CVS (insert links). The source may have been included when you checked out or downloaded GraphicsMagick/ImageMagick. Configure and build.

Building TclMagick in Windows with VC++

Edit the workspace to use the appropriate directories rather than the ones already there. (No script yet to do it for you. quick project for later). I hate the UI for doing that in VC++, and I usually edit the dsp files by hand. But make backups because once I screwed up something and VC++ didn't want to load them.

Testing

There are a few tests, but it would be nice to have more; so write them and contribute. I am too shy to contribute my tests yet, but I asked on the mailing list for permission. I wrote one for doing diffs of BMPs within epsilon of 0 using a nice fequal procedure I found on the wiki (go find the page and link here)

Building in OS X

(it worked, insert more later.)

2008/08/23 stoic In order to get TclMagick to compile on Mac OS 10.4.11 with GraphicsMagick 1.2.5 I had to:

  • Use the cvs version of TclMagick - version 0.45 would not compile, nor would the version supplied with GraphicsMagick.
  • Upgrade the Gnu building tools: autoconf, automake, m4 to the most recent versions.
  • Disable building the shared library. When I tried to build the shared library I got the error: /usr/bin/ld: Undefined symbols: _Tcl_InitStubs _tclStubsPt. To be fair I don't know why I would want the shared library (I enabled building it in the first place for completeness) but I still couldn't get it to work.

(insert examples and tests)

test compare function for BMPs

(either run in debugger or double click and type runTest

 ###########################################################
 # MagickWand compare test
 # - The purpose is to test the correctness of TclMagick,
 #   not to produce meaningful output
 #
 ###########################################################


 ############################################
 # Load debugging version 
 # or require TclMagick package from library
 #
 if { $tcl_platform(platform) == "unix" } {
    set auto_path [linsert $auto_path 0 [file join .. unix]]
    package require TclMagick
 } else {
    set buildtype debug
    set dll [file join .. win $buildtype TclMagick.dll]
    if {[file exists $dll]} {
        load $dll
    }
    #package require TclMagick <--- quick bad kluge to get on with testing
 }
 puts [info script]

 ##########################################
 # Global options
 #
 set base tclmagick-small.bmp
 set basecopy tclmagick-small-copy.bmp
 set bigdiff tclmagick-big-diff.bmp
 set onepixeldiff tclmagick-small-diff.bmp
 set epsilon 1.0e-6

 proc runTest {} {

    foreach cmd {comparePass compareFail compareOnePixelDiff} {
        if {[$cmd]} {
            set result PASS
        } else {
            set result FAIL
        }
        puts "$result $cmd"
    }
 }

 proc compareImages {img1 img2} {
    puts "Comparing $img1 and $img2"

    set cmpCmd {
        set wand1 [magick create wand]
        set wand2 [magick create wand]

        $wand1 ReadImage $img1
        $wand2 ReadImage $img2

        set result [$wand1 CompareImages $wand2 meansquarederror]

        puts "Images compared at $result using meansquarederror"

        magick delete $wand1
        magick delete $wand2
    }
    
    if {[catch {eval $cmpCmd} err]} {
        # get stack trace
        set localinfo $::errorInfo
        
        # free any left over wands
        foreach item [magick names] {
            magick delete $item
        }

        set m "Failed to compare images. error: $err"
        puts $m

        error $m $localinfo ;# actually, should not throw error and should return 0 so other tests can run
    }
    
    return $result
 }

 proc comparePass {} {
    global base basecopy
    puts "Checking for equal images to pass comparison"

    set result [compareImages $base $basecopy]

    # result should be 0.0 from an equal comparison
    return [string eq $result 0.0]
 }

 proc compareFail {} {
    global base bigdiff
    puts "Checking for vastly different images to fail comparison\
            at epsilon $::epsilon"

    set result [compareImages $base $bigdiff]

    if {[fequal $result 0]} {
        return 0
    } else {
        return 1
    }
 }

  proc compareOnePixelDiff {} {
    global base onepixeldiff
    
    puts "Checking epsilon $::epsilon difference in image comparison with\
            only one pixel difference"

    set result [compareImages $base $onepixeldiff]

    if {[fequal $result 0]} {
        return 1
    } else {
        return 0
    }
 }

 # from Tclers' Wiki
 proc fequal {x y} {
    global epsilon

    if {[expr abs($y) < $epsilon]} {
        return [expr abs($x) < $epsilon]
    }
    return [expr (abs($x - $y) / double($y)) < $epsilon]
 }

 console show

See also TclMagick binaries