Save QImage from BYTE buffer segfaults ?
-
@mranger90 said in Save QImage from BYTE buffer segfaults ?:
@R-P-H here is the amended code
// allocates a buffer of imWidth * imHeight bytes, which depending on the compiler // settings will either be initialized to zero, or may contain garbage BYTE *buf = new BYTE[imWidth * imHeight]; // creates a QImage based on the data in the buffer, QImage img(buf, imWidth, imHeight, QImage::Format_Grayscale8); // saves the data img.save("image.bmp", "BMP"); delete [] buf;
The point is that you never put actual image data into the buffer.
This is already what I did according to your first post. The buffer IS populated, I just didn't show that API call. I will modify my original post to make this clear...
So the result is a completely black image. This may be normal but I will have to check with the API provider.
EDIT: I have edited my original post.
-
Is that some private library you can't share ? Or would it be possible to have more information about that API ?
-
@SGaist said in Save QImage from BYTE buffer segfaults ?:
Is that some private library you can't share ? Or would it be possible to have more information about that API ?
Your assumption is correct. There really aren't any additional details on using this API function. It simply takes as input a reference to the buffer and a unique id of the capturing device. It then populates the buffer in place. The example in the documentation initializes the buffer the same way as shown in my original post.
If we are sure the error is on the API side, then they will need to fix that.
I made the assumption that the error was in saving the image to disk.
-
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 ?
-
-
@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.