WarFox Posted January 4, 2021 Share Posted January 4, 2021 (edited) Feel free to ask questions about the code. It reads and writes BMP Files. The PixelProcessor can be used to manipulate pixels in the image. File format specification for reference: http://www.ece.ualberta.ca/~elliott/ee552/studentAppNotes/2003_w/misc/bmp_file_format/bmp_file_format.htm Note that the BMP file format is in binary. This processor targets 24 bit images with pixel data 4 byte aligned. So the fseek is going to round out each "row" by advancing the file pointer by an amount to keep the "row" size some multiple of 4. BmpProcessor.h Spoiler #include <stdio.h> #include "PixelProcessor.h" #ifndef BMP_HEADER #define BMP_HEADER typedef struct BMP_Header { char signature[2]; int file_size; short reserve1; short reserve2; int file_offset; } BMP_Header; typedef struct DIB_Header{ int DIB_size; int image_width; int image_height; short planes; short bits_per_pixel; int compression; int image_size; int x_pixels; int y_pixels; int colors; int important_colors; } DIB_Header; /** * read BMP header of a file. Useful for converting files from PPM to BMP. * * @param file: A pointer to the file being read or written * @param header: Pointer to the destination BMP header */ void readBMPHeader(FILE* file, struct BMP_Header* header); /** * write BMP header of a file. Useful for converting files from PPM to BMP. * * @param file: A pointer to the file being read or written * @param header: The header made by makeBMPHeader function */ void writeBMPHeader(FILE* file, struct BMP_Header* header); /** * read DIB header from a file. Useful for converting files from PPM to BMP. * * @param file: A pointer to the file being read or written * @param header: Pointer to the destination DIB header */ void readDIBHeader(FILE* file, struct DIB_Header* header); /** * write DIB header of a file. Useful for converting files from PPM to BMP. * * @param file: A pointer to the file being read or written * @param header: The header made by makeDIBHeader function */ void writeDIBHeader(FILE* file, struct DIB_Header* header); /** * make BMP header based on width and height. * The purpose of this is to create a new BMPHeader struct using the information * from a PPMHeader when converting from PPM to BMP. * * @param header: Pointer to the destination DIB header * @param width: Width of the image that this header is for * @param height: Height of the image that this header is for */ void makeBMPHeader(struct BMP_Header* header, int width, int height); /** * Makes new DIB header based on width and height. Useful for converting files from PPM to BMP. * * @param header: Pointer to the destination DIB header * @param width: Width of the image that this header is for * @param height: Height of the image that this header is for */ void makeDIBHeader(struct DIB_Header* header, int width, int height); /** * read Pixels from BMP file based on width and height. * * @param file: A pointer to the file being read or written * @param pArr: Pixel array of the image that this header is for * @param width: Width of the image that this header is for * @param height: Height of the image that this header is for */ void readPixelsBMP(FILE* file, struct Pixel** pArr, int width, int height); /** * write Pixels from BMP file based on width and height. * * @param file: A pointer to the file being read or written * @param pArr: Pixel array of the image that this header is for * @param width: Width of the image that this header is for * @param height: Height of the image that this header is for */ void writePixelsBMP(FILE* file, struct Pixel** pArr, int width, int height); #endif BmpProcessor.c Spoiler #include "BmpProcessor.h" #include "PixelProcessor.h" #include <stdio.h> #include <stdlib.h> #include <string.h> /** * read BMP header of a file. Useful for converting files from PPM to BMP. * * @param file: A pointer to the file being read or written * @param header: Pointer to the destination BMP header */ void readBMPHeader(FILE* file, struct BMP_Header* header) { fread(&header->signature, sizeof(char)*2, 1, file); fread(&header->file_size, sizeof(int), 1, file); fread(&header->reserve1, sizeof(short), 1, file); fread(&header->reserve2, sizeof(short), 1, file); fread(&header->file_offset, sizeof(int), 1, file); } /** * write BMP header of a file. Useful for converting files from PPM to BMP. * * @param file: A pointer to the file being read or written * @param header: The header made by makeBMPHeader function */ void writeBMPHeader(FILE* file, struct BMP_Header* header) { fwrite(&header->signature, sizeof(short), 1, file); fwrite(&header->file_size, sizeof(int), 1, file); fwrite(&header->reserve1, sizeof(short), 1, file); fwrite(&header->reserve2, sizeof(short), 1, file); fwrite(&header->file_offset, sizeof(int), 1, file); } /** * read DIB header from a file. Useful for converting files from PPM to BMP. * * @param file: A pointer to the file being read or written * @param header: Pointer to the destination DIB header */ void readDIBHeader(FILE* file, struct DIB_Header* header) { fread(&header->DIB_size, sizeof(int), 1, file); fread(&header->image_width, sizeof(int), 1, file); fread(&header->image_height, sizeof(int), 1, file); fread(&header->planes, sizeof(short), 1, file); fread(&header->bits_per_pixel, sizeof(short), 1, file); fread(&header->compression, sizeof(int), 1, file); fread(&header->image_size, sizeof(int), 1, file); fread(&header->x_pixels, sizeof(int), 1, file); fread(&header->y_pixels, sizeof(int), 1, file); fread(&header->colors, sizeof(int), 1, file); fread(&header->important_colors, sizeof(int), 1, file); } /** * write DIB header of a file. Useful for converting files from PPM to BMP. * * @param file: A pointer to the file being read or written * @param header: The header made by makeDIBHeader function */ void writeDIBHeader(FILE* file, struct DIB_Header* header) { fwrite(&header->DIB_size, sizeof(int), 1, file); fwrite(&header->image_width, sizeof(int), 1, file); fwrite(&header->image_height, sizeof(int), 1, file); fwrite(&header->planes, sizeof(short), 1, file); fwrite(&header->bits_per_pixel, sizeof(short), 1, file); fwrite(&header->compression, sizeof(int), 1, file); fwrite(&header->image_size, sizeof(int), 1, file); fwrite(&header->x_pixels, sizeof(int), 1, file); fwrite(&header->y_pixels, sizeof(int), 1, file); fwrite(&header->colors, sizeof(int), 1, file); fwrite(&header->important_colors, sizeof(int), 1, file); } /** * make BMP header based on width and height. * The purpose of this is to create a new BMPHeader struct using the information * from a PPMHeader when converting from PPM to BMP. * * @param header: Pointer to the destination DIB header * @param width: Width of the image that this header is for * @param height: Height of the image that this header is for */ void makeBMPHeader(struct BMP_Header* header, int width, int height) { header->signature[0] = 0x42; header->signature[1] = 0x4D; header->reserve1 = 0x00; header->reserve2 = 0x00; header->file_offset = 54; //int file_size = (14+40+(height*(width+(width%4)))); header->file_size = (54+(height*(width+(width%4)))*3); } /** * Makes new DIB header based on width and height. Useful for converting files from PPM to BMP. * * @param header: Pointer to the destination DIB header * @param width: Width of the image that this header is for * @param height: Height of the image that this header is for */ void makeDIBHeader(struct DIB_Header* header, int width, int height) { header->DIB_size = 40; header->image_width = width; header->image_height = height; header->planes = 1; header->bits_per_pixel = 24; header->compression = 0; header->image_size = height*(width+(width%4))*(3); header->x_pixels = 0; header->y_pixels = 0; header->colors = 0; header->important_colors = 0; } /** * read Pixels from BMP file based on width and height. * * @param file: A pointer to the file being read or written * @param pArr: Pixel array of the image that this header is for * @param width: Width of the image that this header is for * @param height: Height of the image that this header is for */ void readPixelsBMP(FILE* file, struct Pixel** pArr, int width, int height) { //pArr = (struct Pixel**) malloc(sizeof(struct Pixel*)*width); //for (int i = 0; i < width; i++) { // pArr = (struct Pixel*) malloc(sizeof(struct Pixel) * height); //} int padding_length = (width%4); //fread(&padding, sizeof(char), 1, file); for (int w = 0; w < width; w++) { for (int h = 0; h < height; h++) { unsigned char b,g,r; fread(&b, sizeof(unsigned char), 1, file); fread(&g, sizeof(unsigned char), 1, file); fread(&r, sizeof(unsigned char), 1, file); //printf("%d %d %d\n", b,g,r); pArr[w][h].b = b; pArr[w][h].g = g; pArr[w][h].r = r; if (h == height-1) { fseek(file, sizeof(char)*padding_length, SEEK_CUR); } } }} // b, g, r /** * write Pixels from BMP file based on width and height. * * @param file: A pointer to the file being read or written * @param pArr: Pixel array of the image that this header is for * @param width: Width of the image that this header is for * @param height: Height of the image that this header is for */void writePixelsBMP(FILE* file, struct Pixel** pArr, int width, int height) { int padding_length = width%4; for (int r = 0; r < width; r++) { for (int c = 0; c < height; c++) { //struct Pixel temp = pArr[r][c]; //printf("|%c |%c |%c|", temp.b, temp.g, temp.r); fwrite(&pArr[r][c].b, sizeof(char), 1, file); fwrite(&pArr[r][c].g, sizeof(char), 1, file); fwrite(&pArr[r][c].r, sizeof(char), 1, file); if (c == (height-1)) { fseek(file, sizeof(char)*padding_length, SEEK_CUR); } } } char end_of_file = 0x00; fwrite(&end_of_file, sizeof(char), 1, file);} PixelProcessor.h Spoiler #ifndef PIXEL_HEADER #define PIXEL_HEADER struct Pixel{ unsigned char r, b, g; }; /** * Shift color of Pixel array. The dimension of the array is width * height. The shift value of RGB is * rShift, gShift,bShift. Useful for color shift. * * @param pArr: Pixel array of the image that this header is for * @param width: Width of the image that this header is for * @param height: Height of the image that this header is for * @param rShift: the shift value of color r shift * @param gShift: the shift value of color g shift * @param bShift: the shift value of color b shift */ void colorShiftPixels(struct Pixel** pArr, int width, int height, int rShift, int gShift, int bShift); #endif PixelProcessor.c Spoiler #include <stdio.h> #include "PixelProcessor.h" void colorShiftPixels (struct Pixel** pArr, int width, int height, int rShift, int gShift, int bShift) { for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { pArr[i][j].r += rShift; pArr[i][j].b += bShift; pArr[i][j].g += gShift; } } } Edited January 4, 2021 by WarFox Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now