Save QImage from BYTE buffer segfaults ?
-
@SGaist said in Save QImage from BYTE buffer segfaults ?:
Then are you sure their BYTE type is not something custom ? Do they also show how to access the data ?
Is it the Windows BYTE type ?
They do not show how to access the data afterwards.
It's defined as
typedef unsigned char BYTE;
fromwindows.h
. -
@mranger90 said in Save QImage from BYTE buffer segfaults ?:
@R-P-H Of course it's black, the data never gets initialized.
Also, the reason why it doesn't crash is because:
BYTE *buf = new BYTE(x * y); // allocates a single byte, initialized to the value of (x * y)
BYTE *buf = new BYTE[x * y]; // allocates an array of bytes whose size is x * yThe image is always black and it's not supposed to be, so this doesn't work.
-
Hi, you could try explicitly specify the number of bytes per line:
Edit: also, it could be that your deleting the buffer before the QImage is deleted:BYTE *buf = new BYTE(imWidth * imHeight); //Populate buf with data using API call here (not shown) { QImage img(buf, imWidth, imHeight, imWidth, QImage::Format_Grayscale8); img.save("image.bmp", "BMP"); } delete [] buf;
-
@hskoglund said in Save QImage from BYTE buffer segfaults ?:
Hi, you could try explicitly specify the number of bytes per line:
Edit: also, it could be that your deleting the buffer before the QImage is deleted:BYTE *buf = new BYTE(imWidth * imHeight); //Populate buf with data using API call here (not shown) { QImage img(buf, imWidth, imHeight, imWidth, QImage::Format_Grayscale8); img.save("image.bmp", "BMP"); } delete [] buf;
Hi, thanks for the suggestion. I tried it and result is the same...still crashes on occasion.
I also tried with removing the
delete [] buf
line and still the same. -
@R-P-H
If yourBYTE
meansunsigned char
, then the expression ofnew BYTE(imWidth * imHeight)
is definitely wrong.
As @mranger90 says, that really means you allocate a buf of only one byte size, whose value is (imWidth * imHeight).
So I won't be surprised that it crashes. -
@Bonnie said in Save QImage from BYTE buffer segfaults ?:
@R-P-H
If yourBYTE
meansunsigned char
, then the expression ofnew BYTE(imWidth * imHeight)
is definitely wrong.
As @mranger90 says, that really means you allocate a buf of only one byte size, whose value is (imWidth * imHeight).
So I won't be surprised that it crashes.I tried with
new BYTE[imWidth * imHeight]
as well but the image is always black. -
@R-P-H
Right, this is another problem.
How can you be sure your populated data is not all black?
I will suggest you do some tests without Qt classes.BYTE *buf = new BYTE[imWidth * imHeight]; //Populate buf with data using API call here (not shown) bool AllZero = true; for(int i = 0; i < imWidth * imHeight; i++) { if(buf[i] != 0) AllZero = false; } qDebug() << "AllZero :" << AllZero; delete [] buf;
Or you can just print all of the data to see whether it is all zero(black).
-
@Bonnie said in Save QImage from BYTE buffer segfaults ?:
@R-P-H
Right, this is another problem.
How can you be sure your populated data is not all black?
I will suggest you do some tests without Qt classes.BYTE *buf = new BYTE[imWidth * imHeight]; //Populate buf with data using API call here (not shown) bool AllZero = true; for(int i = 0; i < imWidth * imHeight; i++) { if(buf[i] != 0) AllZero = false; } qDebug() << "AllZero :" << AllZero; delete [] buf;
Or you can just print all of the data to see whether it is all zero(black).
Yes it's all black everytime.
-
QImage is quite reliable, for example if I add just 2 for loops to change the pixels to something not black:
int imWidth = 260; int imHeight = 300; typedef unsigned char BYTE; BYTE *buf = new BYTE[imWidth * imHeight]; for (int y = 0; (y < imHeight); ++y) for (int x = 0; (x < imWidth); ++x) buf[x + y * imWidth] = x*x + y*y; QImage img(buf, imWidth, imHeight, QImage::Format_Grayscale8); img.save("image.bmp", "BMP"); delete [] buf;
I get:
-
Hi again, dug around in my old projects (turn-of-the-century old :-) and I found this function to write grey BMP files the hard way:
void save_bitmap_grey8(char* file_name, int width, int height, BYTE* pixel_data) { #pragma pack(push, 1) struct bitmap_file_header { short bitmap_type; int file_size; short reserved1; short reserved2; int offset_bits; } bfh; #pragma pack(pop) struct bitmap_image_header { int size_header; int width; int height; short planes; short bit_count; int compression; int image_size; int ppm_x; int ppm_y; int clr_used; int clr_important; } bih; struct grey_palette { BYTE r; BYTE g; BYTE b; BYTE a; } gp[256]; for (int i = 0; (i < 256); ++i) { gp[i].r = gp[i].g = gp[i].b = i; gp[i].a = 0; } int imagesize = height * (((width * 8 + 31) & ~31) / 8); memcpy(&bfh.bitmap_type, "BM", 2); bfh.file_size = sizeof(bfh) + sizeof(bih) + sizeof(gp) + imagesize; bfh.reserved1 = 0; bfh.reserved2 = 0; bfh.offset_bits = sizeof(bfh) + sizeof(bih) + sizeof(gp); bih.size_header = sizeof(bih); bih.width = width; bih.height = height; bih.planes = 1; bih.bit_count = 8; bih.compression = 0; bih.image_size = imagesize; bih.ppm_x = 3780; // meter->inch->96 ppi bih.ppm_y = 3780; // same here bih.clr_used = 256; bih.clr_important = 256; FILE* image = fopen(file_name, "wb"); fwrite(&bfh, 1, sizeof(bfh), image); fwrite(&bih, 1, sizeof(bih), image); fwrite(&gp, 1, sizeof(gp), image); fwrite(pixel_data, 1, width * height, image); fclose(image); }
So just swap out QImage with the above function, like this:
int imWidth = 260; int imHeight = 300; BYTE *buf = new BYTE[imWidth * imHeight]; for (int y = 0; (y < imHeight); ++y) for (int x = 0; (x < imWidth); ++x) buf[x + y * imWidth] = x*x + y*y; save_bitmap_grey8("image.bmp",imWidth,imHeight,buf); delete [] buf;
Looks exactly the same, except....
it's upside down! That's a relic of OS/2's spec. for bitmaps, they wanted (x =0 , y = 0) to be in lower left corner instead of top left corner. QImage fixes this but my code has that vintage upside/down bug :-) -
@mranger90 said in Save QImage from BYTE buffer segfaults ?:
try:
BYTE *buf = new BYTE[imWidth * imHeight];So the issue turned out to be with the device itself. Changing the code as above and replacing the device solved the issue. Thanks.