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. How to save image (about 36 mb) to db via QSqlQuery?
Forum Updated to NodeBB v4.3 + New Features

How to save image (about 36 mb) to db via QSqlQuery?

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 4 Posters 803 Views 1 Watching
  • 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.
  • August WienerA Offline
    August WienerA Offline
    August Wiener
    wrote on last edited by
    #1

    Hello there!
    I have a problem with QSqlQuery, when trying to save relatively large (~36 mb) image. When I call QSqlQuery::exec(), I get std::bad_alloc exeption. When I work with smaller images, everything is ok. Need to be sayed - this code executes in other instance of QThread in order to prevent GUI freezing, all code compiled in MinGW-32 compiler, there are 8 GB RAM on PC. And some times (very rarely) I've got this code running without this exception even with images this size (36 mb)

    here is the code:

    ......
    QByteArray byte_array_image, byte_array_icon;
    QBuffer buffer_image(&byte_array_image), buffer_icon(&byte_array_icon);
    
    buffer_image.open(QIODevice::WriteOnly);
    buffer_icon.open(QIODevice::WriteOnly);
    
    image->save(&buffer_image, format.toLocal8Bit().data());
    icon->save(&buffer_icon, "JPEG");
    
    query.prepare("INSERT INTO pictures (id, id_act, date_time, name, picture, icon) VALUES (:id, :id_act, :date_time, :name, :picture, :icon)");
    ......
    query.bindValue(":picture", byte_array_image);
    query.bindValue(":icon", byte_array_icon);
    byte_array_image.clear();
    byte_array_icon.clear();
    
    save_succeed = query.exec();
    
    if (!save_succeed)
        emit database_failed(QUERY_ERROR_HEADER, QUERY_ERROR_SAVE_IMAGE + query.lastError().text());
    
    emit query_finished();
    
    return save_succeed;
    

    As far as I can see, problem can be related with lack of heap space for QApplication to create instance of QString included all bytecode of image. In order to fix that, I ve tried to split this image up to ten parts, but it doesn't help.

    Here is ten-parts-splitted query code:

    ............
    QByteArray byte_array_image, byte_array_icon;
    QBuffer buffer_image(&byte_array_image), buffer_icon(&byte_array_icon);
    
    buffer_image.open(QIODevice::WriteOnly);
    buffer_icon.open(QIODevice::WriteOnly);
    
    image->save(&buffer_image, format.toLocal8Bit().data());
    icon->save(&buffer_icon, "JPEG");
    
    int partlen, parts_count = 0;
    save_succeed = false;
    
    while (!save_succeed && ++parts_count < 10)
    {
         partlen = byte_array_image.size();
         partlen = byte_array_image.size() / parts_count;
    
         query.clear();
         query.prepare("INSERT INTO pictures (id, id_act, date_time, name, part_one, parts_count, icon, src, src_act) "
                          "VALUES (:id, :id_act, :date_time, :name, :part_one, :parts_count, :icon, :src, :src_act)");
         ........
         query.bindValue(":part_one", byte_array_image.mid(0, partlen));
         query.bindValue(":parts_count", parts_count);
         query.bindValue(":icon", byte_array_icon);
    
         try
         {
             save_succeed = query.exec();
         }
         catch (std::bad_alloc &error)
         {
             if (parts_count < 10)
                 continue;
    
             emit database_failed(QUERY_HEAP_ERROR_HEADER, QUERY_HEAP_ERROR_TEXT);
    
             return false;
         }
    
     }
    
     if (save_succeed)
     {
        QStringList part_names = { "part_one", "part_two", "part_three", "part_four", "part_five",
                                       "part_six", "part_seven", "part_eight", "part_nine", "part_ten"};
    
        for (int current_part = 1; current_part < parts_count; ++current_part)
        {
            query.clear();
    
            query.prepare("UPDATE pictures SET "+part_names[current_part]+" = :current_part WHERE id = :id AND src = :src");
            query.bindValue(":current_part", current_part == parts_count - 1 ? byte_array_image.mid(current_part*partlen) : byte_array_image.mid(current_part*partlen, partlen));
            ........
            save_succeed = query.exec();
        }
     }
    
     byte_array_image.clear();
     byte_array_icon.clear();
    

    Am I correct with the problem source? Is there anything I can do to fix it? 36 mb for image is not so much.

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

      Hi,

      You should check the current memory consumption of your application. Since you are building a 32bit application, you are limited to 2GB of RAM available to your process.

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

      August WienerA 1 Reply Last reply
      2
      • SGaistS SGaist

        Hi,

        You should check the current memory consumption of your application. Since you are building a 32bit application, you are limited to 2GB of RAM available to your process.

        August WienerA Offline
        August WienerA Offline
        August Wiener
        wrote on last edited by
        #3

        @sgaist
        Hello and thank you. I checked in task manager, On start my application consumes around 400 mb, when I trying to take snap, this amount grows to 900 mb, but then drops to~ 600. So with every snap I loose about 200 mb.
        I guess that is the problem. Can provided code leads to mem leak?

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

          What do you mean by snap ?

          What kind of image are you manipulating ?
          From the looks of it, you are making at list one copy of your image in a format that may or may not be compressed.
          I don't know about the icon.

          You should profile the application to see what is going on.

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

          August WienerA 1 Reply Last reply
          0
          • SGaistS SGaist

            What do you mean by snap ?

            What kind of image are you manipulating ?
            From the looks of it, you are making at list one copy of your image in a format that may or may not be compressed.
            I don't know about the icon.

            You should profile the application to see what is going on.

            August WienerA Offline
            August WienerA Offline
            August Wiener
            wrote on last edited by August Wiener
            #5

            @sgaist
            By snap I mean image, which I'm pulling from camera
            I've noticed when I'm using try-catch block on qsqlquery::exec() it leads to memory leak. I mean is there a possability that when bad_alloc occurs inside qsqlquery class, program exits from exec() function without propper freeing memory up ?

            1 Reply Last reply
            0
            • Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Why do you use a QImage pointer - where do you free it?

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              August WienerA 1 Reply Last reply
              0
              • Christian EhrlicherC Christian Ehrlicher

                Why do you use a QImage pointer - where do you free it?

                August WienerA Offline
                August WienerA Offline
                August Wiener
                wrote on last edited by
                #7

                @christian-ehrlicher
                I call this function from another one where QImage declared as a static variable.

                1 Reply Last reply
                0
                • Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by Christian Ehrlicher
                  #8

                  And you're sure you don't allocate it again on every call?

                  /edit: And why needs it to be a pointer at all?

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  1 Reply Last reply
                  0
                  • August WienerA August Wiener

                    Hello there!
                    I have a problem with QSqlQuery, when trying to save relatively large (~36 mb) image. When I call QSqlQuery::exec(), I get std::bad_alloc exeption. When I work with smaller images, everything is ok. Need to be sayed - this code executes in other instance of QThread in order to prevent GUI freezing, all code compiled in MinGW-32 compiler, there are 8 GB RAM on PC. And some times (very rarely) I've got this code running without this exception even with images this size (36 mb)

                    here is the code:

                    ......
                    QByteArray byte_array_image, byte_array_icon;
                    QBuffer buffer_image(&byte_array_image), buffer_icon(&byte_array_icon);
                    
                    buffer_image.open(QIODevice::WriteOnly);
                    buffer_icon.open(QIODevice::WriteOnly);
                    
                    image->save(&buffer_image, format.toLocal8Bit().data());
                    icon->save(&buffer_icon, "JPEG");
                    
                    query.prepare("INSERT INTO pictures (id, id_act, date_time, name, picture, icon) VALUES (:id, :id_act, :date_time, :name, :picture, :icon)");
                    ......
                    query.bindValue(":picture", byte_array_image);
                    query.bindValue(":icon", byte_array_icon);
                    byte_array_image.clear();
                    byte_array_icon.clear();
                    
                    save_succeed = query.exec();
                    
                    if (!save_succeed)
                        emit database_failed(QUERY_ERROR_HEADER, QUERY_ERROR_SAVE_IMAGE + query.lastError().text());
                    
                    emit query_finished();
                    
                    return save_succeed;
                    

                    As far as I can see, problem can be related with lack of heap space for QApplication to create instance of QString included all bytecode of image. In order to fix that, I ve tried to split this image up to ten parts, but it doesn't help.

                    Here is ten-parts-splitted query code:

                    ............
                    QByteArray byte_array_image, byte_array_icon;
                    QBuffer buffer_image(&byte_array_image), buffer_icon(&byte_array_icon);
                    
                    buffer_image.open(QIODevice::WriteOnly);
                    buffer_icon.open(QIODevice::WriteOnly);
                    
                    image->save(&buffer_image, format.toLocal8Bit().data());
                    icon->save(&buffer_icon, "JPEG");
                    
                    int partlen, parts_count = 0;
                    save_succeed = false;
                    
                    while (!save_succeed && ++parts_count < 10)
                    {
                         partlen = byte_array_image.size();
                         partlen = byte_array_image.size() / parts_count;
                    
                         query.clear();
                         query.prepare("INSERT INTO pictures (id, id_act, date_time, name, part_one, parts_count, icon, src, src_act) "
                                          "VALUES (:id, :id_act, :date_time, :name, :part_one, :parts_count, :icon, :src, :src_act)");
                         ........
                         query.bindValue(":part_one", byte_array_image.mid(0, partlen));
                         query.bindValue(":parts_count", parts_count);
                         query.bindValue(":icon", byte_array_icon);
                    
                         try
                         {
                             save_succeed = query.exec();
                         }
                         catch (std::bad_alloc &error)
                         {
                             if (parts_count < 10)
                                 continue;
                    
                             emit database_failed(QUERY_HEAP_ERROR_HEADER, QUERY_HEAP_ERROR_TEXT);
                    
                             return false;
                         }
                    
                     }
                    
                     if (save_succeed)
                     {
                        QStringList part_names = { "part_one", "part_two", "part_three", "part_four", "part_five",
                                                       "part_six", "part_seven", "part_eight", "part_nine", "part_ten"};
                    
                        for (int current_part = 1; current_part < parts_count; ++current_part)
                        {
                            query.clear();
                    
                            query.prepare("UPDATE pictures SET "+part_names[current_part]+" = :current_part WHERE id = :id AND src = :src");
                            query.bindValue(":current_part", current_part == parts_count - 1 ? byte_array_image.mid(current_part*partlen) : byte_array_image.mid(current_part*partlen, partlen));
                            ........
                            save_succeed = query.exec();
                        }
                     }
                    
                     byte_array_image.clear();
                     byte_array_icon.clear();
                    

                    Am I correct with the problem source? Is there anything I can do to fix it? 36 mb for image is not so much.

                    W Offline
                    W Offline
                    wrosecrans
                    wrote on last edited by
                    #9

                    @august-wiener said in How to save image (about 36 mb) to db via QSqlQuery?:

                    36 mb for image is not so much.

                    For a file, 36 MB is not too much. For a single field in a relational database, 36 MB is extremely unusual. You will probably have a lot more luck saving the image to a file, and just retaining the filename in the database as a short string. This is the much more common way to do it. The SQL database isn't really designed around storing large binary blobs, and neither are the associated libraries.

                    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