Reputation: 27
In this program I am trying to use C-style files for both reading and writing these files. I am also dynamically allocating the memory onto the heap using new() and delete in order to then write that block of memory to another file. For some reason when I preform a hex hump the files are almost the same. Only the ending bytes are different. Here are my dumps.
This is for my input file. The output should have the same data.
This is my output file. From the dump you can see that its different at the end of the file. Why does this happen if I use fseek() to skip the padding?
#include <cstdint>
#include <cstdio>
#pragma pack(push, 2)
struct BitmapFileHeader {
uint16_t type;
uint32_t size;
uint16_t reserved_1;
uint16_t reserved_2;
uint32_t offset;
};
struct BitmapInfoHeader {
uint32_t size;
uint32_t width;
uint32_t height;
uint16_t planes;
uint16_t bitcount;
uint32_t compression;
uint32_t imagesize;
uint32_t x_pixels_per_meter;
uint32_t y_pixels_per_meter;
uint32_t color_used;
uint32_t color_important;
};
#pragma pack(pop)
struct Pixel {
uint8_t blue;
uint8_t green;
uint8_t red;
};
int main(int argc, char* argv[])
{
if(argc != 3) {
printf("Usage : %s input_file output_file\n", argv[0]);
return 1;
}
FILE *fin;
FILE *fout;
BitmapFileHeader bfh;
BitmapInfoHeader bih;
fin = fopen(argv[1], "rb");
if (nullptr == fin) {
perror(argv[1]);
return -1;
}
if (sizeof(BitmapFileHeader) != fread(
&bfh,
1,
sizeof(bfh),
fin
)) {
printf("Unable to read bitmap file header. \n");
return -2;
}
if (sizeof(BitmapInfoHeader) != fread(
&bih,
1,
sizeof(bih),
fin
)) {
printf("Unable to read bitmap info header. \n");
return -3;
}
printf("Size of File Header = %lu\n", sizeof(BitmapFileHeader));
int8_t first = (bfh.type >> 8) & 0xff;
int8_t second = bfh.type & 0xff;
if ( (first != 'M') && (second != 'B') ){
printf("Input file is not a Bitmap file. \n");
return -4;
}
printf("File type = %c%c\n", first, second);
printf("File size = %u\n", bfh.size);
printf("File offset = %u\n", bfh.offset);
printf("File width = %u\n", bih.width);
printf("Info size = %u\n", bih.size);
uint32_t padding_bytes = 0;
uint32_t row_bytes_final = bih.width * sizeof(Pixel);
uint32_t row_bytes_initial = row_bytes_final;
do{
uint32_t rem = row_bytes_final % 4;
if (rem != 0) {
row_bytes_final += 1;
}
padding_bytes = row_bytes_final - row_bytes_initial;
} while( (row_bytes_final % 4) != 0);
fseek(fin, bfh.offset, SEEK_SET);
Pixel *p = new Pixel[bih.height * bih.width];
for (uint32_t i = 0; i < bih.height; i++) {
for (uint32_t j = 0; j < bih.width; j++) {
uint32_t index = i * bih.width + j;
fread(&p[index], 1, sizeof(p[0]), fin);
}
fseek(fin, padding_bytes, SEEK_CUR);
}
fclose(fin);
fout = fopen(argv[2], "wb");
if(nullptr == fout) {
perror(argv[2]);
return -5;
}
if( sizeof(BitmapFileHeader) != fwrite(
&bfh,
1,
sizeof(bfh),
fout
)) {
printf("Unable to write bitmap file header.\n");
return -6;
}
if( sizeof(BitmapInfoHeader) != fwrite(
&bih,
1,
sizeof(bih),
fout
)) {
printf("Unable to write bitmap info header.\n");
return -7;
}
fseek(fout, bfh.offset, SEEK_SET);
for (uint32_t i = 0; i < bih.height; i++) {
for (uint32_t j = 0; j < bih.width; j++) {
uint32_t index = i * bih.width + j;
fwrite(&p[index], 1, sizeof(p[0]), fout);
}
fseek(fout, padding_bytes, SEEK_CUR);
}
fclose(fout);
delete p;
//fseek(fin, bfh.offset, SEEK_SET);
//Pixel p;
//fread(&p, 1, sizeof(p), fin);
//printf("R = %u, G = %u, B = %u\n", p.red, p.green, p.blue);
return 0;
}
Upvotes: 0
Views: 461
Reputation: 63451
Seeking to a position off the end of the file does not automatically pad it. Padding bytes will only be written on a subsequent write.
You can force this last padding to be written after your loop finishes as follows:
if (padding_bytes > 0) {
fseek(fout, -1, SEEK_CUR);
fputc('\0', fout);
}
By the way, you are using the wrong delete
for your array. Instead use array-delete (corresponding to the array-alloc):
delete[] p;
Upvotes: 1