my first attempt at using CreateDIBSection :P
it seems to work pretty well
AverageColor PROTO :HBITMAP
;***********************************************************************************************
AverageColor PROC USES EBX ESI EDI hbmpBitmap:HBITMAP
;Returns a COLORREF value that approximates the algebraic mean color of an image.
;by DednDave, 6-14-2012
;
;Call With: hbmpBitmap = bitmap image handle
;
; Returns: if successful, EAX = average image color
; EDX = contrasting color (EAX xor 808080h)
; if unsuccessful, EAX = 0 (black)
; EDX = 0FFFFFFh (white)
;
;-------------------------------
AVGCLR_SIZMAX EQU 1564000
AVGCLR_DIMSML EQU 1000
AVGCLR_DIMLRG EQU 1564
AVGCLR_DIMSQR EQU 1252
;-------------------------------
LOCAL hdcMem1 :HDC
LOCAL hdcMem2 :HDC
LOCAL hbmpMem2 :HBITMAP
LOCAL hbmpPrev1 :HBITMAP
LOCAL hbmpPrev2 :HBITMAP
LOCAL pvBits :LPVOID
LOCAL sizeBitmap :_SIZE
LOCAL uBytesPerLine :DWORD
LOCAL bmis :BITMAPINFO
;BITMAPINFO STRUCT
; bmiHeader BITMAPINFOHEADER <>
; biSize dd ? ;BITMAPINFOHEADER structure size
; biWidth dd ? ;image width in pixels
; biHeight dd ? ;signed image height in pixels
; biPlanes dw ? ;= 1
; biBitCount dw ? ;= 24
; biCompression dd ? ;= BI_RGB
; biSizeImage dd ? ;image data bytes
; biXPelsPerMeter dd ? ;= 0
; biYPelsPerMeter dd ? ;= 0
; biClrUsed dd ? ;= 0
; biClrImportant dd ? ;= 0
; bmiColors RGBQUAD <>
;-------------------------------
INVOKE GetBitmapSize,hbmpBitmap,addr sizeBitmap
mov esi,eax ;ESI = image height
xor ebx,ebx
mul ecx
mov edi,ecx ;EDI = image width
or edx,edx
jnz AvgCl1
or eax,eax
jnz AvgCl0
;the image has a width or height of 0, or both
mov edx,0FFFFFFh
jmp AvgCl9
AvgCl0: cmp eax,AVGCLR_SIZMAX
jbe AvgCl4
;If we come here, it means we are going to reduce the image.
;We divide the larger image dimension by the smaller one.
;If that ratio is greater than or equal to 1.25:1, we use a
;rectangle of AVGCLR_DIMLRG x AVGCLR_DIMSML if the image is
;wide, or AVGCLR_DIMSML x AVGCLR_DIMLRG if the image is tall.
;Otherwise, we use a square of AVGCLR_DIMSQR x AVGCLR_DIMSQR.
AvgCl1: xor edx,edx
mov eax,esi
inc ebx
cmp eax,ecx
jae AvgCl2
xchg eax,ecx
AvgCl2: div ecx
dec eax
jnz AvgCl3
shl edx,2
cmp edx,ecx
jae AvgCl3
mov edi,AVGCLR_DIMSQR
mov esi,edi
jmp short AvgCl4
AvgCl3: cmp edi,esi
mov edi,AVGCLR_DIMLRG
mov esi,AVGCLR_DIMSML
jae AvgCl4
xchg edi,esi
AvgCl4: mov eax,edi
xor edx,edx
mov bmis.bmiHeader.biSize,sizeof BITMAPINFOHEADER
shl eax,1
mov bmis.bmiHeader.biWidth,edi
mov bmis.bmiHeader.biHeight,esi
add eax,edi
mov bmis.bmiHeader.biCompression,edx ;BI_RGB = 0
mov bmis.bmiHeader.biXPelsPerMeter,edx
add eax,3
mov bmis.bmiHeader.biYPelsPerMeter,edx
and al,0FCh
mov bmis.bmiHeader.biClrUsed,edx
mov bmis.bmiHeader.biClrImportant,edx
mov uBytesPerLine,eax
mov bmis.bmiHeader.biPlanes,1
mul esi
mov bmis.bmiHeader.biBitCount,24
mov bmis.bmiHeader.biSizeImage,eax
push edi
INVOKE GetDC,HWND_DESKTOP
xchg eax,edi
INVOKE CreateCompatibleDC,edi
mov hdcMem1,eax
INVOKE SelectObject,eax,hbmpBitmap
xor edx,edx
mov hbmpPrev1,eax
INVOKE CreateDIBSection,edi,addr bmis,DIB_RGB_COLORS,addr pvBits,edx,edx
mov hbmpMem2,eax
INVOKE CreateCompatibleDC,edi
mov hdcMem2,eax
INVOKE SelectObject,eax,hbmpMem2
mov hbmpPrev2,eax
INVOKE ReleaseDC,HWND_DESKTOP,edi
dec ebx
pop edi
jz AvgCl5
inc ebx
INVOKE BitBlt,hdcMem2,ebx,ebx,edi,esi,hdcMem1,ebx,ebx,SRCCOPY
jmp short AvgCl6
AvgCl5: INVOKE SetStretchBltMode,hdcMem2,HALFTONE
INVOKE SetBrushOrgEx,hdcMem2,ebx,ebx,ebx
INVOKE StretchBlt,hdcMem2,ebx,ebx,edi,esi,hdcMem1,
ebx,ebx,sizeBitmap.x,sizeBitmap.y,SRCCOPY
;EDI = DIB section width
;ESI = DIB section height
;pvBits = address of first image scan line
;uBytesPerLine = bytes per line
AvgCl6: push ebp
push esi
mov edx,pvBits
mov eax,ebx
push uBytesPerLine
mov ecx,ebx
mov ebp,ebx
AvgCl7: push edi
push edx
AvgCl8: mov al,[edx]
add ebx,eax
mov al,[edx+1]
add ecx,eax
mov al,[edx+2]
add edx,3
add ebp,eax
sub edi,1
jnz AvgCl8
pop edx
pop edi
add edx,[esp]
sub esi,1
jnz AvgCl7
pop edx
pop eax
mul edi
xchg eax,edi
;EBX = blue total
;ECX = green total
;EBP = red total
;ESI = 0
;EDI = divisor
mov eax,ebx
mov edx,esi
mov ebx,esi
div edi
shl edx,1
cmp edx,edi
sbb al,-1
adc al,-1
mov bh,al
mov edx,esi
mov eax,ecx
shl ebx,8
div edi
shl edx,1
cmp edx,ecx
sbb al,-1
adc al,-1
mov edx,esi
mov bh,al
mov eax,ebp
div edi
shl edx,1
cmp edx,ecx
sbb al,-1
adc al,-1
mov bl,al
pop ebp
INVOKE SelectObject,hdcMem2,hbmpPrev2
INVOKE DeleteObject,eax
INVOKE DeleteDC,hdcMem2
INVOKE SelectObject,hdcMem1,hbmpPrev1
INVOKE DeleteDC,hdcMem1
xchg eax,ebx
mov edx,eax
xor edx,808080h
AvgCl9: ret
AverageColor ENDP
;***********************************************************************************************
oh yah - a needed support function
GetBitmapSize PROTO :HBITMAP,:LPVOID
;***********************************************************************************************
GetBitmapSize PROC hbmpBitmap:HBITMAP,lpSize:LPVOID
;BITMAP STRUCT
; bmType dd ?
; bmWidth dd ?
; bmHeight dd ?
; bmWidthBytes dd ?
; bmPlanes dw ?
; bmBitsPixel dw ?
; bmBits dd ?
xor eax,eax
sub esp,sizeof BITMAP-12
push eax
push eax
push eax
INVOKE GetObject,hbmpBitmap,sizeof BITMAP,esp
pop edx
pop ecx
pop eax
mov edx,lpSize
add esp,sizeof BITMAP-12
or edx,edx
jz GBSize
mov [edx]._SIZE.x,ecx
mov [edx]._SIZE.y,eax
GBSize: ret
GetBitmapSize ENDP
;***********************************************************************************************
Just out of curiosity, how would you use the average color?
well - there are other uses, but i am using it as a background or "matte" to surround an image
i am almost finished with this little project
one more function to write
i want to be able to open a variety of image types from file or resource
BMP, DIB, EMF, GIF, ICO, JPG, PNG, TIFF, WMF
at the moment, i can only open BMP's - otherwise it is pretty much done
i will post it with source
it has pan/zoom - pan-grab - pretty cool :P
maybe later, i will make it handle transparent images, as well
not needed for this program, but i want a versatile function i can use for other things
i could add some other things - like measuring calipers :P
i implemented calipers in a 16-bit program long ago that was kinda neat
here is the project as it is...
it will only open BMP and DIB files, at the moment
and - it needs a bit of clean-up
but, i thought it would be fun for others to play with :P
notice that, when you open a new image, the custom colors in the color-picker are modified
the first custom color is the image average and the last one is the contrasting color
(http://img9.imageshack.us/img9/6327/mapviewer.png)
Hi,
Rather nice program Dave. I think I will see if I can
learn something from it.
Thanks,
Steve
thanks Steve :t
Nice looking project
thanks Don
i have some more work to do on it
i had to set it aside to get some other things done, for now
hopefully, i will get back to it in the next few days