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

Samples from Users
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus

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

GDI Image Encoding


GDI Examples: The GDI+ is pretty powerful. You can do any kind of effect and text formatting. One example just draws vertical text with some transparency. Also you can output to several image formats.

GDI+ Functions 1.0

(Save as: GDIPlus.wbt)
;GDI+ Functions 1.0
;WIN 98 or later. See examples.
;Guido 06/04

;Enumerations (names abreviated to fit wb)
;- enum StringFormatFlags
SFF_DirectionRightToLeft        = 1
SFF_DirectionVertical           = 2
SFF_NoFitBlackBox               = 4
SFF_DisplayFormatControl        = 32
SFF_NoFontFallback              = 1024
SFF_MeasureTrailingSpaces       = 2048
SFF_NoWrap                      = 4096
SFF_LineLimit                   = 8192
SFF_NoClip                      = 16384

;- enum StringAlignment
;Left edge for left-to-right text,
;right for right-to-left text,
;and top for vertical
StringAlignmentNear   = 0
StringAlignmentCenter = 1
StringAlignmentFar    = 2

;- enum TextRenderingHint
TRH_SystemDefault = 0             ;Glyph with system default rendering hint
TRH_SingleBitPerPixelGridFit = 1  ;Glyph bitmap with hinting
TRH_SingleBitPerPixel = 2         ;Glyph bitmap without hinting
TRH_AntiAliasGridFit = 3          ;Glyph anti-alias bitmap with hinting
TRH_AntiAlias = 4                 ;Glyph anti-alias bitmap without hinting
TRH_ClearTypeGridFit = 5          ;Glyph CT bitmap with hinting

;gpStartUp() : Initializes GDI+ , must be called only once before using any gdi+ function.
;agp     : one dimensional array of 3 elements, used as a handle to be passed to the other gp functions.
;          On function success it will be filled, otherwise all elements are set to 0.
;Returns : 0 success, a negative value means error:
;						-1 dllload() failed to load gdiplus.dll
;						-2 GdiplusStartup api call failed
#definefunction gpStartUp(agp)
	arrinitialize(agp, 0)

	errormode(@off)
	hgdiplus = dllload("gdiplus.dll")
	errormode(@on)
	
	if hgdiplus==0 then return -1
	
	agp[0] = hgdiplus ;save
	
	btoken = binaryalloc(4)
	bGdiplusStartupInput = binaryalloc(16)
	binarypoke4(bGdiplusStartupInput, 0, 1) ;GdiplusVersion
	r = dllcall(agp[0], long:"GdiplusStartup", lpbinary:btoken, lpbinary:bGdiplusStartupInput, lpnull)
	token = binarypeek4(btoken, 0)
	binaryfree(btoken)
	binaryfree(bGdiplusStartupInput)

	if r<>0 ;error GdiplusStartup
		dllfree(hgdiplus)
		agp[0] = 0
		return -2 ;error
	endif
	
	agp[1] = token ;save
	
	;save EncoderQuality GUID for later use in gpSaveImageToFile()
	bEncoderQuality = MAKE_GUID("1d5be4b5-fa4a-452d-9cdd5db35105e7eb")
	agp[2] = bEncoderQuality
	
	return 0 ;success
#endfunction

;gpShutDown() : Cleans up resources used by GDI+. Each call to GdiplusStartup should be paired
;               with a call to GdiplusShutdown
;agp : array returned by gpStartUp()
;Returns : no return value
#definefunction gpShutDown(agp)
	if agp[0]<>0
		dllcall(agp[0], long:"GdiplusShutdown", long:agp[1])
		dllfree(agp[0])
	endif
	if agp[2]<>0 then binaryfree(agp[2])
#endfunction

#definefunction gpCreateStringFormat(agp, formatAttributes, language)
	bformat = binaryalloc(4)
	
	r = dllcall(agp[0], long:"GdipCreateStringFormat", long:formatAttributes, long:language, lpbinary:bformat)
	format = binarypeek4(bformat, 0)
	binaryfree(bformat)
	
	if r==0 then return format
	else return 0
#endfunction

#definefunction gpDeleteStringFormat(agp, format)	
	return dllcall(agp[0], long:"GdipDeleteStringFormat", long:format)
#endfunction

