WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

ImageMagick

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

ImageMagick Wrapper Function

 Keywords:  ImageMagickObject.MagickImage.1 Image Graphic Pixie ImageMagick Wrapper Function ProcessImage UDF Rotate Resize Crop Sharpen Grayscale Contrast Fill Color Tint Transparent Fuzz Percent Mask Quality 

Note: This example was written for ImageMagick version 6.x and may not be compatible with version 7.x.
;// **************************************************************************************************************************************************************
;// **************************************************************************************************************************************************************
;// **************************************************************************************************************************************************************
;//
;//                                   IMAGEMAGICK WRAPPER FUNCTION
;//             THIS FUNCTION REQUIRES THAT IMAGEMAGICK BE REGISTERED AS A COM OBJECT
;//   YOU CAN DOWNLOAD IMAGEMAGICK FROM: http://www.imagemagick.org/script/binary-releases.php#windows
;//
;//   I ONLY IMPLEMENTED THE PARTS OF IMAGEMAGICK THAT I HAVE A USE FOR, BUT IT WOULD BE EASY TO
;//   EXTEND THIS TO INCLUDE MORE FUNCTIONALITY.
;//
;//   ARGUMENTS:
;//   PROXYPATH - PATH TO LOW RESOLUTION PROXY IMAGES (ONLY USED WHEN CROPPING)
;//   SOURCEPATH - PATH TO THE SOURCE FILES
;//   DESTINATIONPATH - OUTPUT PATH FOR PROCESSED FILES
;//   IMAGE LIST IS A @TAB DELIMITED LIST OF IMAGE FILES FOUND IN THE SOURCEPATH
;//   OPTIONSARRAY IS AN ARRAY OF VALUES WHICH ARE CONVERTED INTO IMAGEMAGICK COMMAND LINE OPTIONS
;//
;//   IMAGE PROCESSING IS HANDLED ACCORDING TO WHAT OPTIONS ARE POPULATED IN THE OPTIONS ARRAY
;//
;//   OPTIONSARRAY IS FORMATTED AS FOLLOWS
;//   PI_ROTATE = 0
;//   PI_RESIZE = 1
;//   PI_CROP = 2
;//   PI_SHARPENING = 3
;//   PI_GRAYSCALE = 4
;//   PI_CONTRAST = 5
;//   PI_FILLCOLOR = 6
;//   PI_TINT = 7
;//   PI_TRANSPARENT = 8
;//   PI_FUZZPERCENT = 9
;//   PI_MASK = 10
;//   PI_OUTPUTTYPE = 11
;//   PI_OUTPUTQUALITY = 12
;//   PI_OUTPUTNAME = 13
;//
;//   PI_ROTATE CAN HAVE A VALUE IN DEGREES OR STRING "AUTO-ORIENT" WHICH WILL ROTATE THE IMAGE
;//   BASED ON EXIF DATA IN THE FILE.
;//
;//   PI_RESIZE CAN CONTAIN AN OUTPUT RESOLUTION (1500x1500, ETC.)
;//
;//   PI_CROP CONTAINS A PIPE DELIMITED STRING OF CROPPING COORDINATES AND VALUES:
;//   x1|y1|x2|y2|cropWidth|cropHeight|outputFileName|cropOrientation
;//
;//   THE ONLY PORTIONS USED ARE THE X1, Y1, CROPWIDTH AND CROPHEIGHT. [THE OTHERS VALUES ARE LEGACY DATA
;//   FROM A PREVIOUS IMPLEMENTATION.]
;//
;//   x1 = CROP POSITION IN PIXELS FROM LEFT EDGE OF PROXY
;//   y1 = CROP POSITION IN PIXELS FROM TOP EDGE OF PROXY
;//   CROPWIDTH = PIXEL WIDTH OF CROP REGION AT TIME CROP WAS MADE
;//   CROPHEIGHT = PIXEL HEIGHT OF CROP REGION AT TIME CROP WAS MADE
;//
;//   WHEN CROPPING A HIGHER RESOLUTION IMAGE, THESE VALUES ARE CONVERTED TO NEW PIXEL LOCATIONS
;//
;//   PI_SHARPENING CAN HAS THREE KEYWORDS: 'low', 'medium', 'high' - THESE WILL TRANSLATE INTO
;//   SHARPENING PRE-SETS (WHICH ARE PRETTY ARBITRARY). YOU CAN (AND PROBABLY SHOULD) PASS YOUR OWN SHARPENING INSTRUCTIONS WHICH WILL BE INSERTED WITHOUT MODIFICATION.
;//
;//   PI_GRAYSCALE - PASS 1 TO CONVERT THE IMAGE TO GRAYSCALE
;//
;//   PI_CONTRAST IS AN INTEGER. PASS THE NUMBER OF CONTRAST "BOOSTS" YOU WANT IMAGEMAGICK TO APPLY.
;//
;//   PI_FILLCOLOR IS AN RGB TRIPLET - THIS COLOR IS REQUIRED ONLY WHEN USING THE TINT OPTION
;//
;//   PI_TINT IS A PERCENTAGE (PASS IT AS AN INTEGER). THE FILL COLOR WILL BE APPLIED AS A TINT TO THE IMAGE AT THIS PERCENTAGE.
;//
;//   PI_TRANSPARENT IS AN RGB TRIPLET - THIS COLOR WILL BE MADE TRANSPARENT IN THE OUTPUT IMAGE
;//   (YOU WILL NEED TO OUTPUT AS A FILETYPE THAT SUPPORTS TRANSPARENCY)
;//
;//   PI_FUZZPERCENT IS A PERCENTAGE (PASS IT AS AN INTEGER). THIS VALUE IS USED TO FIND "LIKE" COLORS WHEN USING PI_TRANSPARENT
;//   AND MAKE THOSE COLORS TRANSPARENT AS WELL.
;//
;//   PI_MASK IS A PATH TO AN IMAGE WHOSE CONTENTS WILL BE USED TO APPLY TRANSPARENCY TO THE OUTPUT IMAGE. THE MASK IMAGE SHOULD
;//   CONTAIN ONLY GRAYSCALE IMAGE DATA. BLACK PIXELS IN THE MASK WILL MAP THAT PIXEL IN THE SOURCE IMAGE AS TRANSPARENT, WHILE WILL REMAIN 100% OPAQUE.
;//
;//   PI_OUTPUTTYPE IS THE FILE EXTENSION (JPG, PNG, ETC.) OF THE OUTPUT FILE - DON'T INCLUDE THE '.'
;//
;//   PI_QUALITY - WHEN SAVING JPG, THE JPG QUALITY SETTING - 90 OFFERS A GOOD COMPRESSION/QUALITY RATIO
;//
;//   PI_OUTPUTNAME - THE NAME OF THE FILE TO OUTPUT. IF BLANK, OUTPUTFILENAME = INPUTFILENAME
;//
;//   PI_CUSTOM - A SLOT FOR INSERTING CUSTOM IMAGEMAGICK PROCESSING. YOU WILL NEED TO PREFORMAT IT WITH EACH OPTION AND VALUE SURROUNDED BY " "
;//               AND SEPARATED BY , EXAMPLE: "-gaussian-blur", "3"
;//
;//               IF NOT PROPERLY FORMATTED, THE IMAGEMAGICK CALL WILL LIKELY FAIL WITH NO ERROR.
;//               NOTE: IMAGEMAGICK PROCESSING IS PERFORMED IN THE ORDER OF THE OPTIONS ON THE COMMAND LINE. THIS CUSTOM PROCESSING SLOT IS PERFORMED
;//               AFTER ALL OTHER PROCESSING. CUSTOM PROCESSING WILL BE PERFORMED AFTER ROTATE, RESIZE, CROPPING, ETC.
;//
;// **************************************************************************************************************************************************************
;// **************************************************************************************************************************************************************
;// **************************************************************************************************************************************************************

