0

So I'm using the median cut algorithm (sample found here) which reads a .raw image into Points. The actual reading in is done here: Median Cut Algorithm

medianCutPoints = new QList< QList<int>* >();
FILE * raw_in;
int numPoints = 617*800;
Point* points = (Point*)malloc(sizeof(Point) * numPoints);
raw_in = fopen("C:\\Users\\David\\Desktop\\image.raw", "rb");
for(int i = 0; i < numPoints; i++)
{
    fread(&points[i], 3, 1, raw_in);
}
fclose(raw_in);

Then, the palette is generated via the algorithm..

std::list<Point> palette =
    medianCut(points, numPoints, 15);

and finally, I store the points into a list.

for (iter = palette.begin() ; iter != palette.end(); iter++)
{
    medianCutPoints->append(new QList<int>());
    medianCutPoints->last()->append((int)iter->x[0]);
    medianCutPoints->last()->append((int)iter->x[1]);
    medianCutPoints->last()->append((int)iter->x[2]);
}

However, this only seems to work for a .raw, as there's no compressing going on as in a jpeg or png. If I feed in a jpg/png, the colors are greatly off from what they should be. This essentially is leaving me to only two options I can think of - use jpg and png libraries to decode the image into a .raw, or somehow read in each pixel of a compressed image into Points.

I'm having trouble understanding how the first loop works. I'm used to C#.NET, so how exactly is fread working, and how is Point* points setup? If I print out points[width*height].x[0], I get a number from the RGB code. But if I also do points[0].x[width*height], I still get a number. I figured this would be points[numberOfpoints].x[0-2], x being 3 spots for RGB.

Is there a way I can set Point* points to each pixel from a jpg/png as fread is doing with a .raw? With Qt being my first real venture into c++, this is a bit more complex than what I can comprehend, and I haven't had much luck searching for how exactly this is working.

dajaffe
  • 855
  • 13
  • 34
  • Can you show us the Point class? That might make things more clear(especially the fread call). –  May 03 '12 at 02:27
  • @Ethan Steinberg I believe Point is just a standard class in c++, but I might be wrong.. I don't have it defined anywhere. – dajaffe May 03 '12 at 03:29

1 Answers1

2

If you're using the same algorithm to read from a png/jpg file, It will not work. png uses lossless compression while jpg uses lossy compression. The data within will be different from how the 'raw' image is set up. From looking at the algorithm above, 'raw' image is set up in RGB format. So, your fread is reading 3 bytes into every point. Point structure stores 3 values x[], which in this case corresponds to R(red), G(green), B(blue).

Note that, points is an array and hence contiguous in memory. Assuming you only have x[3] in Point structure and width*height doesn't overflow, points[0][width*height] will give you the value of points[(width*height)/3][(width*height)%3]. Essentially, the first and second subscript is added to the memory location of points.

For reading images using QT, you can try QImageReader. It supports many formats: http://doc.qt.io/archives/qt-4.7/qimagereader.html#supportedImageFormats

Christophe Weis
  • 2,518
  • 4
  • 28
  • 32
deebee
  • 1,747
  • 13
  • 14
  • Thanks for the explanation. So I'm assuming I'm going to either have to convert non-raw file formats into a raw format using a decompression via a 3rd party library that the current Median-cut can handle, or... re-write the Median-cut algorithm to handle an array of QRBGs or an array of ints (which I can manually populate via QImage.pixel())? Or.. what about just manually going through a QImage.pixel()'s and somehow "build" a .raw file to feed in? – dajaffe May 03 '12 at 03:33
  • I actually just figured it out. I plan on reading each pixel in a compressed image into an array of unsigned 8-bit ints, then read that into the Point array. I was able to test it out by generating a sample binary file of a few numbers in hex, then read it into the algorithm, and it seemed to work. – dajaffe May 04 '12 at 03:07