Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

JPEG encoder producing bad images

jnoring
Beginner
1,148 Views

I'm having some trouble with the JPEG encoder sample, specifically the code in ipp_samplejpegjpegviewjpegcodec. I'm finding that it will randomly produce junk images as output. Here is how I'm using the code:

BOOL SaveAsJPEG( WM_MEDIA_TYPE * MediaType, byte * pBuffer,

int quality, byte ** pOutBuffer, DWORD * pOutBufferLength )

{

WMVIDEOINFOHEADER * pVIH = (WMVIDEOINFOHEADER * )MediaType->pbFormat;

CJPEGEncoder encoder;

*pOutBuffer =

new byte[pVIH->bmiHeader.biSizeImage];

int LineStep = (pVIH->bmiHeader.biBitCount * pVIH->bmiHeader.biWidth ) / 8;

int JPEGSize = 0;

// Input and output color defs. our inputs get determined below.

JCOLOR InColor = ::JC_UNKNOWN;

JCOLOR OutColor = ::JC_YCBCR;

JSS InSampling = ::JS_OTHER;

JSS OutSampling = ::JS_411;

IppiSize roi;

roi.height = abs(pVIH->bmiHeader.biHeight);

// biheight can potentially be negative

roi.width = pVIH->bmiHeader.biWidth;

if( MediaType->subtype == WMMEDIASUBTYPE_YUY2 )

{

InColor = ::JC_YCBCR;

InSampling = ::JS_422;

OutSampling = ::JS_422;

}

else if( MediaType->subtype == ::WMMEDIASUBTYPE_RGB24 )

{

InColor = ::JC_BGR;

InSampling = ::JS_444;

}

// JAN: as far as I can tell, the # of channels parameter isn't actually used. This would make sense, since that

// information can be infered from the colorspace and format anyways.

JERRCODE jerr = encoder.SetSource( (Ipp8u * ) pBuffer,LineStep,roi, pVIH->bmiHeader.biPlanes, InColor, InSampling );

if(JPEG_OK != jerr)

{

return FALSE;

}

jerr = encoder.SetDestination(*pOutBuffer, (

int) pVIH->bmiHeader.biSizeImage, quality, OutColor, OutSampling );

if(JPEG_OK != jerr)

{

return FALSE;

}

jerr = encoder.WriteHeader();

if(JPEG_OK != jerr)

{

return FALSE;

}

jerr = encoder.WriteData();

if(JPEG_OK != jerr)

{

return FALSE;

}

*pOutBufferLength = (DWORD) encoder.m_dst.currPos;

CAtlFile jpeg;

jpeg.Create(

"C:\blah.jpg",GENERIC_WRITE, FILE_SHARE_READ, OPEN_ALWAYS) ;

JPEGSize = encoder.m_dst.currPos;

jpeg.Write(*pOutBuffer, *pOutBufferLength);

jpeg.Close();

return TRUE;

}

...if I check blah.jpg, sometimes it looks great, and other times it looks not so great.

The image will have large, blocky sections in it. I suspect it may have something to do

with using 422 video as an input. Does anyone have any ideas that could help me troubleshoot

what's going wrong?

Thanks in advance.

0 Kudos
10 Replies
Vladimir_Dudnik
Employee
1,148 Views

I think something is wrong with parameters you apply for JPEG encoder. For example, number of channels parameter is actually used, even if it can be determined indirectly in that particular case. As far as I know, number of planes in BITMAPINFOHEADER is always equal to 1. But IPP JPEG encoder expect it should be specified as 3 for three-channel images. Information about color is just additional info and used to decide what kind of color conversion is required. If you will specify input and output color as JC_UNKNOWN there will be no way to determine number of color components in image except nChannels parameter.

Hope it helps,
Vladimir

0 Kudos
jnoring
Beginner
1,148 Views

I'll try changing the channels, but I looked through the source code, and I can't see anywhere that m_src.nChannels is actually used in the encoding process. Plus if this were in error, I'd expect it to fail every time, rather than sporadically producing a bad image.

Also, I use 422 and YCbCr settings, so that should be more than enough info for it to figure out how many color channels there are. I don't use JC_UNKNOWN.

0 Kudos
jnoring
Beginner
1,148 Views

Okay, I still get corrupt images if I change the channels parameter to 3. I also took some time to turn on trace and error statements. Here is the output from a good file:

validvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalid-> WriteSOI
emit marker 216
-> WriteAPP0
emit marker 224
length 16
-> WriteCOM
emit marker 254
length 54
-> WriteDQT
emit marker 219
length 67
id 0
precision 0

16 11 12 14 12 10 16 14
13 14 18 17 16 19 24 40
26 24 22 22 24 49 35 37
29 40 58 51 61 60 57 51
56 55 64 72 92 78 64 68
87 69 55 56 80 109 81 87
95 98 103 104 103 62 77 113
121 112 100 120 92 101 103 99

-> WriteDQT
emit marker 219
length 67
id 1
precision 0

17 18 18 24 21 24 47 26
26 47 99 66 56 66 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99