#definefunction gpLoadImageFromFile(agp, file)
	wfile = MAKE_WCHAR(file)
	bimage = binaryalloc(4)
	
	r = dllcall(agp[0], long:"GdipLoadImageFromFile", lpbinary:wfile , lpbinary:bimage)
	image = binarypeek4(bimage, 0)
	
	binaryfree(wfile)
	binaryfree(bimage)
	
	if r==0 then return image
	else return 0
#endfunction

#definefunction Hex2Dec(hex)
  str = "0123456789ABCDEF"
  hex = strtrim(strupper(hex))
  hexlen = strlen(hex)
  dec = 0
  for x=1 to hexlen
    dec = (dec*16) + strindex(str, strsub(hex, x, 1), 0, @fwdscan) -1
  next
  return dec
#endfunction

#definefunction gpDisposeImage(agp, image)
	return dllcall(agp[0], long:"GdipDisposeImage", long:image)
#endfunction

;gpGetEncoderClsid() : Gets an image encoder CLSID
;agp 		: array returned by gpStartUp()
;format : string representing the encoder, possible values:
;					image/bmp 
;					image/jpeg 
;					image/gif 
;					image/tiff 
;					image/png 
;Returns : if succeeds a buffer handle containing the CLSID, if it fails the function returns 0.
;          You are responsible of free this buffer when you no longer need it.
#definefunction gpGetEncoderClsid(agp, format)
	kernel32 = strcat(dirwindows(1), "kernel32.dll")

	bnum = binaryalloc(4)  ;number of image encoders
	bsize = binaryalloc(4) ;size of the image encoder array in bytes
	
	dllcall(agp[0], long:"GdipGetImageEncodersSize", lpbinary:bnum, lpbinary:bsize)
	num = binarypeek4(bnum, 0) 
	size = binarypeek4(bsize, 0)
	if size==0 ;failure
		binaryfree(bnum)
		binaryfree(bsize)
		return 0
	endif
	
	szImageCodecInfo = 76 ;structure size
	bImageCodecInfo = binaryalloc(size)
	
	wformat = MAKE_WCHAR(format)
	
	dllcall(agp[0], long:"GdipGetImageEncoders", long:num, long:size, lpbinary:bImageCodecInfo)
	binaryeodset(bImageCodecInfo, size)
	
	for j=0 to (szImageCodecInfo*num)-szImageCodecInfo by szImageCodecInfo
		pMimeType = binarypeek4(bImageCodecInfo, j+48) ;MimeType
	
		if dllcall(kernel32, long:"lstrcmpW", lpbinary:wformat, long:pMimeType)==0 ;found
			bCLSID = binaryalloc(16)
			binarycopy(bCLSID, 0, bImageCodecInfo, j, 16)
			
			binaryfree(wformat)
			binaryfree(bImageCodecInfo)
			binaryfree(bnum)
			binaryfree(bsize)
			return bCLSID ;success
		endif
	next
	
	binaryfree(wformat)
	binaryfree(bImageCodecInfo)
	binaryfree(bnum)
	binaryfree(bsize)
	return 0 ;faliure
#endfunction

;gpSaveImageToFile()
;agp           : array returned by gpStartUp()
;image         : image handle returned by gpLoadImageFromFile()
;filename      : file to be created
;bclsidEncoder : image encoder handle, returned by gpGetEncoderClsid()
;quality       : JPEG encoding quality, from 0 to 100. 0 corresponds to the greatest compression,
;                and a quality level of 100 corresponds to the least compression.
;                Passing a negative value will take the default quality.
;Returns : 0 if it succeeds, @true if it fails
#definefunction gpSaveImageToFile(agp, image, filename, bclsidEncoder, quality)
	wfilename = MAKE_WCHAR(filename)
	
	if quality<0 ;default
		r = dllcall(agp[0], long:"GdipSaveImageToFile", long:image, lpbinary:wfilename, lpbinary:bclsidEncoder, long:0)
		binaryfree(wfilename)
		return r
	else ;set quality
		EncoderParameterValueTypeLong = 4
		
		szEncoderParameter = 28
		szEncoderParameters = 4 + szEncoderParameter
		
		bquality = binaryalloc(4)
		binarypoke4(bquality, 0, quality)
		bEncoderQuality = agp[2]
		
		bEncoderParameters = binaryalloc(szEncoderParameters)
		binarypoke4(bEncoderParameters, 0, 1) ;Count
		binarycopy(bEncoderParameters, 4, bEncoderQuality, 0, 16) ;Guid
		binarypoke4(bEncoderParameters, 20, 1) ;NumberOfValues
		binarypoke4(bEncoderParameters, 24, EncoderParameterValueTypeLong) ;Type
		binarypoke4(bEncoderParameters, 28, intcontrol(42, bquality, 0, 0, 0)) ;Value 
		
		r = dllcall(agp[0], long:"GdipSaveImageToFile", long:image, lpbinary:wfilename, lpbinary:bclsidEncoder, lpbinary:bEncoderParameters)
		binaryfree(wfilename)
		binaryfree(bquality)
		binaryfree(bEncoderParameters)
		return r	
	endif
