The MASM Forum

General => The Campus => Topic started by: Ar0n on January 06, 2016, 02:01:25 PM

Title: Converting bitmap color depth
Post by: Ar0n on January 06, 2016, 02:01:25 PM
Guys, I need to convert a 32 bit bitmap to 24, 8, 4, or 1 bit, what functions should I use?
I tried with CreateCompatibleDC -> CreateDIBSection -> Bitblt but it didn't work  :(
Title: Re: Converting bitmap color depth
Post by: Grincheux on January 06, 2016, 04:44:35 PM
Try with CreateCompatibleBitmap and make the bitmap compatible with a memory DC.

QuoteBecause memory device contexts allow both color and monochrome bitmaps, the format of the bitmap returned by the CreateCompatibleBitmap function differs when the specified device context is a memory device context. However, a compatible bitmap that was created for a nonmemory device context always possesses the same color format and uses the same color palette as the specified device context.

https://msdn.microsoft.com/en-us/library/windows/desktop/dd183488(v=vs.85).aspx (https://msdn.microsoft.com/en-us/library/windows/desktop/dd183488(v=vs.85).aspx)

You will loose a lot of infos even if the image is in black and white.

That could help you : https://msdn.microsoft.com/en-us/library/windows/desktop/dd162950(v=vs.85).aspx (https://msdn.microsoft.com/en-us/library/windows/desktop/dd162950(v=vs.85).aspx)
Title: Re: Converting bitmap color depth
Post by: dedndave on January 06, 2016, 10:52:21 PM
the 24-bit case is just a matter of moving bytes around

for the others, you are drastically reducing the number of available colors
and - there are as many ways to do it as there are people who have written code for it - lol

in the past, i have used this one by Derrick Coetzee to create 16-color images

http://www.cs.berkeley.edu/~dcoetzee/downloads/scolorq/ (http://www.cs.berkeley.edu/~dcoetzee/downloads/scolorq/)

it takes some getting used to
and, for any given image, i create several dithered reductions and select the best one
this is not ideal, but yields good results

for 256-color images, i suggest a standardized palette
then, use a nearest-color function to convert to the palette index
i have made a few posts related to this
use the forum "advanced search" tool to look for "color distance", "palette", and "color space"

there are other ways, but a standard palette is probably simplest
Title: Re: Converting bitmap color depth
Post by: dedndave on January 06, 2016, 10:54:52 PM
it helps to fully understand the windows bitmap/dib formats...

https://msdn.microsoft.com/en-us/library/dd183377%28v=vs.85%29.aspx (https://msdn.microsoft.com/en-us/library/dd183377%28v=vs.85%29.aspx)
Title: Re: Converting bitmap color depth
Post by: Ar0n on January 07, 2016, 05:27:10 PM
thanks to both, now I understand what is DIB and DDB and their differences, I know the bitmap format and know the difference between bitmaps of 1,2,4,16 and 24,32-bit. dedndave, you're right, now I understand you. ok so I managed to create the 24-bitmap ( yeah it's just create a DIB and copy the bytes ) but for 1,2,4,16 I need to create the RGB palette ( right? ).

How do I create this palette? atm I do this (pseudocode):


.for i < COLOR_DEPTH
    BitmapInfo.bmiColors[i].rgbRed = i;
    BitmapInfo.bmiColors[i].rgbGreen = i;
    BitmapInfo.bmiColors[i].rgbBlue = i;
    BitmapInfo.bmiColors[i].rgbReserved = 0;
.endfor


it works with 16-bit bitmap images, but they are gray.. also it's black image in 1,2,4-bit bitmaps.
is there a standard way to solve this?

dedndave, that example you gave me looks very advanced for me lol
Title: Re: Converting bitmap color depth
Post by: dedndave on January 07, 2016, 10:55:57 PM
blue byte, green byte, red byte, zero byte

4 bytes, known as an RGBQUAD structure

RGBQUAD STRUCT
  rgbBlue       BYTE      ?
  rgbGreen      BYTE      ?
  rgbRed        BYTE      ?
  rgbReserved   BYTE      ?
