Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Save QImage from BYTE buffer segfaults ?

Save QImage from BYTE buffer segfaults ?

Scheduled Pinned Locked Moved Solved General and Desktop
qimagebmpbytes
43 Posts 8 Posters 11.3k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SGaistS Offline
    SGaistS Offline
    SGaist
    Lifetime Qt Champion
    wrote on last edited by
    #26

    Is that some private library you can't share ? Or would it be possible to have more information about that API ?

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    R 1 Reply Last reply
    0
    • SGaistS SGaist

      Is that some private library you can't share ? Or would it be possible to have more information about that API ?

      R Offline
      R Offline
      R-P-H
      wrote on last edited by
      #27

      @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.

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #28

        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 ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        R 1 Reply Last reply
        0
        • R R-P-H

          @Jarek-B said in Save QImage from BYTE buffer segfaults ?:

          From the documentation
          https://doc.qt.io/qt-5/qimage.html#QImage-4
          data must be 32-bit aligned, and each scanline of data in the image must also be 32-bit aligned.

          So (as far as I understand) that is not enough to have memory buffer aligned to 32 bit address, also each line have to be aligned to 32 bit address. So if you have image that is 260x300 pixels, a whole line will take 288 bytes. So for whole image you should have 288*300 bytes which is more than you have provided.

          Hi, interesting...I have not seen any examples like that. How are you arriving at 288 bytes ? Are you suggesting I make the buffer 288x300 bytes instead ?

          J Offline
          J Offline
          Jarek B
          wrote on last edited by Jarek B
          #29

          @R-P-H

          Just round up space that you need for one line

          280 / 32 = 8.75
          9 * 32 = 288

          R 1 Reply Last reply
          0
          • J Jarek B

            @R-P-H

            Just round up space that you need for one line

            280 / 32 = 8.75
            9 * 32 = 288

            R Offline
            R Offline
            R-P-H
            wrote on last edited by
            #30

            @Jarek-B said in Save QImage from BYTE buffer segfaults ?:

            @R-P-H

            Just round up space that you need for one line

            280 / 32 = 8.75
            9 * 32 = 288

            I tried: BYTE *buf = new BYTE(288 * 300); Result is exactly the same. Still crashes on occasion.

            1 Reply Last reply
            0
            • SGaistS SGaist

              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 ?

              R Offline
              R Offline
              R-P-H
              wrote on last edited by
              #31

              @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; from windows.h.

              1 Reply Last reply
              0
              • mranger90M mranger90

                @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 * y

                R Offline
                R Offline
                R-P-H
                wrote on last edited by
                #32

                @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 * y

                The image is always black and it's not supposed to be, so this doesn't work.

                1 Reply Last reply
                0
                • hskoglundH Online
                  hskoglundH Online
                  hskoglund
                  wrote on last edited by hskoglund
                  #33

                  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;
                  
                  R 1 Reply Last reply
                  0
                  • hskoglundH hskoglund

                    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;
                    
                    R Offline
                    R Offline
                    R-P-H
                    wrote on last edited by
                    #34

                    @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.

                    B 1 Reply Last reply
                    0
                    • R R-P-H

                      @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.

                      B Offline
                      B Offline
                      Bonnie
                      wrote on last edited by
                      #35

                      @R-P-H
                      If your BYTE means unsigned char, then the expression of new 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.

                      R 1 Reply Last reply
                      0
                      • B Bonnie

                        @R-P-H
                        If your BYTE means unsigned char, then the expression of new 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.

                        R Offline
                        R Offline
                        R-P-H
                        wrote on last edited by
                        #36

                        @Bonnie said in Save QImage from BYTE buffer segfaults ?:

                        @R-P-H
                        If your BYTE means unsigned char, then the expression of new 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.

                        B 1 Reply Last reply
                        0
                        • R R-P-H

                          @Bonnie said in Save QImage from BYTE buffer segfaults ?:

                          @R-P-H
                          If your BYTE means unsigned char, then the expression of new 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.

                          B Offline
                          B Offline
                          Bonnie
                          wrote on last edited by Bonnie
                          #37

                          @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).

                          R 1 Reply Last reply
                          0
                          • B Bonnie

                            @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).

                            R Offline
                            R Offline
                            R-P-H
                            wrote on last edited by R-P-H
                            #38

                            @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.

                            1 Reply Last reply
                            0
                            • R Offline
                              R Offline
                              R-P-H
                              wrote on last edited by
                              #39

                              I would like to try save the buffer to a
                              BMP image using only standard C++ just to check that it's not a problem with using QImage. But I haven't been able to get that working yet...

                              1 Reply Last reply
                              0
                              • hskoglundH Online
                                hskoglundH Online
                                hskoglund
                                wrote on last edited by
                                #40

                                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:
                                Screenshot 2020-07-10 at 01.49.14.png

                                R 1 Reply Last reply
                                1
                                • hskoglundH Online
                                  hskoglundH Online
                                  hskoglund
                                  wrote on last edited by
                                  #41

                                  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....
                                  Screenshot 2020-07-10 at 05.35.30.png 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 :-)

                                  1 Reply Last reply
                                  1
                                  • hskoglundH hskoglund

                                    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:
                                    Screenshot 2020-07-10 at 01.49.14.png

                                    R Offline
                                    R Offline
                                    R-P-H
                                    wrote on last edited by
                                    #42

                                    @hskoglund Thanks for the info ! Looks to me like the API is not populating the buffer hence why it is all black.

                                    1 Reply Last reply
                                    0
                                    • R Offline
                                      R Offline
                                      R-P-H
                                      wrote on last edited by
                                      #43

                                      @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.

                                      1 Reply Last reply
                                      1

                                      • Login

                                      • Login or register to search.
                                      • First post
                                        Last post
                                      0
                                      • Categories
                                      • Recent
                                      • Tags
                                      • Popular
                                      • Users
                                      • Groups
                                      • Search
                                      • Get Qt Extensions
                                      • Unsolved