#endfunction

#definefunction gpGetImageGraphicsContext(agp, image)
	bgraphics = binaryalloc(4)
	
	r = dllcall(agp[0], long:"GdipGetImageGraphicsContext", long:image, lpbinary:bgraphics)
	graphics = binarypeek4(bgraphics, 0)
	binaryfree(bgraphics)
	
	if r==0 then return graphics
	else return 0
#endfunction

;color : color value returned by MAKE_ARGB()
#definefunction gpCreateSolidFill(agp, color)
	bbrush = binaryalloc(4)
	
	r = dllcall(agp[0], long:"GdipCreateSolidFill", long:color, lpbinary:bbrush)
	brush = binarypeek4(bbrush, 0)
	binaryfree(bbrush)
	
	if r==0 then return brush
	else return 0
#endfunction

#definefunction gpDrawString(agp, graphics, string, lenght, font, layoutRect, stringFormat, brush)
	wstring = MAKE_WCHAR(string)
	
	r = dllcall(agp[0], long:"GdipDrawString", long:graphics, lpbinary:wstring, long:lenght, long:font, lpbinary:layoutRect, long:stringFormat, long:brush)
	binaryfree(wstring)
	
	return r
#endfunction

#definefunction gpSetTextRenderingHint(agp, graphics, mode)
	return dllcall(agp[0], long:"GdipSetTextRenderingHint", long:graphics, long:mode)
#endfunction

#definefunction gpCreateStringFormat(agp, formatAttributes, language)
	bformat = binaryalloc(4)
	
	r = dllcall(agp[0], long:"GdipCreateStringFormat", long:formatAttributes, long:language, lpbinary:bformat)
	format = binarypeek4(bformat, 0)
	binaryfree(bformat)
	
	if r==0 then return format
	else return 0
#endfunction

#definefunction gpCreateFontFromDC(agp, hdc)
	bfont = binaryalloc(4)
	
	r = dllcall(agp[0], long:"GdipCreateFontFromDC", long:hdc, lpbinary:bfont)
	font = binarypeek4(bfont, 0)
	
	if r==0 then return font
	else return 0
#endfunction

#definefunction gpGetImageWidth(agp, img)
	bwidth = binaryalloc(4)
	
	r = dllcall(agp[0], long:"GdipGetImageWidth", long:img, lpbinary:bwidth)
	width = binarypeek4(bwidth, 0)
	binaryfree(bwidth)
	
	if r==0 then return width
	else return 0
#endfunction

#definefunction gpGetImageHeight(agp, img)
	bheight = binaryalloc(4)
	
	r = dllcall(agp[0], long:"GdipGetImageHeight", long:img, lpbinary:bheight)
	height = binarypeek4(bheight, 0)
	binaryfree(bheight)
	
	if r==0 then return height
	else return 0
#endfunction

#definefunction gpDeleteGraphics(agp, graphics)
	return dllcall(agp[0], long:"GdipDeleteGraphics", long:graphics)
#endfunction

#definefunction gpGetDC(agp, graphics)
	bhdc = binaryalloc(4)
	
	r = dllcall(agp[0], long:"GdipGetDC", long:graphics, lpbinary:bhdc)
	hdc = binarypeek4(bhdc, 0)
	
	if r==0 then return hdc
	else return 0
#endfunction

#definefunction gpReleaseDC(agp, graphics, hdc)	
	return dllcall(agp[0], long:"GdipReleaseDC", long:graphics, long:hdc)
#endfunction

#definefunction gpDeleteFont(agp, font)
	return dllcall(agp[0], long:"GdipDeleteFont", long:font)