RGBQUAD ENDS


the reserved byte must be 0

for a 256-color image, there will be up to 256 palette entries
i usually create all 256, even though the format allows you to use a lesser quantity

you can use CreateDIBSection with iUsage = DIB_RGB_COLORS
Title: Re: Converting bitmap color depth
Post by: dedndave on January 07, 2016, 10:58:19 PM
sometimes, you want to get or set the palette of a 256-color DIB (or 16 or 4 or mono)

GetDIBColorTable
SetDIBColorTable
Title: Re: Converting bitmap color depth
Post by: Farabi on January 09, 2016, 12:13:36 AM
For a 12-bit pixel. in order for the picture not to be artifacted, you have to make the color a bit darker, and then increase the light intensity by 1 until you see it fit. Not by shifting the bits. As for 24-bit to 16-bit, I had no clue how to do it.
Title: Re: Converting bitmap color depth
Post by: Ar0n on January 09, 2016, 05:43:33 PM
Yeah guys, but I don't know how to create this palette of colors, I need to know how to create it.
Can I take out the bytes from another bitmap and use them in my bitmap(s)? does it have some affect? does it could affect in different PCs with different video cards, etc?
Title: Re: Converting bitmap color depth
Post by: dedndave on January 09, 2016, 06:02:55 PM
it's just a table of 4 bytes per color (1024 bytes for 256 colors)

one of the simplest forms of a BMP file is the mono, 16-color, and 256 color with a palette
(the simplest is probably 24-bit/32-bit with no alpha and no palette)

you start with a BITMAPFILEHEADER structure (14 bytes)

https://msdn.microsoft.com/en-us/library/dd183374%28v=vs.85%29.aspx (https://msdn.microsoft.com/en-us/library/dd183374%28v=vs.85%29.aspx)

after that is a BITMAPINFO structure
this structure is made up of other structures, so really need not be defined, per se

https://msdn.microsoft.com/en-us/library/dd183374%28v=vs.85%29.aspx (https://msdn.microsoft.com/en-us/library/dd183374%28v=vs.85%29.aspx)

so, to simplify, let's ignore the BITMAPINFO structure and just examine the BITMAPINFOHEADER structure
and - the palette

https://msdn.microsoft.com/en-us/library/dd183376%28v=vs.85%29.aspx (https://msdn.microsoft.com/en-us/library/dd183376%28v=vs.85%29.aspx)

now, you follow that with the palette, made up of RGBQUAD structures
2 for a monochrome image (8 bytes total)
16 for a 16-color image (64 bytes total)
256 for a 256-color image (1024 bytes total)

each RGBQUAD has a blue byte, a green byte, and a red byte, followed by a zero filler byte
(previously discussed)

after that is the image data
the last line of the image is typically first in the file
for a 256-color image, each byte of image data refers to a color index
i.e., if the byte is 0, the first palette entry will be used for the pixel color
if the byte is 0FFh, the last palette entry will be used for the pixel color

the length of each line of any BMP or DIB is evenly divisible by 4
so, if there are only 31 bytes of image data, the line is padded with a 0 byte to fill in

monochrome images are similar, but have 8 pixels encoded into each data byte
16-color images have 2 pixels encoded into each data byte

when i use CreateDIBSection, i often create the structures on the stack inside a PROC
once the DIB section is created, the structures are no longer necessary
Title: Re: Converting bitmap color depth
Post by: FORTRANS on January 10, 2016, 12:50:45 AM
Hi,

Quote from: Ar0n on January 09, 2016, 05:43:33 PM
Yeah guys, but I don't know how to create this palette of colors, I need to know how to create it.

   Do a forum search on "pairwise".  dedndave, Gunther, and I discussed
palette creation in that thread.  I use a pairwise clustering algorithm to
reduce the colors in an image to 256 or 16 colors.  (Or custom values for
testing dumb Ideas.)  Median cut and "octree" are other algorithms
to create a smaller palette.  "Most used colors" is used as well, though
I don't like the results.  So try a search on those terms if curious.

HTH,

Steve N.