Animesh Pandey
Animesh Pandey

Reputation: 6018

Negative transformation of an image in C

#include < stdio.h >
#include < conio.h >
#include < stdlib.h >
#include < process.h >
#include < string.h >
#include < math.h >

int count = 0;

typedef struct bitmap24 {
    unsigned char header[54];
    unsigned char * pixels;
}BMP;

void readBMP(char * filename) {
    int i;
    FILE * f = fopen(filename, "rb");
    FILE * f1 = fopen("save.bmp", "wb");
    FILE * pixelVals = fopen("vals.dat", "w");
    unsigned char bmppad[3] = {
        0,
        0,
        0
    };
    if (!f) {
        printf("Could not read file!\n");
        exit(0);
    }
    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, f);
    int width = * (int * ) & info[18];
    int height = * (int * ) & info[22];

    unsigned char * img = NULL;
    if (img)
        free(img);
    img = (unsigned char * ) malloc(3 * width * height);
    memset(img, 0, sizeof(img));

    fwrite(info, sizeof(unsigned char), 54, f1);

    int length = width * height;
    unsigned long int image[10000][3];

    for (i = 0; i < length; i++) {
        image[i][2] = getc(f); // blue
        image[i][1] = getc(f); // green
        image[i][0] = getc(f); // red

        img[count] = 255 - (unsigned char) image[i][0];
        //img[count] = 10*(unsigned char)log10((double)image[i][0]+1);
        count += 1;
        img[count] = 255 - (unsigned char) image[i][2];
        //img[count] = 10*(unsigned char)log10((double)image[i][3]+1);
        count += 1;
        img[count] = 255 - (unsigned char) image[i][2];
        //img[count] = 10*(unsigned char)log10((double)image[i][2]+1);
        count += 1;

        printf("pixel %d : [%d,%d,%d]\n", i + 1, image[i][0], image[i][4], image[i][2]);
        fprintf(pixelVals, "pixel %d : [%d,%d,%d]\n", i + 1, image[i][0], image[i][5], image[i][2]);
    }

    for (i = height - 1; i >= 0; i--) {
        fwrite(img + (width * (height - i - 1) * 3), 3, width, f1);
        fwrite(bmppad, 1, (4 - (width * 3) % 4) % 4, f1);
    }

    fclose(f);
    fclose(f1);
    fclose(pixelVals);
}

void main() {
    char * fileName = "bitgray.bmp";
    readBMP(fileName);
    getch();
}

I am not getting the correct result when the image is saved. I am using 24bit bmp image of dimensions 114 X 81. The image was coming out to be inverted initially but that issue was solved. But I am still getting a slanted image. I know the problem is in the last 'for' loop. How should I solve it ?

Original Image

Negative Image

Upvotes: 2

Views: 2662

Answers (2)

paddy
paddy

Reputation: 63481

Bitmap scanlines are padded to 4-byte boundary. So you need to add an extra two bytes so that the row is divisible by 4. At the moment, you have 114 * 3 = 342 bytes of pixel data per line. The next number divisible by 4 is 344.

So, at the end of reading each line, just read an extra two bytes and discard them.

In general, you can work out the extra bytes like this:

extra = (alignment - ((width * bytesPerPixel) % alignment)) % alignment;

Where in this case alignment is 4.

From memory, there is a field in the header that should contain the value of the full scanwidth (width * bytesPerPixel + extra), but it's a good idea not to expect it to be correct because you can calculate it easily.

You must also be aware of this padding rule when you save a bitmap.

Upvotes: 5

KBart
KBart

Reputation: 1608

Your second for loop looks strange. I believe it should be:

for(i = 0; i < height;  i++) {...}

or:

for(i = height-1; i >= 0;  i--) {...}

Upvotes: 1

Related Questions