#endfunction

#definefunction gpDeleteBrush(agp, brush)
	return dllcall(agp[0], long:"GdipDeleteBrush", long:brush)
#endfunction

#definefunction MAKE_WCHAR(st)
	kernel32 = strcat(dirwindows(1), "kernel32.dll")
	CP_ACP = 0
	
	blen = strlen(st) * 2 + 10
	wbuf = binaryalloc(blen)
	r = dllcall(kernel32, long:"MultiByteToWideChar", long:CP_ACP, long:0, lpstr:st, long:-1, lpbinary:wbuf, long:blen)
	binaryeodset(wbuf, blen)
	Return wbuf	
#endfunction

#definefunction MAKE_GUID(id)
  id = StrClean(id, "{}-", "", 0, 1)
  buf = binaryalloc(16)

  ;LONG
  BinaryPoke4(buf, 0, Hex2Dec(strsub(id, 1, 8)))

  ;WORD
  os = 4
  st = 9
  for x=1 to 2
    BinaryPoke2(buf, os, Hex2Dec(strsub(id, st, 4)))
    os = os + 2
    st = st + 4
  next

  ;BYTE
  os = 8
  st = 17
  for x=1 to 8
    BinaryPoke(buf, os, Hex2Dec(strsub(id, st, 2)))
    os = os + 1
    st = st + 2
  next
  return buf
#endfunction

;Values from 0 to 255
;alpha            : amount of transparency, 0 max, 255 no transparency
;red, green, blue : amount of each color
#definefunction MAKE_ARGB(Alpha, red, green, blue)
	return (blue << 0) |(green << 8) |(red << 16) | (Alpha << 24)
#endfunction

#definefunction MAKE_RECTF(x, y, width, height)
	oleaut32 = strcat(dirwindows(1), "oleaut32.dll")

	brectF = binaryalloc(16)
	arectF = intcontrol(42, brectF, 0, 0, 0)
	
	DllCall(oleaut32, long:"VarR4FromI4", long:x, long:arectF)
	DllCall(oleaut32, long:"VarR4FromI4", long:y, long:arectF+4)
	DllCall(oleaut32, long:"VarR4FromI4", long:width, long:arectF+8)
	DllCall(oleaut32, long:"VarR4FromI4", long:height, long:arectF+12)
	binaryeodset(brectF, 16)

	return brectF
#endfunction


Example #1

;Example, encodes an image file to JPEG
;Guido 06/04

#include "gdiplus.wbt"

;change this with your files
inFile = "C:\myimage.bmp"
outFile = "C:\myimage_new.jpg"

;init GDI+
agp = arrdimension(3)
r = gpStartUp(agp)
if r<>0
	message("Error %r%", "Unable to start GDI+")
	exit
endif

;get encoder
bJPEG = gpGetEncoderClsid(agp, "image/jpeg")
if !bJPEG
	message("Error", "Encoder not found")
	gpShutDown(agp)
	exit
endif

;load image
img = gpLoadImageFromFile(agp, inFile)
if !img
	message("Error", "Unable to load image file")
	gpShutDown(agp)
	exit
endif

;encode
r = gpSaveImageToFile(agp, img, outFile, bJPEG, 50)

if r==0 then message("", "File saved successfully")
else message("Error %r%", "Failed to save file")

;free
gpDisposeImage(agp, img)
binaryfree(bJPEG)
gpShutDown(agp)
exit


Example #2

;Example, draws text on an image file saving it as a new bmp file.
;Guido 06/04

#include "gdiplus.wbt"

#definefunction CreateFont(fheight, fweight, fitalic, funderline, fstrikeout, fface)
	gdi32 = strcat(dirwindows(1), "gdi32.dll")
	return dllcall(gdi32, long:"CreateFontA", long:fheight, long:0, long:0, long:0, long:fweight, long:fitalic, long:funderline, long:fstrikeout, long:0, long:0, long:0, long:0, long:0, lpstr:fface)
#endfunction

;Used to delete the font object
#definefunction DeleteObject(hobj)
	gdi32 = strcat(dirwindows(1), "gdi32.dll")
	return dllcall(gdi32, long:"DeleteObject", long:hobj)
#endfunction