-> WriteSOF0
emit marker 192
length 17
-> WriteDHT
emit marker 196
length 31
id 0
class 0
-> WriteDHT
emit marker 196
length 31
id 1
class 0
-> WriteDHT
emit marker 196
length 181
id 0
class 1
-> WriteDHT
emit marker 196
length 181
id 1
class 1
-> WriteSOS
emit marker 218
length 12
ncomp 3
id 0
dc_selector 0
ac_selector 0
id 1
dc_selector 1
ac_selector 1
id 2
dc_selector 1
ac_selector 1
Ss 0
Se 63
Ah 0
Al 0
-> WriteEOI
emit marker 217

...and here's the output from a bad file:

validvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalidvalid-> WriteSOI
emit marker 216
-> WriteAPP0
emit marker 224
length 16
-> WriteCOM
emit marker 254
length 54
-> WriteDQT
emit marker 219
length 67
id 0
precision 0

16 11 12 14 12 10 16 14
13 14 18 17 16 19 24 40
26 24 22 22 24 49 35 37
29 40 58 51 61 60 57 51
56 55 64 72 92 78 64 68
87 69 55 56 80 109 81 87
95 98 103 104 103 62 77 113
121 112 100 120 92 101 103 99

-> WriteDQT
emit marker 219
length 67
id 1
precision 0

17 18 18 24 21 24 47 26
26 47 99 66 56 66 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99
99 99 99 99 99 99 99 99

-> WriteSOF0
emit marker 192
length 17
-> WriteDHT
emit marker 196
length 31
id 0
class 0
-> WriteDHT
emit marker 196
length 31
id 1
class 0
-> WriteDHT
emit marker 196
length 181
id 0
class 1
-> WriteDHT
emit marker 196
length 181
id 1
class 1
-> WriteSOS
emit marker 218
length 12
ncomp 3
id 0
dc_selector 0
ac_selector 0
id 1
dc_selector 1
ac_selector 1
id 2
dc_selector 1
ac_selector 1
Ss 0
Se 63
Ah 0
Al 0
-> WriteEOI
emit marker 217

...the images in question are quite small; I first scale QVGA or VGA images down to 128*96 pixels, and then they're handed off to the library. Here's an example of what a good and bad thumbnail look like, if that helps at all:

http://www.flickr.com/photos/goldfishy/archives/date-taken/2007/03/02/

0 Kudos
Vladimir_Dudnik
Employee
1,148 Views

You are right, nchannels is not used in encoder, sorry for mispointing you. Well, could you please attach to this thread one input frame and one resulting JPEG stream?

Vladimir

0 Kudos
jnoring
Beginner
1,148 Views

No need to apologize--believe me, I'm thrilled to have someone listening. :)

Thelink I posted abovehas bad and good JPEG output images; the input image could be tricky because it's YUY2; do you just want the raw file containing YUY2 image data? (it'd be 128*96*2 bytes in size, and wouldn't have any header info since it's just a dib)

I'm also going to see if I can reproduce the error with RGB24 input values.

0 Kudos
Vladimir_Dudnik
Employee
1,148 Views

Yes, just raw input frame will be enough as we know its parameters.

Need something to test.

0 Kudos
jnoring
Beginner
1,148 Views

Vladimir,

I determined that the JPEG compressor is not producing bad frames by examining the input. I found that my imputs were clearly bad to begin with (whoops), and after a few more hours of examination, I figured out why they were bad.

Thanks for all of your help.

0 Kudos
Vladimir_Dudnik
Employee
1,148 Views

Hi, glad to hear that issue was solved.

Note, JPEG codec is threaded with using OpenMP API, so if you want to take advantage of modern dual core systems or old SMP systems:) you need to compile codec with Intel C/C++ compiler or MS VC2005 compiler, see Makefile for necessary options. Please let us know your feeling regarding functionality and performance of IPP JPEG codec.

Regards,
Vladimir

0 Kudos
jnoring
Beginner
1,148 Views

We are compiling with MS VC2005, although I'm not totally sure what options in the makefile we'd need to extract. In any event, the JPEG encoder/decoder works very well. One thing: does the JPEG library support YV12 inputs? I'd like to use YV12, but I recall I ended up using YUY2 because it appeared like it didn't support YV12.

I would also love to have a C# library for doing jpeg compression/decompression. It seems like most of the underlying IPP function calls have a C# definition available. I suppose I could just compile the JPEG library into a dll and export some function calls, but it's be really cool to have a sample implementation in managed code.

0 Kudos
Vladimir_Dudnik
Employee
1,148 Views

Thanks for providing additional information. You are right, currently JPEG codec do not support YV12 as direct input or output. We do have it in plan, but it still not implemented yet.

I think it is better to compiler time-consuming algorithms (like JPEG) as a DLL (and recommend to use Intel C/C++ compiler for the performance reasons) and provide C# interface to small number of interface functions instead of implementing JPEG codec in C# with wrapping each IPP function in C#. Anyway, I recommend you to submit your feature request to Intel Premier Support, so we will consider it at next IPP version planning stage.

As far as I know, you need to specify option openmp in VC2005 project settings to enable OpenMP (after that it will implicitely define macro _OPENMP and IPP JPEG codec will take advantage of OpenMP API automatically)

Vladimir

0 Kudos
Reply