There is certainly a problem with the aptina header generation code. The function DefineQuantizationTableMarker() produces incorrect results. I don’t know exactly why this is, but it clearly does. Replace the function from the developer’s guide with the following:
// Calculate and write the quantisation tables 
// qscale is the customised scaling factor - see MT9D131 developer guide page 78
int DefineQuantizationTableMarker (unsigned char *pbuf, int qscale, int format)
{
	int i, length, temp;
	unsigned char newtbl[64];			// temporary array to store scaled zigzagged quant entries
	if (format == FORMAT_MONOCHROME)	// monochrome
		length  =  67;
	else
		length  =  132;
	*pbuf++  =  0xFF;			// define quantization table marker
	*pbuf++  =  0xDB;
	*pbuf++  =  length>>8;		// length field
	*pbuf++  =  length&0xFF;
	*pbuf++  =  0;				// quantization table precision | identifier
	
	// calculate scaled zigzagged luminance quantisation table entries
	for (i=0; i<64; i++) {
		temp = (JPEG_StdQuantTblY[i] * qscale + 16) / 32;
		// limit the values to the valid range
		if (temp <= 0) 
			temp = 1;
		if (temp > 255) 
			temp = 255; 
		newtbl[zigzag[i]] = (unsigned char) temp;
	}
	// write the resulting luminance quant table to the output buffer
	for (i=0; i<64; i++)
		*pbuf++ = newtbl[i];
	// if format is monochrome we're finished, otherwise continue on, to do chrominance quant table
	if (format == FORMAT_MONOCHROME)
		return length+2;
	*pbuf++ = 1;				// quantization table precision | identifier for chrominance
	// calculate scaled zigzagged chrominance quantisation table entries
	for (i=0; i<64; i++) {
		temp = (JPEG_StdQuantTblC[i] * qscale + 16) / 32;
		// limit the values to the valid range
		if (temp <= 0) 
			temp = 1;
		if (temp > 255) 
			temp = 255; 
		newtbl[zigzag[i]] = (unsigned char) temp;
	}
	// write the resulting chrominance quant table to the output buffer
	for (i=0; i<64; i++)
		*pbuf++ = newtbl[i];
	return (length+2);
}
To go along with the code you need the following 3 lookup tables:
unsigned char JPEG_StdQuantTblY[64] = 
{
16,  11,  10,  16,  24,  40,  51,  61, 
12,  12,  14,  19,  26,  58,  60,  55,
14,  13,  16,  24,  40,  57,  69,  56,
14,  17,  22,  29,  51,  87,  80,  62,
18,  22,  37,  56,  68,  109, 103, 77,
24,  35,  55,  64,  81,  104, 113, 92,
49,  64,  78,  87, 103,  121, 120, 101,
72,  92,  95,  98, 112,  100, 103,  99
};
unsigned char JPEG_StdQuantTblC[64] = 
{
17,  18,  24,  47,  99,  99,  99,  99, 
18,  21,  26,  66,  99,  99,  99,  99,
24,  26,  56,  99,  99,  99,  99,  99,
47,  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
};
// this table is used for regular-position to zigzagged-position lookup
static unsigned char zigzag[64] = 
{ 
0, 1, 5, 6,14,15,27,28,
2, 4, 7,13,16,26,29,42,
3, 8,12,17,25,30,41,43,
9,11,18,24,31,40,44,53,
10,19,23,32,39,45,52,54,
20,22,33,38,46,51,55,60,
21,34,37,47,50,56,59,61,
35,36,48,49,57,58,62,63 
};
The inspiration for this code came from a user named Cristi Cuturicu at the website http://www.wotsit.org who posted some jpeg encoder / decoder code. I don’t really know exactly where the aptina code is “broken”, and I’m not too motivated to find out.
Using this revised function produces a far cleaner image. Take a look at the attached jpeg.
It’s not perfect yet, but it’s a big step forward.