#DefineFunction processImage(proxyPath, sourcePath, destinationPath, imageList, optionsArray)

   DirChange(sourcePath)
   imageMagickObj = ObjectCreate("ImageMagickObject.MagickImage.1")

   imCLI = ''

   ;// OPTIONSARRAY POSITIONS
   PI_ROTATE = 0
   PI_RESIZE = 1
   PI_CROP = 2
   PI_SHARPENING = 3
   PI_GRAYSCALE = 4
   PI_CONTRAST = 5
   PI_FILLCOLOR = 6
   PI_TINT = 7
   PI_TRANSPARENT = 8
   PI_FUZZPERCENT = 9
   PI_MASK = 10
   PI_OUTPUTTYPE = 11
   PI_OUTPUTQUALITY = 12
   PI_OUTPUTNAME = 13
   PI_CUSTOM = 14

   ;// IF NO VALUES FOR OUTPUTTYPE AND OUTPUTQUALITY, SET DEFAULT OUTPUTTYPE TO JPG AND DEFAULT OUTPUTQUALITY TO 90
   If optionsArray[PI_OUTPUTTYPE] == '' Then optionsArray[PI_OUTPUTTYPE] = 'jpg'
   If StrLower(optionsArray[PI_OUTPUTTYPE]) == 'jpg' && optionsArray[PI_OUTPUTQUALITY] == '' Then optionsArray[PI_OUTPUTQUALITY] = 90

   ;// IMAGEMAGICK COMMANDLINE FORMATTING
   Select @TRUE

      Case optionsArray[PI_ROTATE] != ''

         optionsArray[PI_ROTATE] = StrLower(optionsArray[PI_ROTATE])
         If optionsArray[PI_ROTATE] == 'auto-orient'
            imCLI = imCLI:', "-auto-orient"'
         Else
            imCLI = imCLI:', "-rotate" "':optionsArray[PI_ROTATE]:'"'
         EndIf

      Continue

      Case optionsArray[PI_OUTPUTQUALITY] != ''

         imCLI = imCLI:', "-quality", "':optionsArray[PI_OUTPUTQUALITY]:'"'

      Continue

      Case optionsArray[PI_CROP] != ''

         imCLI = imCLI:'{{cropoptions}}'

      Continue

      Case optionsArray[PI_RESIZE] != ''

         imCLI = imCLI:', "-resize", "':optionsArray[PI_RESIZE]:'"'

      Continue

      Case optionsArray[PI_SHARPENING] != ''

         optionsArray[PI_SHARPENING] = StrLower(optionsArray[PI_SHARPENING])

         If optionsArray[PI_SHARPENING] == 'low'
            imCLI = imCLI:', "-unsharp", ".3x1.0+1+0"'
         ElseIf optionsArray[PI_SHARPENING] == 'medium'
            imCLI = imCLI:', "-unsharp", "2x2.0+1+0"'
         ElseIf optionsArray[PI_SHARPENING] == 'high'
            imCLI = imCLI:', "-unsharp", "3x3.0+1+0"'
         Else
            imCLI = imCLI:', "-unsharp", "':optionsArray[PI_SHARPENING]:'"'
         EndIf

      Continue

      Case optionsArray[PI_GRAYSCALE] == 1

         imCLI = imCLI:', "-colorspace", "Gray"'

      Continue

      Case optionsArray[PI_CONTRAST] != ''

          For c = 1 To optionsArray[PI_CONTRAST]
             imCLI = imCLI:', "-contrast"'
          Next

      Continue

      Case optionsArray[PI_FILLCOLOR] != ''

          imCLI = imCLI:', "-fill", "rgb(':optionsArray[PI_FILLCOLOR]:')"'

      Continue

      Case optionsArray[PI_TINT] != ''

          imCLI = imCLI:', "-tint", ':optionsArray[PI_TINT]

      Continue

      Case optionsArray[PI_FUZZPERCENT] != ''

         imCLI = imCLI:', "-fuzz", "':optionsArray[PI_FUZZPERCENT]:'%%"'

      Continue

      Case optionsArray[PI_TRANSPARENT] != ''

         imCLI = imCLI:', "-transparent", "rgb(':optionsArray[PI_TRANSPARENT]:')"'

      Continue

      Case optionsArray[PI_MASK] != ''

         imCLI = imCLI:', "':optionsARRAY[PI_MASK]:'", "-alpha", "Off", "-compose", "Copy_Opacity", "-composite"'

      Continue

      Case optionsArray[PI_CUSTOM] != ''

         imCLI = imCLI:', ':optionsArray[PI_CUSTOM]

      Break

   EndSelect


   ;// PROCESS LIST OF IMAGES
   iCount = ItemCount(imageList, @TAB)
   For i = 1 To iCount

      image = ItemExtract(i, imageList, @TAB)
      fileName = FileRoot(image)
      imCommandLine = imCLI

      ;// IF WE ARE CROPPING THE IMAGE, WORK OUT THE CROPPING COORDINATES
      If optionsArray[PI_CROP] != ''

         ;x1|y1|x2|y2|width|height|outputFileName|cropOrientation
         cropOptions = optionsArray[PI_CROP]

         xPos = ItemExtract(1, cropOptions, '|')
         yPos = ItemExtract(2, cropOptions, '|')
         proxyCropWidth = ItemExtract(5, cropOptions, '|')
         proxyCropHeight = ItemExtract(6, cropOptions, '|')

         ;// IF WE ARE NOT CROPPING THE SAME IMAGE AS WAS CROPPED IN THE INTERFACE
         ;// DO THE EXTRA PROCESSING NEEDED TO READ OUT IMAGE DIMENSIONS AND CONVERT CROPPING COORDINATES FOR USE ON LARGER IMAGE.
         If proxyPath != sourcePath

            ;// READ SIZE INFO FOR PROXY IMAGE
            proxyFile = proxyPath:'\':image
            proxyCommandLine = '"-format", "%%wx%%h", "':proxyFile:'"'
            proxySize = imageMagickObj.Identify("NULL", %proxyCommandLine%)
            proxyWidth = ItemExtract(1, proxySize, 'x')+0.0
            proxyHeight = ItemExtract(2, proxySize, 'x')+0.0

            ;// CONVERT PROXY CROP COORDINATES INTO PERCENTAGES
            xPercent = xPos/proxyWidth
            yPercent = yPos/proxyHeight
            widthPercent = proxyCropWidth/proxyWidth
            heightPercent = proxyCropHeight/proxyHeight

            ;// READ SIZE INFO FOR SOURCE IMAGE
            imageFile = sourcePath:'\':image
            sourceCommandLine = '"-format", "%%wx%%h", "':imageFile:'"'
            sourceSize = imageMagickObj.Identify("NULL", %sourceCommandLine%)
            sourceWidth = ItemExtract(1, sourceSize, 'x')+0.0
            sourceHeight = ItemExtract(2, sourceSize, 'x')+0.0

            ;// IF THE SOURCE FILE IS NOT THE SAME ORIENTATION AS THE PROXY FILE, SWAP THE SOURCE DIMENSIONS
            ;// THE SOURCE FILE WILL BE ROTATED PRIOR TO CROPPING
            cropRotate = ''
            If proxyHeight > proxyWidth && sourceHeight < sourceWidth

               sourceWidth = ItemExtract(2, sourceSize, 'x')+0.0
               sourceHeight = ItemExtract(1, sourceSize, 'x')+0.0
               cropRotate = '"-auto-orient", '

            EndIf

            ;// CONVERT PROXY CROP PERCENTAGES INTO PIXEL VALUES FOR CROPPING HIGHER RESOLUTION FILE
            cropX = Int(sourceWidth*xPercent)
            cropY = Int(sourceHeight*yPercent)

            cropWidth = Int(sourceWidth*widthPercent)
            cropHeight = Int(sourceHeight*heightPercent)

         Else

            ;// WE ARE CROPPING THE PROXY IMAGE - WE CAN USE CROP POSITIONS AND SIZES AS-IS
            imageFile = sourcePath:'\':image
            cropWidth = proxyCropWidth
            cropHeight = proxyCropHeight
            cropX = xPos
            cropY = yPos
            cropRotate = ''

         EndIf

         ;// IMAGE MAGICK CROPPING
         imCommandLine = StrReplace(imCommandLine, '{{cropoptions}}', ', ':cropRotate:'"-gravity", "NorthWest", "-crop", "':cropWidth:'x':cropHeight:'+':cropX:'+':cropY:'"')

      Else

         ;// WE ARE NOT CROPPING THE IMAGE, REMOVE THE CROPOPTIONS TAG FROM THE COMMANDLINE
         imCommandLine = StrReplace(imCommandLine, '{{cropoptions}}', '')

      EndIf

      ;// APPEND THE SOURCE IMAGE TO THE COMMAND LINE
      imCommandLine = '"':sourcePath:'\':image:'"':' ':imCommandLine

      ;// APPEND THE DESTINATION IMAGE TO THE COMMAND LINE
      If optionsArray[PI_OUTPUTNAME] == ''
         imCommandLine = imCommandLine:', "':destinationPath:'\':FileRoot(image):'.':optionsArray[PI_OUTPUTTYPE]:'"'
      Else
         ;// IF WE ARE PROCESSING A LIST OF IMAGES AND HAVE SUPPLIED AN OUTPUT NAME, ADD A COUNTER VALUE TO THAT OUTPUT NAME TO KEEP FILES NAMES UNIQUE
         If iCount > 1
            imCommandLine = imCommandLine:', "':destinationPath:'\':optionsArray[PI_OUTPUTNAME]:'_':i:'.':optionsArray[PI_OUTPUTTYPE]:'"'
         Else
            imCommandLine = imCommandLine:', "':destinationPath:'\':optionsArray[PI_OUTPUTNAME]:'.':optionsArray[PI_OUTPUTTYPE]:'"'
         EndIf
      EndIf

      ;// PROCESS IMAGE
      imageMagickObj.Convert("NULL", %imCommandLine%)

   Next

   ObjectClose(imageMagickObj)
   Return 1

#EndFunction

#DefineSubRoutine processImageArray()

   ;// CONSTANTS FOR PROCESSIMAGE OPTIONS ARRAY
   PI_ROTATE = 0
   PI_RESIZE = 1
   PI_CROP = 2
   PI_SHARPENING = 3
   PI_GRAYSCALE = 4
   PI_CONTRAST = 5
   PI_FILLCOLOR = 6
   PI_TINT = 7
   PI_TRANSPARENT = 8
   PI_FUZZPERCENT = 9
   PI_MASK = 10
   PI_OUTPUTTYPE = 11
   PI_OUTPUTQUALITY = 12
   PI_OUTPUTNAME = 13
   PI_CUSTOM = 14

   pi_optionsArray = ArrDimension(18)
   ArrInitialize(pi_optionsArray, '')
   Return pi_optionsArray

#EndSubRoutine

Article ID:   W18077
Filename:   ImageMagick Wrapper Function.txt
File Created: 2019:12:02:11:30:52
Last Updated: 2019:12:02:11:30:52