I have a custom 8 bit image stored as BYTE*
BYTE* m_pData;
It contains grayscal values.
I created a Bitmap
Bitmap bm(m_width, m_height, m_pitch, PixelFormat8bppIndexed, m_pData);
Then I adjusted its ColorPalette to get correct greyscale values:
UINT nPaletteSize = bm.GetPaletteSize();
pPalette = new Gdiplus::ColorPalette[nPaletteSize];
bm.GetPalette(pPalette, nPaletteSize);
bm.Flags = 0;//PaletteFlagsGrayScale;
for(UINT i = 0; i < pPalette->Count; i++)
{
pPalette->Entries[i] = Color::MakeARGB(0xFF, (BYTE)i, (BYTE)i, (BYTE)i);
}
bm.SetPalette(pPalette);
Next step is getting the CLSID for jpg (see CImage),
set up EncoderParameters and call bm.Save(...).
Here are my questions:
- Saving it as a "bmp" works as expected i get a 8 bit bmp. But
saving it as a "jpg" I get a 24 bit jpg. How to get a 8 bit jpg?
- Maybe a stupid question:
HowTo reserve memory (C++) for EncoderParameters so that I can use
more than one parameter?
EncoderParameters ep;
//ToDo: howto alloc mem
//
ep.Count = 2;
ep.Parameter[0] = ...
ep.Parameter[1] = ...
- Why is it necessary to adjust the ColorPalette?
I thought it would be sufficent to create a Gdiplus::Bitmap
with the correct format.
thx
Tom
8bpp greyscale images and 8bpp jpg is not supported with gdiplus version
1.0.
There is a new version of gdiplus in Windows 7 that supports greyscale
images and more enhanced codec support.
I have not tried the new version so I do not know if the jpeg codec was
updated to support 8bpp greyscale images.
I do know that greyscale and 8bpp indexed jpeg images are supported with
Microsoft's WIC API.
You can try it yourself by downloading the WIC explorer from Microsoft's
download site.
>
> - Maybe a stupid question:
> HowTo reserve memory (C++) for EncoderParameters so that I can use
> more than one parameter?
> EncoderParameters ep;
> //ToDo: howto alloc mem
> //
> ep.Count = 2;
> ep.Parameter[0] = ...
> ep.Parameter[1] = ...
//To allocate memory for "Count" parameters
int Count = 2;
EncoderParameters *ep = new EncoderParameters[Count];
> - Why is it necessary to adjust the ColorPalette?
> I thought it would be sufficent to create a Gdiplus::Bitmap
> with the correct format.
It is not sufficient. It is your responsibility to create a palette, fill
in the palette and finally set the bitmap to use the palette that you
created.
AFAIK, standard JPEG only supports 24-bit image. It also doesn't support
transparency nor multiple layers.
Thanks. I'll have a look at it.
>> - Maybe a stupid question:
>> HowTo reserve memory (C++) for EncoderParameters so that I can use
>> more than one parameter?
>> EncoderParameters ep;
>> //ToDo: howto alloc mem
>> //
>> ep.Count = 2;
>> ep.Parameter[0] = ...
>> ep.Parameter[1] = ...
>
> //To allocate memory for "Count" parameters
> int Count = 2;
> EncoderParameters *ep = new EncoderParameters[Count];
It seems to work, although I don't know why. IMHO memory allignment
of a struct containing a struct
EncoderParameters
{
UINT
EncoderParameter[]
}
is something like
<sizeof(UINT)><EncoderParameter[0]><EncoderParameter[1]>...
and on the contrary
EncoderParameters *ep = new EncoderParameters[Count];
would result in sth. like
<sizeof(UINT)><EncoderParameter[0]><sizeof(UINT)><EncoderParameter[0]>...
My workaround was creating an own struct and casting it to
EncoderParameters:
MyEncoderParameters
{
UINT Count
EncoderParameter Parameter[10]
}
But I didn't test it in all circumstances.
Since the EncoderParameters structure already allocates memory for one
EncoderParameter, you may use the following:
EncoderParameters* ep = reinterpret_cast<EncoderParameters*>( new unsigned
char[ sizeof(EncoderParameters) + sizeof(EncoderParameter) * (Count-1) ] );