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

Pixie (obsolete)
plus

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

Convert 24 Bit Bitmaps to Greyscale


Question:

I recently wrote this program to convert 24 bit bitmaps to greyscale but I think I'm doing it the hard way. Is there an easier way, perhaps using GDI+?.
;PART 1

;Run part 1 to create translation tables.
;NOTE: This will create folder c:\Xlate.

#DefineFunction MultiplierTable(multiplier,filename)
buf=BinaryAlloc(256)
For x=1 To 256
BinaryPoke(buf,(x-1),x*multiplier)
Next
BinaryWrite(buf,filename)
BinaryFree(buf)
#EndFunction

#DefineFunction AdditionTable()
buf=BinaryAlloc(65536)
For high=1 To 256
For low=1 To 256
offset=((high-1)*256)+(low-1)
value=(high-1)+(low-1)
If value>255 Then value=255
BinaryPoke(buf,offset,value)
Next
Next
BinaryWrite(buf,"c:\Xlate\AdditionTable.dat")
BinaryFree(buf)
#EndFunction

#DefineFunction GreyscaleHeader()
buf=BinaryAlloc(1078)
BinaryPokeStr(buf,0,"BM")
BinaryPoke2(buf,10,1078)
BinaryPoke(buf,14,40)
BinaryPoke(buf,26,1)
BinaryPoke(buf,28,8)
BinaryPoke(buf,47,1)
value=0
For x=54 To 1074 By 4
BinaryPoke4(buf,x,value)
value=value+65793
Next
BinaryWrite(buf,"c:\Xlate\GreyscaleHeader.dat")
BinaryFree(buf)
#EndFunction

;************************************************************
;Control Section

DirMake("c:\Xlate")
DirChange("c:\Xlate")

;Geometric conversion red*.3, green*.59, blue*.11
;Averaging conversion red*.33, green*.33, blue*.33
MultiplierTable(.3,"RedTable.dat")
MultiplierTable(.59,"GreenTable.dat")
MultiplierTable(.11,"BlueTable.dat")
AdditionTable()
GreyscaleHeader()

Exit

;***********************************************************
;***********************************************************
;PART 2

;Convert 24 bit bitmaps to greyscale

;NOTE: For this program to work, images must follow
;rule filesize=(pixels*3)+54 bytes for header. Images that
;have been cropped from larger images don't follow this rule.
;However, resizing the image slightly will usually fix this.

infile="c:\P5.bmp"
outfile="c:\output.bmp"

;get image dimensions
buf=BinaryAlloc(54)
BinaryReadEx(buf,0,infile,0,54)
type=BinaryPeekStr(buf,0,2)
If type<>"BM" Then
Message("Error","Input file is not a bitmap.")
Exit
EndIf
height=BinaryPeek2(buf,22)
width=BinaryPeek2(buf,18)
depth=BinaryPeek(buf,28)
pixels=width*height
If depth<>24 Then
Message("Error","Image is not 24 bit.")
Exit
EndIf
BinaryFree(buf)

;Load buffers
redbuffer=BinaryAlloc(pixels*4)
greenbuffer=BinaryAlloc(pixels*4)
bluebuffer=BinaryAlloc(pixels*4)
BinaryReadEx(redbuffer,0,infile,54,pixels*3)
BinaryCopy(greenbuffer,0,redbuffer,0,pixels*3)
BinaryCopy(bluebuffer,0,redbuffer,0,pixels*3)

;Apply math
xlatebuffer=BinaryAlloc(256)
BinaryRead(xlatebuffer,"c:\Xlate\RedTable.dat")
BinaryXlate(redbuffer,xlatebuffer,0)
BinaryRead(xlatebuffer,"c:\Xlate\GreenTable.dat")
BinaryXlate(greenbuffer,xlatebuffer,0)
BinaryRead(xlatebuffer,"c:\Xlate\BlueTable.dat")
BinaryXlate(bluebuffer,xlatebuffer,0)
BinaryFree(xlatebuffer)

;Create logical OR table
count=0
a=3
While a<(pixels*3)+3
count=count+1
a=a*2
EndWhile
ORbuffer=BinaryAlloc(a)
BinaryPoke4(ORbuffer,0,65535)
bytes=3
For x=1 To count
BinaryCopy(ORbuffer,bytes,ORbuffer,0,bytes)
bytes=bytes*2
Next

;Isolate red, green and blue values
BinaryOr(redbuffer,0,ORbuffer,0,pixels*3)
BinaryOr(greenbuffer,0,ORbuffer,1,pixels*3) ;shift ORbuffer left
BinaryOr(bluebuffer,0,ORbuffer,2,pixels*3) ;shift ORbuffer left
BinaryFree(ORbuffer)

;convert every 3 bytes into double words
BinaryReplace(redbuffer,"ÿÿ","ÿÿÿ",@FALSE)
BinaryReplace(greenbuffer,"ÿÿ","ÿÿÿ",@FALSE)
BinaryPoke(greenbuffer,BinaryEodGet(greenbuffer),255)
BinaryReplace(bluebuffer,"ÿÿ","ÿÿÿ",@FALSE)

;combine tables
BinaryAnd(redbuffer,0,greenbuffer,0,pixels*4)
BinaryFree(greenbuffer)
BinaryAnd(redbuffer,0,bluebuffer,0,pixels*4)
BinaryFree(bluebuffer)
BinaryReplace(redbuffer,Num2Char(255),Num2Char(1),@FALSE)

;Add red, green and blue values together into a single byte
Addbuffer=BinaryAlloc(65536)
BinaryRead(Addbuffer,"c:\xlate\AdditionTable.dat")
BinaryXlate(redbuffer,Addbuffer,2)
BinaryXlate(redbuffer,Addbuffer,2)
BinaryFree(Addbuffer)
BinaryEodSet(redbuffer,pixels)

;create output file
finalbuffer=BinaryAlloc(pixels+1078)
BinaryRead(finalbuffer,"c:\xlate\GreyscaleHeader.dat")
BinaryCopy(finalbuffer,1078,redbuffer,0,pixels)
BinaryFree(redbuffer)
BinaryPoke4(finalbuffer,2,pixels+1078) ;file size
BinaryPoke2(finalbuffer,22,height) ;image height
BinaryPoke2(finalbuffer,18,width) ;image width
BinaryWrite(finalbuffer,outfile)
BinaryFree(finalbuffer)

;view result
Run(outfile,"")

Exit

Answer:

Use the Pixie Extender.

AddExtender("wwimg34i.dll")
Bright= 100 ;no adjustment
Sat= 0 ;grayscale 
Hue= 100 ;no adjustment
BSH=StrCat(Bright,",",Sat,",",Hue)

infile="color.jpg"
outfile="BlackandWhite.jpg"

ImgModulate(infile,outfile,BSH) ;Brightness, Saturation, Hue



Article ID:   W16842
File Created: 2014:01:29:15:34:52
Last Updated: 2014:01:29:15:34:52