Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
9 Views

UIC bitmap decoder

Jump to solution
I'm new to UIC, and I'm trying to figure out how to use the BMP decoder. I think I'm following the example, but I'm getting heap corruption at the end of my file. I'm trying to decode a 24 BPP BGR bitmap saved out by a C# .NET program, but I get the same results on several BMP images. I'll put my short example code below, but I had several questions:

1) is it possible to allocate the image memory myself, or do I have to use the UIC buffers?
2) How does one copy a UIC image?

Any help appreciated.

[cpp]#include "stdfilein.h"
#include "stdfileout.h"
#include "uic_bmp_dec.h"

using namespace UIC;
typedef unsigned int uint;
inline uint AlignStep(uint step) { return (step + 31) & 0xFFFFFFE0; } 
char* color_str[] = { "Unknown", "Grayscale", "RGB", "BGR",
"YCbCr", "CMYK", "YCCK", "YUV" };

int decodeBMP(BaseStreamInput& in, Image& image) 
{
	BMPDecoder decoder;
	ImageSamplingGeometry samplingGeometry;    
	ImageDataPtr dataPtr; 
	ImageDataOrder dataOrder;

	if(!IsOk(decoder.Init()))
	{
		return 1;
	}
	if(!IsOk(decoder.AttachStream(in)))
	{
		return 1;
	}

	if(!IsOk(decoder.ReadHeader(image.ColorSpec(), samplingGeometry)))
	{
		return 1;
	}
	uint nOfComponents = samplingGeometry.NOfComponents();
	
	//dataOrder.SetDataType(T8u);
	if(!IsOk(dataOrder.ReAlloc(Interleaved, nOfComponents)))
	{
		return 1;
	}

	for(uint component = 0; component < nOfComponents; component++)
	{
		dataOrder.PixelStep()[component] = nOfComponents;
		dataOrder.LineStep() [component] =
			AlignStep(samplingGeometry.RefGridRect().Width() *
			dataOrder.PixelStep()[component]);
	}

	image.ColorSpec().ReAlloc(nOfComponents);
	image.ColorSpec().SetColorSpecMethod(Enumerated);
	image.ColorSpec().SetComponentToColorMap(Direct);

	for(uint i = 0; i < nOfComponents; i++)
		image.ColorSpec().DataRange().SetAsRange8u(255);
	image.ColorSpec().SetEnumColorSpace(UIC::BGR);

	if(!IsOk(image.Buffer().ReAlloc(dataOrder, samplingGeometry)))
	{
		return 1;
	}
	if(!IsOk(decoder.ReadData(image.Buffer().DataPtr(), 
		image.Buffer().BufferFormat().DataOrder())))
	{
		return 1;
	} 	
	int a = 1;
	return 0;
}
int main(int argc, char* argv[])	
{
	ExcStatus res;
	CStdFileInput fi;
	CStdFileOutput fo;
	Image image; 
	if(argc < 2)
	{
		printf("only got %d args\n", argc);
		return 1;  
	}  
	if(!BaseStream::IsOk(fi.Open(argv[1])))
		return 1;
	res = decodeBMP(fi,image);
	if(!IsOk(res))
		return 1;
	printf("file: %s\n",argv[1]);
	printf("%dx%dx%d, %d-bits, color: %s\n",
		image.Buffer().BufferFormat().SamplingGeometry().RefGridRect().Width(),
		image.Buffer().BufferFormat().SamplingGeometry().RefGridRect().Height(),
		image.Buffer().BufferFormat().SamplingGeometry().NOfComponents(),
		image.ColorSpec().DataRange()[0].BitDepth() + 1,
		color_str[image.ColorSpec().EnumColorSpace()]);
}[/cpp]
0 Kudos

Accepted Solutions
Highlighted
New Contributor I
9 Views
Hi,
to remove heap corruption you need to make some modification of your sample code:
istead of
[cpp]    for(uint component = 0; component < nOfComponents; component++)  
    {  
        dataOrder.PixelStep()[component] = nOfComponents;  
        dataOrder.LineStep() [component] =  
            AlignStep(samplingGeometry.RefGridRect().Width() *  
            dataOrder.PixelStep()[component]);  
    }  [/cpp]
you need
[cpp]    dataOrder.PixelStep()[0] = nOfComponents;
    dataOrder.LineStep()[0]  = samplingGeometry.RefGridRect().Width() * nOfComponents + 
                               BYTES_PAD(samplingGeometry.RefGridRect().Width(), nOfComponents, 1);[/cpp]