;DrawTextOnFile() : Draws text on an existing image file, creating a new one. Source file  remains untouched.
;                   Supported formats should be bmp,jpeg,gif,tiff,png.
;text             : the text to draw
;font             : text font, returned by CreateFont()
;x,y,width,height : Position and dimension of the rectangle containing the text in pixels.
;                   If you pass widht and height the text will be wrapped inside the rectange,
;                   passing 0 for width and height will just place the text at x,y position.
;stringFormat     : returned by gpCreateStringFormat(), or 0 for no format.
;TextRendering    : a TextRenderingHint enum value or 0 for default
;brush            : text brush, returned by gpCreateSolidFill()
;inFile           : source file
;outFile          : new file to create
;encoder          : type of encoder to use for the new file, returned by gpGetEncoderClsid()
;quality          : JPEG encoding quality 0-100 or -1 for default 
;Returns          : 0 success or a negative value if it fails
#definefunction DrawTextOnFile(agp, text, font, x, y, width, height, stringFormat, TextRendering, brush, inFile, outFile, encoder, quality)
	gdi32 = strcat(dirwindows(1), "gdi32.dll")

	img = gpLoadImageFromFile(agp, infile)
	if !img then return -1 ;error

	graphics = gpGetImageGraphicsContext(agp, img)
	if !graphics
		gpDisposeImage(agp, img)
		return -2 ;error
	endif
	
	if TextRendering then gpSetTextRenderingHint(agp, graphics, TextRendering)
	
	;font
	hdc = gpGetDC(agp, graphics)
	obj_old = dllcall(gdi32, long:"SelectObject", long:hdc, long:font)
	gpfont = gpCreateFontFromDC(agp, hdc)
	gpReleaseDC(agp, graphics, hdc)

	if !gpfont
		gpDisposeImage(agp, img)
		gpDeleteGraphics(agp, graphics)
		return -3 ;error
	endif
	
	;draw
	brectF = MAKE_RECTF(x, y, width, height)
	r = gpDrawString(agp, graphics, text, strlen(text), gpfont, brectF, stringFormat, brush)
	binaryfree(brectF)
	
	if r<>0
		gpDeleteFont(agp, gpfont)
		gpDisposeImage(agp, img)
		gpDeleteGraphics(agp, graphics)
		return -4 ;error
	endif
	
	;save file
	if fileexist(outFile) then filedelete(outFile)
	r = gpSaveImageToFile(agp, img, outFile, encoder, quality)
	
	gpDeleteFont(agp, gpfont)
	gpDisposeImage(agp, img)
	gpDeleteGraphics(agp, graphics)

	if r<>0 then return -4 ;error
	
	return 0 ;success
#endfunction


; -------------------------------------------------------
; CODE START
; -------
;change this with your files
inFile = "C:\myimage.bmp"
outFile = "C:\myimage_new.bmp"

;init GDI+
agp = arrdimension(3)
r = gpStartUp(agp)
if r<>0
	message("Error %r%", "Unable to start GDI+")
	exit
endif

;encoder
bBMP = gpGetEncoderClsid(agp, "image/bmp")
if !bBMP
	message("Error", "Encoder not found")
	gpShutDown(agp)
	exit
endif

;brush
brush = gpCreateSolidFill(agp, MAKE_ARGB(150, 255, 0, 0)) ;red with some transparency
if !brush
	message("Error", "Failed to create brush")
	gpShutDown(agp)
	exit
endif

;font
fheight=28
fweight=700
fitalic=0
funderline=0
fstrikeout=0
fface="Tahoma"
hfont = CreateFont(fheight, fweight, fitalic, funderline, fstrikeout, fface)

;text format
LANG_NEUTRAL  = 0 ;api language ID
stringFormat  = gpCreateStringFormat(agp, SFF_DirectionVertical, LANG_NEUTRAL)
TextRendering = TRH_SystemDefault

r = DrawTextOnFile(agp, "hello world", hfont, 10, 10, 0, 0, stringFormat, TextRendering, brush, inFile, outFile, bBMP, -1)

if r==0 then message("", "File saved successfully")
else message("Error %r%", "Failed")

;free
gpDeleteStringFormat(agp, stringFormat)
DeleteObject(hfont)
gpDeleteBrush(agp, brush)
gpShutDown(agp)
binaryfree(bBMP)
exit

Article ID:   W16693
File Created: 2005:02:18:12:21:52
Last Updated: 2005:02:18:12:21:52