0

I am currently doing a project where I have to reduce a 24bpp picture to a 3bpp image using a 4x4 ordered dither matrix. However, after doing my dithering processing, my image is only showing up about 1/3 of the way. Does anyone know what I'm doing wrong?

Source:

#include <stdio.h>
#include <fstream>

/*24 bit per pixel - 3 bit per pixel dither*/
/*Use the 4x4 Ordered Dither Matrix:

    [1 9 3 11]
    [13 5 15 7]
    [4 12 2 10]
    [16 8 14 6]

*/
int checkColor(int a, int b);

unsigned char buf[512][512];
unsigned char out[512][512];
float ratio = 1.0 / 17;


int main(){

    FILE *fp, *output;
    int i, j, k, l;

    /*dither matrix*/
    unsigned int dith[4][4] = {{1, 9, 3, 11}, {13, 5, 15, 7}, {4, 12, 2, 10}, {16, 8, 14, 6}};


    if((fp = fopen("LennaRGB512.data", "rb")) == NULL){
        printf("error opening file\n");
    }

    for (i = 0; i < 512; i++) {
        for (j = 0; j < 512; j++) {
            buf[i][j] = fgetc(fp); /*Put data in buffer*/
        }
    }

    i = 0;
    j = 0;

    int x, y;
    int bd = 64;
    for (k = 0; k < 512; k++){
        for (l = 0; l < 512; l++){
            int oldPixel = buf[k][l];
            int value = (oldPixel + (ratio * dith[k%4][l%4]));

            int r = ((oldPixel >> 16) & 0xff) + value;
            int g = ((oldPixel >> 8) & 0xff) + value;
            int b = (oldPixel & 0xff) + value;

            int newPixel = 0x000000 | checkColor(r, bd) << 16 | checkColor(g, bd) << 8 | checkColor(b, bd);
            out[k][l] = newPixel;
        }
    }


    output = fopen("converted_img.data", "wb");

    for (i = 0; i < 512; i++){
        for (j = 0; j < 512; j++){
            fputc(out[i][j], output);
        }
    }

    fclose(output);
    fclose(fp);

    return 0;
}

int checkColor(int a, int b){
    return a / b * b;
}

My before image is a 512x512 image, however my output image which is dithered is only a portion of the image (512x170)

ks1322
  • 33,961
  • 14
  • 109
  • 164
s.gang
  • 131
  • 3
  • 14

1 Answers1

1

Your source image is 24bpp. This is three bytes per pixel. If you're only reading 512 bytes wide and 512 bytes tall, this exactly represents 512x170 (512/3) of your image. You need to read 3 bytes per pixel in the beginning.

Also, you're converting to 32bpp with int newPixel, not 3bpp but storing it in a char, which will overflow (truncate) the value.

Further, why is your dither pattern 4bpp? (2^4 = 16 values).

It seems your teacher didn't explain things well.

MarcD
  • 588
  • 3
  • 11
  • My teacher just told us to use a 4 * 4 ordered dither matrix. Also they did not teach us jack about color dithering, instead they showed us that we could dither by 1 or 0 in greyscale images. I'm literally working from nothing so I appreciate your help. – s.gang Oct 12 '16 at 22:22
  • See https://en.wikipedia.org/wiki/Ordered_dithering for some details of what the method does. There's a mistake in their psuedocode algorithm though, so don't use it. You'll want to make your buf array size 512x512x3 to hold each rgb triplet. Apply your dithering first, and then convert to 3bpp (which you'll need a palette or color map for). Please post your assignment verbatim so I know exactly what your teacher is asking for. – MarcD Oct 12 '16 at 22:49
  • I'm guessing that what your teacher means by 3bpp is one bit each for red, green, and blue. Otherwise it would suggest a palette with 8 colors. Knowing what he's asking for will help immensely. – MarcD Oct 12 '16 at 22:52
  • You need to quantize an 24-bit color image into just a 3 bit color image without Look Up Table. Transform a given 24 bit RGB Lena to 3bit per pixel without completely losing intensity (bit depth) of each color. Use 4X4 ordered dither matrix for this. Using an ordered 4x4 dither matrix, transform each 256 intensity of R,G, B of the 512 x 512 Lena color image in lena.data (given in the class webpage) to (16 + 1) differentintensity using 1 bit per channel 1 bit for R 1 bit for G 1 bit for B – s.gang Oct 12 '16 at 22:53
  • Also that is not my wording thats verbatim my teachers wording – s.gang Oct 12 '16 at 22:55
  • 1
    I think I know what he's asking. There's a very similar question on SO here : http://stackoverflow.com/questions/36087038/how-to-implement-24bit-to-3bit-ordered-dither-algorithm . To convert 888 RGB to 111 RGB you need to test whether the R, G, or B value is greater than or equal to 128. If so, set a 1 in the corresponding bit. I'm not sure how he wants you to store the corresponding 3 bits though. You should ask your teacher to clarify the assignment for you. He's left out some crucial details. – MarcD Oct 12 '16 at 23:08
  • So now I've used my teachers example code to get each stream, they use a 3 dimensional buffer [512][512][3] and loop through putting each in the r, g, b buffers at once by doing fputc[512][512][0]..... all in the same execution loop. So now I have 3 different arrays 512x512. However when I use the pseudocode on wiki (with my own color comparison function assinging 1 and 0 respectively) and then i write the r 512x512 into file however I literally have the same 512x170 block but now its all black. Im so beyond confused still. – s.gang Oct 13 '16 at 00:29
  • To test what your output looks like, assign 255 or 0 to each RGB component. – MarcD Oct 13 '16 at 00:47
  • The file output is .data aka just raw file data. I open that with gimp – s.gang Oct 13 '16 at 01:33
  • Yes but gimp is interpreting that as 24bpp RGB data. That's why you need to know what output file format your teacher wants. – MarcD Oct 13 '16 at 01:36
  • All we were told was to open our raw post-dithered data file with gimp. Here's a link to the specific assignment: http://eecs.csuohio.edu/~sschung/CIS465/LabAssignment3CIS465.pdf – s.gang Oct 13 '16 at 02:27
  • He hasn't given you enough information to properly complete the assignment. Right now it entirely depends on what gimp can read for an input data file. – MarcD Oct 13 '16 at 02:35
  • You should email your instructor and ask for clarification on what kind of output file he is expecting. – MarcD Oct 13 '16 at 02:37