GP2X Vertical Line Problem


boogle

Still Fresh
Joined
Dec 20, 2005
Messages
32
I'm using Ryleh's Minimal Library v0.A, and after a day's worth of debugging think I have found a problem either with the library, or something silly I keep overlooking.

I'm loading a JPG, then converting it to 8bit palettized. I've created a simple greyscale palette, so the image should look as good as the original - only greyscale. The problem is, when it is displayed, the image has some white vertical lines through it. There is a slightly shaded area (appears white in photo) that appears to have greyish lines going through it. The lines are perfectly spaced across the entire image. Photo

After hours of trying to figure out what was going wrong - I decided to just save off the converted image and see exactly whats going wrong with the conversion. To my surprise, upon opening the file the image was 100% perfect (admitidly the first and last rows were swapped, probably due to the JPG decoding not being 100%).

So this has left me very, very confused. The image is fine, and the palette works fine when I do a test (gradiant going from black to white). Whats going on?

My code is quite simple:

Code:
	blitRect.x = 0;
	blitRect.y = 0;
	blitRect.w = britImg.width;
	blitRect.h = britImg.height;
	blitRect.data8 = (unsigned char*)britImg.data;
	blitRect.solid = 1;

...

gp2x_blitter_rect8(&blitRect);

I wrote my own blitter (old slow way) and it displayed exactly the same problem.
 
How are you converting it from a jpg to 8 bit palletized ?

The photo looks as if the row offset is wrong.
 
When outputting to a file, the file is accurate so the conversion appears to be working fine:

Code:
bool CImporter::Palettize24bit(ImageData_t &iData)
{
	unsigned int end = iData.width * iData.height;
	unsigned int i, index, error;
	unsigned char *ptr = iData.data;
	unsigned char* data = new unsigned char[end];

	for (i = 0; i < end; ++i)
	{
  index = 0;
  PaletteEntry(*(unsigned int*)ptr, index, error);
  data[i] = index;
  ptr += (iData.bpp / 8);
	}

	delete[] iData.data;
	iData.bpp = 8;
	iData.data = data;

	return true;
}

void CImporter::PaletteEntry(unsigned int color, unsigned int &entry, unsigned int &error)
{
	int i;
	unsigned int val;
	error = 0xFFFFFFFF;
	entry = 0;

	color &= 0xFFFFFF00;
	for (i = 0; i < 256; ++i)
	{
  val = MAX(color, m_palette[i]) - MIN(color, m_palette[i]);
  if (val < error)
  {
  	error = val;
  	entry = i;
  }
	}
}
 
I've found the problem, better late than never. Started playing about with it yesterday and found the solution - so here it is for anyone whose also puzzled:

The bad line is here: PaletteEntry(*(unsigned int*)ptr, index, error);

The pointer isn't increasing by 32bits each time, but instead 24bits meaning alignment is lost. This isn't a problem on x86 but it seems to be a problem on ARM (or maybe GCC doesn't like it, I really don't know). I found the solution to be reading in data a byte at a time and assembling the integer with binary shifting.

Code:
color = 0;
  color = iData.data[tracker] << 24;
  color += iData.data[tracker+1] << 16;
  color += iData.data[tracker+2] << 8;

Very crude code, but it illustrates the point :)
 
Back
Top