Simple Read then Write .bmp File C code - c

I am trying to do a simple read of a .bmp file, and then output that same .bmp file. Right now, it only works if the width and height are the exact same. That's a good indicator of what my problem is, but I can't seem to figure it out. I'm looking for any ideas or suggestions y'all may have. There are other questions about this, but they seem not to be exactly what I'm looking for. However, my output when the width and height are different is similar to the output that is shown here Read/Write SImple BMP Image C++ - basically it's skewed, incomplete, and repetitive, not the actual image.
Here is the code where I read in the .bmp file:
bool LoadBmp(const char *filepath)
{
FILE *f = fopen(filepath, "rb");
if (f)
{
Bwidth = 0;
Bheight = 0;
pixels = NULL;
unsigned char info[54] = {0};
fread(info, sizeof(unsigned char), 54, f);
Bwidth = *(unsigned int *)&info[18];
Bheight = *(unsigned int *)&info[22];
unsigned int size = Bwidth * Bheight * 3; // ((((Bwidth * Bheight) + 31) & ~31) / 8) * Bheight;
pixels = malloc(size);
fread(pixels, sizeof(unsigned char), size, f);
fclose(f);
return true;
}
return false;
}
Note that I was unsure whether to create size how I do below (Bwidth * Bheight * 3) or use what is commented out. Also note that 'Bwidth' and 'Bheight' are declared as unsigned int, whereas 'pixels' is defined as unsigned char*. Additionally, I purposely am not using a struct to store .bmp file data.
Here is the code that I use to write the .bmp file that I just loaded:
static bool WriteBMP(int x, int y, unsigned char *bmp, char * name)
{
const unsigned char bmphdr[54] = {66, 77, 255, 255, 255, 255, 0, 0, 0, 0, 54, 4, 0, 0, 40, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, 8, 0, 0, 0, 0, 0, 255, 255, 255, 255, 196, 14, 0, 0, 196, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char hdr[1078];
int i, j, c, xcorr, diff;
FILE *f;
xcorr = (x+3) >> 2 << 2; // BMPs have to be a multiple of 4 pixels wide.
diff = xcorr - x;
for (i = 0; i < 54; i++) hdr[i] = bmphdr[i];
*((int*)(&hdr[18])) = xcorr;
*((int*)(&hdr[22])) = y;
*((int*)(&hdr[34])) = xcorr*y;
*((int*)(&hdr[2])) = xcorr*y + 1078;
for (i = 0; i < 256; i++) {
j = i*4 + 54;
hdr[j+0] = i; // blue
hdr[j+1] = i; // green
hdr[j+2] = i; // red
hdr[j+3] = 0; // dummy
}
f = fopen(name, "wb");
if (f) {
assert(f != NULL);
c = fwrite(hdr, 1, 1078, f);
assert(c == 1078);
if (diff == 0) {
c = fwrite(bmp, 1, x*y, f);
assert(c == x*y);
} else {
*((int*)(&hdr[0])) = 0; // need up to three zero bytes
for (j = 0; j < y; j++) {
c = fwrite(&bmp[j * x], 1, x, f);
assert(c == x);
c = fwrite(hdr, 1, diff, f);
assert(c == diff);
}
}
fclose(f);
return true;
}
else return false;
}
Thanks in advance for your help. I appreciate your time!

Related

.BMP files in C - DIB header returns image size 0 even though the BMP header returns the file size

I'm trying to flip a BMP image in C.
I ran into a problem where when I try to read the BMP header everything is alright and the values are correct, but when I try to read the DIB header I get all of the values right except for the image size (raw bitmap data). I get a zero, which is really weird considering I got the file size in the BMP header. I tried debugging the code and looking up the problem online but that didn't help much.
This is my code:
#include <stdlib.h>
typedef unsigned int int32;
typedef unsigned short int int16;
typedef unsigned char char8;
struct BITMAP_header {
char name[2]; // BM
int32 size;
int garbage; // ?
int32 image_offset; //offset from where the image starts in the file
};
struct DIB_header {
int32 header_size;
int32 width;
int32 height;
int16 colorplanes;
int16 bitsperpixel;
int32 compression;
int32 image_size;
int32 temp[4];
};
struct RGB
{
char8 blue;
char8 green;
char8 red;
};
struct Image {
struct RGB** rgb;
int height;
int width;
};
struct Image readImage(FILE *fp, int height, int width) {
struct Image pic;
pic.rgb = (struct RGB**)malloc(height * sizeof(void*)); // pointer to a row of rgb data (pixels)
pic.height = height;
pic.width = width;
for (int i = height-1; i >=0 ; i--)
{
pic.rgb[i] = (struct RGB*)malloc(width * sizeof(struct RGB)); // allocating a row of pixels
fread(pic.rgb[i], width, sizeof(struct RGB), fp);
}
return pic;
}
void freeImage(struct Image pic) {
for (int i = pic.height -1; i>= 0; i--)
{
free(pic.rgb[i]);
}
free(pic.rgb);
}
void createImage(struct BITMAP_header header, struct DIB_header dibheader, struct Image pic) {
FILE* fpw = fopen("new.bmp", "w");
if (fpw == NULL) {
return 1;
}
fwrite(header.name, 2, 1, fpw);
fwrite(&header.size, 3 * sizeof(int), 1, fpw);
fwrite(&dibheader, sizeof(struct DIB_header), 1, fpw);
int count = 0;
for (int i = pic.height - 1; i >= 0; i--) {
fwrite(pic.rgb[count], pic.width, sizeof(struct RGB), fpw);
count++;
}
fclose(fpw);
}
int openbmpfile() {
FILE* fp = fopen("C:\\Users\\User\\Downloads\\MARBLES.BMP", "rb"); // read binary
if (fp == NULL) {
return 1;
}
struct BITMAP_header header;
struct DIB_header dibheader;
fread(header.name, 2, 1, fp); //BM
fread(&header.size, 3 * sizeof(int), 1, fp); // 12 bytes
printf("First two characters: %c%c\n", header.name[0], header.name[1]);
if ((header.name[0] != 'B') || (header.name[1] != 'M')) {
fclose(fp);
return 1;
}
printf("Size: %d\n", header.size);
printf("Offset: %d\n", header.image_offset);
fread(&dibheader.header_size, sizeof(struct DIB_header) , 1, fp);
printf("Header size: %d\nWidth: %d\nHeight: %d\nColor planes: %d\nBits per pixel: %d\nCompression: %d\nImage size: %d\n",
dibheader.header_size, dibheader.width, dibheader.height, dibheader.colorplanes, dibheader.bitsperpixel,
dibheader.compression, dibheader.image_size);
if ((dibheader.header_size != 40) || (dibheader.compression != 0) || (dibheader.bitsperpixel != 24)) {
fclose(fp);
return 1;
}
fseek(fp, header.image_offset, SEEK_SET);
struct Image image = readImage(fp, dibheader.height, dibheader.width);
createImage(header, dibheader, image);
fclose(fp);
freeImage(image);
return 0;
}
int main() {
openbmpfile();
}
I also tried writing the size manually by decreasing the header size by the file size but it didn't work.
thanks in advance!
The format expect the structure size to be 14 and 40 for BITMAP_header and DIB_header. But the compiler aligns the structure and the size will be different. You have to use compiler specific flags to disable structure alignment (it's unclear which compiler you use). It's the same problem with RGB structure.
There is also endian-ness dependence, and the fact that bitmap doesn't store pixels in RGB format, it flips the bytes.
typedef unsigned int int32;
This will hide unsigned as signed. Some of the values in the structure are supposed to be signed. For example, height could be negative, indicating that it's supposed to be flipped.
You can read the integers one by one, using
void readint(FILE *f, int *val, int size)
{
unsigned char buf[4];
fread(buf, size, 1, f);
*val = 0;
for (int i = size - 1; i >= 0; i--)
*val += (buf[i] << (8 * i));
}
void writeint(FILE* f, int val, int size)
{
unsigned char buf[4];
for (int i = size - 1; i >= 0; i--)
buf[i] = (val >> 8 * i) & 0xff;
fwrite(buf, size, 1, f);
}
Then you read a 24-bit bitmap as follows:
fread(header.name, 2, 1, fp); //BM
readint(fp, &header.size, 4);
readint(fp, &header.garbage, 4);
readint(fp, &header.image_offset, 4);
readint(fp, &dibheader.header_size, 4);
readint(fp, &dibheader.width, 4);
readint(fp, &dibheader.height, 4);
readint(fp, &dibheader.colorplanes, 2);
readint(fp, &dibheader.bitsperpixel, 2);
readint(fp, &dibheader.compression, 4);
readint(fp, &dibheader.image_size, 4);
readint(fp, &dibheader.temp[0], 4);
readint(fp, &dibheader.temp[1], 4);
readint(fp, &dibheader.temp[2], 4);
readint(fp, &dibheader.temp[3], 4);
char *buf = malloc(dibheader.image_size);
if (!buf)
return 0;
fread(buf, 1, dibheader.image_size, fp);
There are other issues you have to consider, for example width alignment of bitmap, etc. You want to start with a 24-bit bitmap whose width is multiple of 4.
To write the bitmap, use the binary flag, write in the same order
FILE* fout = fopen("new.bmp", "wb");
if (fout == NULL) return 0;
fwrite(header.name, 1, 2, fout);
writeint(fout, header.size, 4);
writeint(fout, header.reserved, 4);
writeint(fout, header.image_offset, 4);
writeint(fout, info.header_size, 4);
writeint(fout, info.width, 4);
writeint(fout, info.height, 4);
writeint(fout, info.colorplanes, 2);
writeint(fout, info.bitsperpixel, 2);
writeint(fout, info.compression, 4);
writeint(fout, info.image_size, 4);
writeint(fout, info.temp[0], 4);
writeint(fout, info.temp[1], 4);
writeint(fout, info.temp[2], 4);
writeint(fout, info.temp[3], 4);
fwrite(buf, 1, info.image_size, fout);

How to fix ' Error: invalid read of size 4'

I'm trying to learn C and am completing different challenges in order to learn faster. The code seems logical to me and should progress. However, I'm getting an invalid read of size four on line 29
I've tried to change the data type that gets parsed through, but it didn't seem to work.
#include <unistd.h>
typedef struct s_grid
{
int x;
int y;
} t_grid;
void set_point(t_grid *coord, int i, int j)
{
coord->x = i;
coord->y = j;
}
//check loccation of next zero
int where_is_zero(int **sudoku)
{
int x;
int y;
t_grid coord;
x = 0;
y = 0;
while (x < 9)
{
y = 0;
while (y < 9)
{
if (sudoku[x][y] == 0) //Here I'm getting the error.
{
set_point(&coord, x, y);
return (0);
}
x++;
}
y++;
}
return (1);
}
int solve_sudoku(int **grid)
{
int row;
int col;
int num;
t_grid coord;
if (where_is_zero(grid) == 1)
return (1);
row = coord.x;
col = coord.y;
//where_is_zero(grid);
num = 1;
while (num <= 9)
{
if (check_number(grid, row, col, num) == 1)
{
grid[row][col] = num;
if (solve_sudoku(grid) == 1)
return (1);
grid[row][col] = 0;
}
num++;
}
return (0);
}
void ft_putchar(char c)
{
write(1, &c, 1);
}
void ft_putstr(char *str)
{
while (*str != '\0')
{
ft_putchar(*str);
str++;
}
}
//my main function
int main(int argc, char **argv)
{
int board[9][9] ={ { 0, 9, 0, 0, 0, 0, 8, 5, 3 },
{ 0, 0, 0, 8, 0, 0, 0, 0, 4 },
{ 0, 0, 8, 2, 0, 3, 0, 6, 9 },
{ 5, 7, 4, 0, 0, 2, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 9, 0, 0, 6, 3, 7 },
{ 9, 4, 0, 1, 0, 8, 5, 0, 0 },
{ 7, 0, 0, 0, 0, 6, 0, 0, 0 },
{ 6, 8, 2, 0, 0, 0, 0, 9, 0 } };
solve_sudoku(board);
return (0);
}
I removed some code just to highlight where the problem is. It should find the next 0 in the table and set the coordinations to my structure.
The problem lies in how you have the loop set up. See my comments below:
while (x < 9)
{
y = 0;
while (y < 9)
{
if (sudoku[x][y] == 0) //Here I'm getting the error.
{
set_point(&coord, x, y);
return (0);
}
x++; // This increments the x index while you're inside the y loop
}
y++; // This increments the y index when you meant to increment the x
}
If you swap both lines, that should work fine and will resolve your out-of-bounds error.
What would also help you write this better is instead of using a while loop, use a for loop. If you haven't covered that topic yet, it's really straightforward:
for(int x = 0; x < 9 ; ++x)
{
for (int y = 0; y < 9; ++y)
{
if (sudoku[x][y] == 0) //Here you won't get the error anymore!
{
set_point(&coord, x, y);
return (0);
}
}
}
What the for loop line means there is this: Start the loop by setting it to 0, at the end of an iteration, increment it. On the next iteration, check if x is still less than 9. If so, proceed with the next iteration.
Your problem is due to mixing types. In main() you declare:
int board[9][9] = { ....
You then pass:
solve_sudoku(board);
board has the type int (*)[9] (a pointer to array of int [9]). See C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3). Your solve_soduku expects a parameter of type int** (pointer to pointer to int).
int solve_sudoku(int **grid) { ...
The type are NOT compatible. (and your compiler should be screaming warnings at you)
board is a pointer to array of int [9], while grid is a pointer to pointer to int. You must make the types compatible. The easiest way is to change solve_sudoku to
int solve_sudoku(int (*grid)[9]) { ...
Otherwise you will need to declare board as int** and allocate and fill in main().

Reading binary signed short issue in C

I am learning C as a hobbyist. As a fun project I decided to code a .hgt file reader. hgt file are earth elevation files.
I found few information on this file format : https://dds.cr.usgs.gov/srtm/version2_1/Documentation/Quickstart.pdf
You can find files for the whole planet here :
http://viewfinderpanoramas.org/Coverage%20map%20viewfinderpanoramas_org3.htm
but it seems to be pretty straight forward : a list of signed two bytes integers they say.
I found that two bytes integers are well represented by "signed short" type, is that right ? In my code , you will see I used int_16t ( I tried that when having issues with signed shorts) I believe they have the same range )
Anyway, I open the file , dump the data in an array, and write it to a bmp file.
At first I thought it worked great, but that was because I was viewing the result of a very low elevation part of the earth. When I tried to render some files corresponding to areas with mountains, the image below shows the issue.
Below is my code so far.
I was pretty sure the issue is at the beginning, when reading the data, but I don't know anymore.
I would love some help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdint.h>
#include <math.h>
int main(int argc, char *argv[]) {
if(argc < 2) {
printf("I need a hgt file path as a paramater\n");
return 0;
} else {
const int DIM = 1201;
FILE *fp;
int16_t *elevation_buffer;
elevation_buffer = malloc(sizeof(int16_t) * DIM * DIM); // 2 bytes integers
fp = fopen(argv[1], "rb");
/* Seek to the beginning of the file */
fseek(fp, 0, SEEK_SET);
/* read elevation data from HGT file */
fread(elevation_buffer, sizeof(int16_t), DIM*DIM, fp);
fclose(fp);
printf("sizeof signed short int : %d\n", sizeof(signed short int));
printf("sizeof int16_t : %d\n", sizeof(int16_t));
/* creating a bmp file to visualize elevation tile*/
int w = DIM;
int h = DIM;
int x,y,r,g,b;
FILE *f;
unsigned char *img = NULL;
int filesize = 54 + 3 * w * h; //w is your image width, h is image height, both int
img = (unsigned char *)malloc(3 * w * h);
memset(img, 0, 3 * w * h);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
x = i;
y = (h - 1) - j;
float elevation = (elevation_buffer[x + y * w] - INT16_MIN) / (float)(INT16_MAX - INT16_MIN);
r = (int)(elevation * 255);
float freq = 100.0f;
if (r > 255) {
r = 255;
} else if(r < 0) {
r = 0;
}
g = r;
b = r;
img[(x + y * w) * 3 + 2] = (unsigned char)(r);
img[(x + y * w) * 3 + 1] = (unsigned char)(g);
img[(x + y * w) * 3 + 0] = (unsigned char)(b);
}
}
unsigned char bmpfileheader[14] = {'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0};
unsigned char bmpinfoheader[40] = {40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0};
unsigned char bmppad[3] = {0, 0, 0};
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
bmpinfoheader[4] = (unsigned char)(w);
bmpinfoheader[5] = (unsigned char)(w >> 8);
bmpinfoheader[6] = (unsigned char)(w >> 16);
bmpinfoheader[7] = (unsigned char)(w >> 24);
bmpinfoheader[8] = (unsigned char)(h);
bmpinfoheader[9] = (unsigned char)(h >> 8);
bmpinfoheader[10] = (unsigned char)(h >> 16);
bmpinfoheader[11] = (unsigned char)(h >> 24);
f = fopen("img.bmp", "wb");
fwrite(bmpfileheader, 1, 14, f);
fwrite(bmpinfoheader, 1, 40, f);
for (int i = 0; i < h; i++)
{
fwrite(img + (w * (h - i - 1) * 3), 3, w, f);
fwrite(bmppad, 1, (4 - (w * 3) % 4) % 4, f);
}
free(img);
free(elevation_buffer);
fclose(f);
return 0;
}
}
You should account for the byte order... your input file format is specified to contain bytes in big endian byte order.
As a simple fix, you could just check your byteorder and reverse the read in data as necessary. The answer https://stackoverflow.com/a/8571139/5265292 explains a way how to detect byte order on your system.
// ...
fread(elevation_buffer, sizeof(int16_t), DIM*DIM, fp);
fclose(fp);
int byteOrderCheck = 1;
if (*(char *)&byteOrderCheck == 1)
{
// need to revert byte order for little endian
for (int i = 0; i < DIM*DIM; ++i)
{
elevation_buffer[i] = (int16_t)reverse_byte_order((uint16_t)elevation_buffer[i]);
}
}
// ...
with function reverse_byte_order as
uint16_t reverse_byte_order(uint16_t num)
{
return ((num & 0xff) << 8) | (num >> 8);
}
Note this is untested, you may need to change some details.

Read color bytes (RGB) from a bitmap

I'm having a problem with a code that I made that should display the bytes of the RGB color values of each pixel of an image in bmp (bitmap) format.
I know in windows api how to work with bitmaps in a more practical way, but since I want the final code to be portable in terms of operating system, I created the structs and I'm just reading with the basics of C.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
unsigned char *readBMP(char *filename, int *size) {
int width, height;
unsigned char *data;
unsigned char info[54];
FILE *file = fopen(filename, "rb");
if (file == NULL)
return 0;
fread(info, sizeof(unsigned char), 54, file); // read the 54-byte header
// extract image height and width from header
width = *(int *) &info[18];
height = *(int *) &info[22];
*size = 3 * width * height;
data = (unsigned char *) malloc(*size * sizeof(unsigned char)); // allocate 3 bytes per pixel
fread(data, sizeof(unsigned char), (size_t) *size, file); // read the rest of the data at once
for (int i = 0; i < *size; i += 3) {
unsigned char tmp = data[i];
data[i] = data[i + 2];
data[i + 2] = tmp;
}
fclose(file);
return data;
}
int main() {
int size = 0;
char filename[] = "output.bmp";
unsigned char *data = readBMP(filename, &size);
for (int i = 0; i < size; i++) {
printf("%d. %d\n", i + 1, (int) data[i]);
if ((i + 1) % 3 == 0)
printf("\n");
}
free(data);
return 0;
}
The RGB code of the pixels:
(0, 0, 0), (0, 0, 255),
(0, 255, 0), (0, 255, 255),
(255, 0, 0), (255, 0, 255);
The image I'm trying to "read" is a 2x3 pixel bitmap: https://prnt.sc/gnygch
And the output I have is:
1. 255
2. 0
3. 0
4. 255
5. 0
6. 255
7. 0
8. 0
9. 0
10. 255
11. 0
12. 255
13. 0
14. 0
15. 255
16. 0
17. 0
18. 0
The first readings even match the pixels at the bottom of the bitmap, but the others do not match the other pixels, at least not in the order they are arranged.
Can anyone see what I'm doing wrong?
The size of the bitmap is not width * height * 3. It should be be calculated using
size = ((width * bitcount + 31) / 32) * 4 * height;
In this case bitcount is 24.
The rows in 24-bit bitmaps have to be padded. You also need to make sure you are reading a 24-bit bitmaps. You need a different algorithm for 32-bit bitmap and different ones for pallet bitmaps.
The rows are read from bottom to top.
Below is an example for 24-bit.
You may still run in to other problems with this code. It's better to use a library for these functions. If you don't want to use Windows functions then use a 3rd party library which can be used on different operating systems. There are many such libraries out there.
int main()
{
int width, height, padding, bitcount, size;
unsigned char *data = 0;
unsigned char info[54] = { 0 };
FILE *file = fopen("output.bmp", "rb");
if(!file)
return 0;
fread(info, 1, 54, file);
width = *(int*)(info + 18);
height = *(int*)(info + 22);
bitcount = *(int*)(info + 28);
size = ((width * bitcount + 31) / 32) * 4 * height;
padding = width % 4;
if(bitcount != 24) //this code works for 24-bit bitmap only
goto error;
data = malloc(size);
fread(data, 1, size, file);
for(int row = height - 1; row >= 0; row--)
{
for(int col = 0; col < width; col++)
{
int p = (row * width + col) * 3 + row * padding;
printf("%02X%02X%02X ", data[p + 0], data[p + 1], data[p + 2]);
}
printf("\n");
}
error:
if(file) fclose(file);
if(data) free(data);
return 0;
}

Image compression using Huffman Coding

I have some difficulties in my project. I got the RGB values from a 256x256 BMP image. However, I don't know how to continue by using the huffman coding to compress those RGB value.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*-------PROTOTYPES-------*/
long getImageInfo(FILE*, long, int);
void copyImageInfo(FILE* inputFile, FILE* outputFile);
void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors);
//void bmpsave (FILE*, unsigned char , int , int );
/*------STRUCTURES--------*/
typedef struct {int rows; int cols; unsigned char* data;} sImage;
int main(int argc, char* argv[])
{
FILE *bmpInput, *rasterOutput, *bmpOutput,*RedText,*GreenText,*BlueText,*ErrorRedText,*ErrorBlueText,*ErrorGreenText;
FILE *entroGreen,*entroBlue,*entroRed;
sImage originalImage;
unsigned char someChar;
unsigned char *pChar;
long fileSize;
int vectorSize, nColors;
int totalGCount=0, totalBCount=0,totalRCount=0;
int r, c, i,j,k=0;
int redValue, greenValue, blueValue;
int dummyRed=0 ,dummyGreen=0, dummyBlue=0;
int count[256] = {0},countRed[256]= {0},countBlue[256]= {0},countGreen[256]= {0};
double EntropyGreen, EntropyBlue, EntropyRed;
//int error[414720];
//int Red[400][720];
//int Green[400][720];
//int Blue[400][720];
unsigned int uint1;
short word1;
unsigned char byte1, byte2;
FILE *imdata;
int **errorGreen;
int **errorRed;
int **errorBlue;
int **Red;
int **Blue;
int **Green;
int **b;
b = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
b[i] = malloc ( 256 * sizeof (int) );
errorGreen = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
errorGreen[i] = malloc ( 256 * sizeof (int) );
errorRed = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
errorRed[i] = malloc ( 256 * sizeof (int) );
errorBlue = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
errorBlue[i] = malloc ( 256 * sizeof (int) );
//error = (int *) malloc ( 414720 * sizeof (int) ); //Dynamic Memmory Allocation of 1D Array
Red = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
Red[i] = malloc ( 256 * sizeof (int) );
Green = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
Green[i] = malloc ( 256 * sizeof (int) );
Blue = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
Blue[i] = malloc ( 256 * sizeof (int) );
/*--------INITIALIZE POINTER----------*/
someChar = '0';
pChar = &someChar;
if(argc < 2)
{
printf("Usage: %s bmpInput.bmp\n", argv[0]);
exit(0);
}
printf("Reading file %s\n", "Kirschen_256.bmp");
/*----DECLARE INPUT AND OUTPUT FILES----*/
bmpInput = fopen("Kirschen_256.bmp", "rb");
/*RedText = fopen("Red.txt", "w");
BlueText = fopen("Blue.txt", "w");
GreenText = fopen("Green.txt", "w");*/
entroGreen = fopen("entroGreen.txt", "w");
entroRed = fopen("entroRed.txt", "w");
entroBlue = fopen("entroBlue.txt", "w");
ErrorRedText = fopen("ErrorRed.txt", "w");
ErrorBlueText = fopen("ErrorBlue.txt", "w");
ErrorGreenText = fopen("ErrorGreen.txt", "w");
rasterOutput = fopen("Kirschen_256.txt", "w");
bmpOutput = fopen("Kirschen_256().bmp", "wb");
fseek(bmpInput , 0L , SEEK_END);
//fseek is a C function belonging to the ANSI C standard library,
//and included in the file stdio.h. Its purpose is to change the file position indicator for the specified stream.
/*-----GET BMP DATA-----*/
originalImage.cols = (int)getImageInfo(bmpInput, 18, 4);
originalImage.rows = (int)getImageInfo(bmpInput, 22, 4);
fileSize = getImageInfo(bmpInput, 2, 4);
nColors = getImageInfo(bmpInput, 46, 4);
//vectorSize = fileSize - (14 + 40 + 4*nColors);
/*----PRINT DATA TO SCREEN-----*/
printf("Width: %d\n", originalImage.cols);
printf("Height: %d\n", originalImage.rows);
printf("File size: %ld\n", fileSize);
printf("Bits/pixel: %d\n", getImageInfo(bmpInput, 28, 4));
printf("No. colors: %d\n", nColors);
//printf("Vector size: %d\n", vectorSize);
copyImageInfo(bmpInput, bmpOutput);
//copyColorTable(bmpInput, bmpOutput, nColors);
/*----FOR 24-BIT BMP, THERE IS NO COLOR TABLE-----*/
fseek(bmpInput , 54 , SEEK_SET);
fseek(bmpOutput , 54 , SEEK_SET);
/*-----------READ RASTER DATA-----------*/
for(r=0; r<=originalImage.rows-1; r++)
{
for(c=0; c<=originalImage.cols-1; c++)
{
/*----READ FIRST BYTE TO GET BLUE VALUE-----*/
fread(pChar, sizeof(char), 1, bmpInput);
blueValue = *pChar;
Blue[r][c]=*pChar;
if (r==0||c==0){
errorBlue[r][c]=abs(dummyBlue-blueValue);
countBlue[abs(dummyBlue-blueValue)]++;
count[abs(dummyBlue-blueValue)]++;
totalBCount++;
}
else{
errorBlue[r][c]=abs(((dummyBlue+Blue[r-1][c]+Blue[r-1][c-1])/3)-blueValue);
countBlue[abs(((dummyBlue+Blue[r-1][c]+Blue[r-1][c-1])/3)-blueValue)]++;
count[abs(((dummyBlue+Blue[r-1][c]+Blue[r-1][c-1])/3)-blueValue)]++;
totalBCount++;
}
//error[k]=abs(dummyBlue-blueValue);
//k++;
*pChar=dummyBlue;
fwrite(pChar, sizeof(char), 1, bmpOutput);
dummyBlue=blueValue;
/*-----READ NEXT BYTE TO GET GREEN VALUE-----*/
fread(pChar, sizeof(char), 1, bmpInput);
greenValue = *pChar;
Green[r][c]=*pChar;
if (r==0||c==0){
errorGreen[r][c]=abs(dummyGreen-greenValue);
countGreen[abs(dummyGreen-greenValue)]++;
count[abs(dummyGreen-greenValue)]++;
totalGCount++;
}
else{
errorGreen[r][c]=abs(((dummyGreen+Green[r-1][c]+Green[r-1][c-1])/3)-greenValue);
countGreen[abs(((dummyGreen+Green[r-1][c]+Green[r-1][c-1])/3)-greenValue)]++;
count[abs(((dummyGreen+Green[r-1][c]+Green[r-1][c-1])/3)-greenValue)]++;
totalGCount++;
}
*pChar=dummyGreen;
fwrite(pChar, sizeof(char), 1, bmpOutput);
dummyGreen=greenValue;
/*-----READ NEXT BYTE TO GET RED VALUE-----*/
fread(pChar, sizeof(char), 1, bmpInput);
redValue = *pChar;
Red[r][c]=*pChar;
if (r==0||c==0){
errorRed[r][c]=abs(dummyRed-redValue);
countRed[abs(dummyRed-redValue)]++;
count[abs(dummyRed-redValue)]++;
totalRCount++;
}
else{
errorRed[r][c]=abs(((dummyRed+Red[r-1][c]+Red[r-1][c-1])/3)-redValue);
countRed[abs(((dummyRed+Red[r-1][c]+Red[r-1][c-1])/3)-redValue)]++;
count[abs(((dummyRed+Red[r-1][c]+Red[r-1][c-1])/3)-redValue)]++;
totalRCount++;
}
*pChar=dummyRed;
fwrite(pChar, sizeof(char), 1, bmpOutput);
dummyRed=redValue;
/*---------PRINT TO TEXT FILE---------*/
fprintf(rasterOutput, "(%d %d) = \tRed \t%d", r, c, redValue);
fprintf(rasterOutput, "\tGreen \t%d \tBlue \t%d\n", greenValue, blueValue);
/*-----read data, reflect and write to output file----*/
//fseek(bmpOutput, 54 , SEEK_SET);
//fwrite(pChar, sizeof(char), 1, bmpOutput);
}
}
for (j=0; j<256; j++) {
for (i=255; i>=0; i--) {
if(i>=256-(count[j]/16))
b[i][j] = 0x00;
else
b[i][j] = 0xFF;
}
}
imdata = fopen("Kirschen_256after4", "wb");
/* if (imdata == NULL) {
printf("%s open error.\n", imname); exit(0);
}
*/
byte1 = 'B'; byte2 = 'M';
fwrite(&byte1, 1, 1, imdata); fwrite(&byte2, 1, 1, imdata);
uint1 = 54 + 4*256 + originalImage.cols*originalImage.rows; fwrite(&uint1, 4, 1, imdata);
word1 = 0; fwrite(&word1, 2, 1, imdata); fwrite(&word1, 2, 1, imdata);
uint1 = 54 + 4*256; fwrite(&uint1, 4, 1, imdata);
uint1 = 40; fwrite(&uint1, 4, 1, imdata);
fwrite(&originalImage.cols, 4, 1, imdata); fwrite(&originalImage.rows, 4, 1, imdata);
word1 = 1; fwrite(&word1, 2, 1, imdata);
word1 = 8; fwrite(&word1, 2, 1, imdata);
uint1 = 0; fwrite(&uint1, 4, 1, imdata);
uint1 = originalImage.cols*originalImage.rows; fwrite(&uint1, 4, 1, imdata);
j = 11811; fwrite(&j, 4, 1, imdata); fwrite(&j, 4, 1, imdata);
uint1 = 256; fwrite(&uint1, 4, 1, imdata);
uint1 = 0; fwrite(&uint1, 4, 1, imdata);
for (i=0; i<256; i++) {
byte1 = i;
fwrite(&byte1, 1, 1, imdata); fwrite(&byte1, 1, 1, imdata);
fwrite(&byte1, 1, 1, imdata); fwrite(&byte1, 1, 1, imdata);
}
for (i=originalImage.rows-1; i>=0; i--) {
for (j=0; j<originalImage.cols; j++) {
fwrite(&b[i][j], 1, 1, imdata);
}
}
fclose(imdata);
for (i=0; i<256; i++) {
if (countGreen[i]==0)
EntropyGreen += 0;
else
EntropyGreen += ((double)countGreen[i]/(double)totalGCount) * (log2 ((double)1/((double)countGreen[i]/(double)totalGCount)));
if (countRed[i]==0)
EntropyRed += 0;
else
EntropyRed += ((double)countRed[i]/(double)totalRCount) * (log2 ((double)1/((double)countRed[i]/(double)totalRCount)));
if (countBlue[i]==0)
EntropyBlue +=0;
else
EntropyBlue += ((double)countBlue[i]/(double)totalBCount) * (log2 ((double)1/((double)countBlue[i]/(double)totalBCount)));
}
fprintf(entroGreen, "Entropy= %f", EntropyGreen);
fprintf(entroRed, "Entropy= %f", EntropyRed);
fprintf(entroBlue, "Entropy= %f", EntropyBlue);
for (i = 0; i < 256; i++) {
for (j = 0; j < 256; j++) {
fprintf(ErrorRedText, "[%d][%d] = %2d\n", i, j, errorRed[i][j]);
fprintf(ErrorGreenText, "[%d][%d] = %2d\n", i, j, errorGreen[i][j]);
fprintf(ErrorBlueText, "[%d][%d] = %2d\n", i, j, errorBlue[i][j]);
fprintf (ErrorRedText,"\n");
fprintf (ErrorBlueText,"\n");
fprintf (ErrorGreenText,"\n");
}
}
/*for (i = 0; i < 768; i++) {
for (j = 0; j < 1024; j++) {
fprintf(RedText, "a[%d][%d] = %2d\n", i, j, Red[i][j]);
fprintf(GreenText, "a[%d][%d] = %2d\n", i, j, Green[i][j]);
fprintf(BlueText, "a[%d][%d] = %2d\n", i, j, Blue[i][j]);
}
fprintf (RedText,"\n");
fprintf (BlueText,"\n");
fprintf (GreenText,"\n");
}*/
/*for (i = 0; i < 414720; i++){
fprintf(ErrorText, "error[%d] = %d\n",i,error[i]);
fprintf (ErrorText,"\n");
}*/
// PrintHistogram(freq_array, NUM_RANGE);
fclose(bmpInput);
/*fclose(RedText);
fclose(GreenText);
fclose(BlueText);*/
fclose(ErrorRedText);
fclose(ErrorGreenText);
fclose(ErrorBlueText);
fclose(rasterOutput);
fclose(bmpOutput);
fclose(entroGreen);
fclose(entroRed);
fclose(entroBlue);
return 0;
}
/*----GET IMAGE INFO SUBPROGRAM------*/
long getImageInfo(FILE* inputFile, long offset, int numberOfChars)
{
unsigned char *ptrC;
long value=0L;
int i;
unsigned char dummy;
dummy = '0';
ptrC = &dummy;
fseek(inputFile, offset, SEEK_SET);
for(i=1; i<=numberOfChars; i++)
{
fread(ptrC, sizeof(char), 1, inputFile);
/* calculate value based on adding bytes */
value = (long)(value + (*ptrC)*(pow(256, (i-1))));
}
return(value);
}
/*-------------COPIES HEADER AND INFO HEADER----------------*/
void copyImageInfo(FILE* inputFile, FILE* outputFile)
{
unsigned char *ptrC;
unsigned char dummy;
int i;
dummy = '0';
ptrC = &dummy;
fseek(inputFile, 0L, SEEK_SET);
fseek(outputFile, 0L, SEEK_SET);
for(i=0; i<=50; i++)
{
fread(ptrC, sizeof(char), 1, inputFile);
fwrite(ptrC, sizeof(char), 1, outputFile);
}
}
/*----------------COPIES COLOR TABLE-----------------------------*/
void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors)
{
unsigned char *ptrC;
unsigned char dummy;
int i;
dummy = '0';
ptrC = &dummy;
fseek(inputFile, 54L, SEEK_SET);
fseek(outputFile, 54L, SEEK_SET);
for(i=0; i<=(4*nColors); i++) /* there are (4*nColors) bytesin color table */
{
fread(ptrC, sizeof(char), 1, inputFile);
fwrite(ptrC, sizeof(char), 1, outputFile);
}
}
I highly recommend using a search engine such as Google before asking on StackOverflow. This is a prime example. My Google Search yield examples in both C and C++.
When you have difficulties with your program, show the relevant code here.

Resources