there is BYTES_PAD is
[cpp]#define ALIGN_VALUE (sizeof(int) - 1)
#define BYTES_PAD(iWidth, iChannels, iDU) (((iWidth * iChannels * iDU + ALIGN_VALUE) & (~ALIGN_VALUE)) - iWidth * iChannels * iDU)[/cpp]
About questions:
1) where is no problem in using external users buffers to store decoded image in it. The sample code below show how it can be done:
[cpp]  Ipp32u        size;
  Ipp8u*        buff;
  ImageDataPtr  dataPtr;

  size = dataOrder.LineStep[0] * samplingGeometry.RefGridRect().Width();
  buff = (Ipp8u*)ippMalloc(size);

  dataPtr.p8u = buff;

  image.Buffer().Attach(&dataPtr, dataOrder, samplingGeometry);
[/cpp]
in theis case you don need to realloc Image.Buffer() like you did in:
[cpp]if(!IsOk(image.Buffer().ReAlloc(dataOrder, samplingGeometry)))[/cpp]
2) sorry, but it is not clear for me what you mean in this question. is it "how can i copy decoded image from UIC::Image object"?

View solution in original post

0 Kudos
5 Replies
Highlighted
New Contributor I
10 Views
Hi,
to remove heap corruption you need to make some modification of your sample code:
istead of
[cpp]    for(uint component = 0; component < nOfComponents; component++)  
    {  
        dataOrder.PixelStep()[component] = nOfComponents;  
        dataOrder.LineStep() [component] =  
            AlignStep(samplingGeometry.RefGridRect().Width() *  
            dataOrder.PixelStep()[component]);  
    }  [/cpp]
you need
[cpp]    dataOrder.PixelStep()[0] = nOfComponents;
    dataOrder.LineStep()[0]  = samplingGeometry.RefGridRect().Width() * nOfComponents + 
                               BYTES_PAD(samplingGeometry.RefGridRect().Width(), nOfComponents, 1);[/cpp]
there is BYTES_PAD is
[cpp]#define ALIGN_VALUE (sizeof(int) - 1)
#define BYTES_PAD(iWidth, iChannels, iDU) (((iWidth * iChannels * iDU + ALIGN_VALUE) & (~ALIGN_VALUE)) - iWidth * iChannels * iDU)[/cpp]
About questions:
1) where is no problem in using external users buffers to store decoded image in it. The sample code below show how it can be done:
[cpp]  Ipp32u        size;
  Ipp8u*        buff;
  ImageDataPtr  dataPtr;

  size = dataOrder.LineStep[0] * samplingGeometry.RefGridRect().Width();
  buff = (Ipp8u*)ippMalloc(size);

  dataPtr.p8u = buff;

  image.Buffer().Attach(&dataPtr, dataOrder, samplingGeometry);
[/cpp]
in theis case you don need to realloc Image.Buffer() like you did in:
[cpp]if(!IsOk(image.Buffer().ReAlloc(dataOrder, samplingGeometry)))[/cpp]
2) sorry, but it is not clear for me what you mean in this question. is it "how can i copy decoded image from UIC::Image object"?

View solution in original post

0 Kudos
Highlighted
Beginner
9 Views
Thanks!

My misunderstanding was that the pixelStep and LineStep were for each channel and not for the entire image. I had stolen that code from the JPEG2000 example which had plane data and not like BMP which uses interleaved, which was my error.

Thanks also for the example of ippMalloc. It makes sense to use such a function because like ReAlloc the deallocation matches the allocation. For optimization, it would be nice to pass in an external (non-IPP) buffer when decoding. But, it would have to use malloc, which my external library doesn't use. So, I'll just memcpy it when done...

As for copying images, I have figured out what I want.

I really appreciate your fast, accurate response.


0 Kudos
Highlighted
Valued Contributor I
9 Views
I would like to suggest you to use Photoshop to create test images in all possible BMP formats, and then try to decode those using UIC so you know in advance what works and what doesn't.

I was a bit disappointed and I wrote my own decoder in the end.
0 Kudos
Highlighted
9 Views
Thank you for your suggestion, Igor.

By the way, in IPP 7.0 we have fixed issues which you reported out on previous version of UIC BMP decoder.

Note, there are still some limitations on UIC BMP implementation (like old OS/2 BMP format, 1, 4 or 16 bits per pixel formats and some others). Our goal in UIC BMP implementation is to provide simple code which handle most of true color BMP files. UIC development focus is on more complex image compression formats.

Regards,
Vladimir
0 Kudos
Highlighted
Valued Contributor I
9 Views
Hello Vladimir,

I suggested them to check because some developers might have different requirements (if you are writing image viewer or converter you will want to support even those old formats).

I am not saying that UIC::BMP class is useless, just that it has limitations which should be carefully considered.
0 Kudos