C++: Write BMP image format error on WINDOWS -
i have strange problem here... i'm using same code(copy-paste) linux in windows read , write , bmp image. , reason in linux every thing works perfectly fine, when i'm coming windows 10 can't open images , i've receive error message how said this:
"it looks don't support file format."
do have idea should do? put code below.
edit:
i've solved padding problem , it's write images white, idea why? i've update code also.
struct bmp { int width; int height; unsigned char header[54]; unsigned char *pixels; int size; int row_padded; }; void writebmp(string filename, bmp image) { string filename = "output files\\" + filename; file *out = fopen(filename.c_str(), "wb"); fwrite(image.header, sizeof(unsigned char), 54, out); unsigned char tmp; (int = 0; < image.height; i++) { (int j = 0; j < image.width * 3; j += 3) { // convert (b, g, r) (r, g, b) tmp = image.pixels[j]; image.pixels[j] = image.pixels[j + 2]; image.pixels[j + 2] = tmp; } fwrite(image.pixels, sizeof(unsigned char), image.row_padded, out); } fclose(out); } bmp readbmp(string filename) { bmp image; string filename = "input files\\" + filename; file *f = fopen(filename.c_str(), "rb"); if (f == null) throw "argument exception"; fread(image.header, sizeof(unsigned char), 54, f); // read 54-byte header // extract image height , width header image.width = *(int *) &image.header[18]; image.height = *(int *) &image.header[22]; image.row_padded = (image.width * 3 + 3) & (~3); image.pixels = new unsigned char[image.row_padded]; unsigned char tmp; (int = 0; < image.height; i++) { fread(image.pixels, sizeof(unsigned char), image.row_padded, f); (int j = 0; j < image.width * 3; j += 3) { // convert (b, g, r) (r, g, b) tmp = image.pixels[j]; image.pixels[j] = image.pixels[j + 2]; image.pixels[j + 2] = tmp; } } fclose(f); return image; }
in point of view code should cross-platform... it's not... why?
thanks help
check header
the header must start following 2 signature bytes: 0x42 0x4d
. if it's different third party application think file doesn't contain bmp picture despite .bmp file extension.
the size , way pixels stored little bit more complex expect: assume number of bits per pixels 24 , no no compression used. not guaranteed. if it's not case, might read more data available, , corrupt file when writing back.
furthermore, size of header depends on bmp version using, you can detect using 4 byte integer @ offset 14.
improve code
when load file, check signature, bmp version, number of bits per pixel , compression. debugging purpose, consider dumping header check manually:
for (int i=0; i<54; i++) cout << hex << image.header[i] << " ";` cout <<endl;
furthermore, when fread()
check number of bytes read correspond size wanted read, sure you're not working uninitialized buffer data.
edit:
having checked dump, appears format expected. verifying padded size in header padded size have calculated appears error here:
image.row_padded = (image.width * 3 + 3) & (~3); // ok size of single row rounded multiple of 4 image.pixels = new unsigned char[image.row_padded]; // oops ! little short ?
in fact read row row, keep last 1 in memory ! different of first version, did read full pixels of picture.
similarly, write last row repeated height time.
reconsider padding, working total padded size.
image.row_padded = (image.width * 3 + 3) & (~3); // ok size of single row rounded multiple of 4 image.size_padded = image.row_padded * image.height; // padded full size image.pixels = new unsigned char[image.size_padded]; // yeah ! if (fread(image.pixels, sizeof(unsigned char), image.size_padded, f) != image.size_padded) { cout << "error: bytes couldn't read"<<endl; } else { ... // process pixels expected } ...
Comments
Post a Comment