2007-03-20

Convert Images to Monochrome with GdiPlus X

from times to times someone asks about creating monochrome images, that, in most of the cases will be used to be sent by fax.


unfortunately, gdi+ does not offer full support to 1bpp indexed images (monochrome bitmaps).


but with the help of anatoliy mogylevets and mike gagnon, i could find that the good and old gdi (not gdiplus) provides some functions (copyimage and loadimage) to do that in a flash. so, we've agreed to add this important feature to the library, as a new method added to the image and bitmap classes: getmonochrome().


steps to get the monochrome 1bpp version of any image using the gdi+x classes


  1. load image to gdiplus
  2. call the image.getmonochrome to obtain a new object that will contain the 1bpp image
  3. save normally as bmp

 


important:


all samples below use the new gdiplus-x library, that is still in alpha version, but is already stable and reliable to do the majority of gdi+ tasks. download the latest stable release from codeplex:

http://www.codeplex.com/wiki/view.aspx?projectname=vfpx&title=gdiplusx

 


here's a sample code:


 


do locfile("system.app")


with _screen.system.drawing
   * create a bitmap object based on a bmp file.
   local looriginalbmp as xfcbitmap
   looriginalbmp = .
bitmap.new(getpict())
   local lomonochrbmp as xfcbitmap
   lomonochrbmp = looriginalbmp.getmonochrome()
   * save the created monochromatic bmp
   lomonochrbmp.save("c:\monochromatic.bmp", .imaging.imageformat.bmp)
endwith
return

 
 
and here are the results for two images:



          


 


          


 


the first picture seems nice, doesn't it?


but the vfpx logo did not appear in the monochrome image. that happens because the orange background from the text is dark, and gdi converts it to black.


 


but using a little trick we can fix that, by converting the image to a brighter greyscale  before converting to monochrome. it's not in the scope of this short article to explain how to do that, because i already came into this deply in two articles published in utmag, special effects on images with new gdiplus-x classes - part 1 and special effects on images with new gdiplus-x classes - part 2.


to convert to greyscale, we can use a color matrix that will convert each pixel to the average between its red, green and blue components. for a default greyscale, we normally multiply each color component with 0.33 ( 1 / 3 ). to obtain a brighter image, we have to multiply each component with a higher factor.


 


so, here are the steps to convert to monochrome :


1 - load original image to gdi+


2 - create a new temporary bitmap with the same size of the original


3 - create an imageattributes object


4 - apply a "greyscale" color matrix to image attributes


6 - draw the original image to the created bitmap using the imageattributes


7 - save the image


 


for this sample i created a loop in which the factor ranges from .10 to 1, to obtain different images.


 


do locfile("system.app")


with _screen.system.drawing


local lcimgfile
lcimgfile =
getpict()


* create a bitmap object based on a bmp file.
local looriginalbmp as xfcbitmap
looriginalbmp = .
bitmap.fromfile(lcimgfile)


local lotempbmp as xfcbitmap
lotempbmp = .
bitmap.new(looriginalbmp.width, looriginalbmp.height)


local logfx as xfcgraphics
logfx = .graphics.fromimage(lotempbmp)


local loattr as xfcimageattributes
local logreyscalematrix as xfccolormatrix
local lomonochrbmp as xfcbitmap


local lorectbounds as xfcrectangle
lorectbounds = looriginalbmp.getbounds()


for lnfactor = .10 to 1 step .10
   logreyscalematrix =
_screen.system.drawing.imaging.colormatrix.new( ;
      lnfactor, lnfactor, lnfactor, 0.0, 0.0, ;
      lnfactor, lnfactor, lnfactor, 0.0, 0.0, ;
      lnfactor, lnfactor, lnfactor, 0.0, 0.0, ;
      0.0 , 0.0 , 0.0 , 1.0, 0.0, ;
      0.0 , 0.0 , 0.0 , 0.0, 1.0)


   loattr = null
   loattr = .imaging.imageattributes.new()
   loattr.setcolormatrix(logreyscalematrix)


   * draw the image with the color matrix transformations
   logfx.drawimage(looriginalbmp, lorectbounds, lorectbounds, 2, loattr)


   lomonochrbmp = lotempbmp.getmonochrome()


   * save the created monochromatic bmp
   lomonochrbmp.save("c:\" + juststem(lcimgfile) + ;
      transform(lnfactor * 100) + ".bmp", .imaging.imageformat.bmp)
endfor


endwith
return


 


and this time we can obtain better results, according to the desired factor.

































original picture
factor = 10factor = 20factor = 30factor = 40factor = 50
factor = 60factor = 70factor = 80factor = 90factor = 100



 


 


 































original picture
factor = 10factor = 20factor = 30factor = 40factor = 50
factor = 60factor = 70factor = 80factor = 90factor = 100

 


 


 


related links:

utmag articles:

special effects on images with new gdiplus-x classes - part 1

special effects on images with new gdiplus-x classes - part 2

using tiffs with the new gdi+ classes

No comments:

Post a Comment