Important: Please read the Qt Code of Conduct -

[SOLVED] How to store a qimage to iOS Camera Roll (Photo Album) ?

  • Hi, i am trying to port an native Objective C iOS App to an QT App.
    The App uses the iPhone/iPad Camera and should create an Image which is saved to the Camera Roll of the Device.

    So here is the Problem: How do I access the Camera Roll or what Path (QStandardPaths::PicturesLocation returns an empty string) I need to use when saving an Image.


  • Ok it seems no one ever tried this or ever succeeded.

    I found only a dirty way to do it without going too deep in UIImage and QtImage Logic - I didn't have the time so I needed to use already working Algorithm.

    For my "solution" you need the OpenCV Framework in your Qt Project (see my post how to do this). Basically you have to Convert the QImage to an IplImage and then the IplImage to an UIImage.

    To accomplish that you need to use following code in a Qt/Objective C Hybrid mm File (see for how to mix Objective C and C++ in Qt) :

    #include "cv.h"

    #import <Foundation/NSData.h>
    #import <UIKit/UIKit.h>

    UIImage* GetUIImg(IplImage* iplImage) {
    // NOTE Do not try to include this function in your header, because it will
    // need UIImage and if you add the UIKit Objective C Lib in your header
    // to make the Type visible the Qt Preprocessor will try to Process the
    // UIKit Lib as C++ and will fail
    cv::Mat cvMat = cv::cvarrToMat(iplImage);

    NSData *data = [NSData length:cvMat.elemSize() *];
    CGColorSpaceRef colorSpace;
    if (cvMat.elemSize() == 1)
        colorSpace = CGColorSpaceCreateDeviceGray();
        colorSpace = CGColorSpaceCreateDeviceRGB();
    CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
    CGImageRef imageRef = CGImageCreate(cvMat.cols,                                     // Width
                                        cvMat.rows,                                     // Height
                                        8,                                              // Bits per component
                                        8 * cvMat.elemSize(),                           // Bits per pixel
                                        cvMat.step[0],                                  // Bytes per row
                                        colorSpace,                                     // Colorspace
                                        kCGImageAlphaNone | kCGBitmapByteOrderDefault,  // Bitmap info flags
                                        provider,                                       // CGDataProviderRef
                                        NULL,                                           // Decode
                                        false,                                          // Should interpolate
                                        kCGRenderingIntentDefault);                     // Intent
    UIImage* imgResult = [[UIImage alloc] initWithCGImage:imageRef];
    return imgResult;


    void ObjCHelpers::saveImgToGallery(QImage qimg4Album) {
    QImage* qImage = &qimg4Album;

    int width = qImage->width();
    int height = qImage->height();
    CvSize Size;
    Size.height = height;
    Size.width = width;
    IplImage *ipl4Album = cvCreateImage(Size, IPL_DEPTH_8U, 1);
    char *charTemp = (char *) ipl4Album->imageData;
    for (int y = 0; y < height; y++)
        for (int x = 0; x < width; x++)
            int index = y * width + x;
            charTemp[index] = (char) qGray(qImage->pixel(x, y));
    UIImage* uiimg4Album = GetUIImg(ipl4Album);
    UIImageWriteToSavedPhotosAlbum(uiimg4Album, Nil, Nil, Nil);


    Its not a perfect solution but it works for me. If someone knows how an QImage is stored internally and knows the same about an UIImage, he could do the Convertion without using an IplImage but I already use the OpenCV Framework in my Project and had an working Ipl to UI Image Convertion in another Project so it was the simplest way for me.

  • Lifetime Qt Champion


    QImage can be of several "formats": and "here":

    You should also take a look at QtMacExtras, you have a helper function to get a CGImageRef from a QPixmap.

    Hope it helps

  • Sorry to dig this old topic.
    I also needed to save a picture to the camera roll, and I thought that such a frequent use case would be supported "out of the box" by Qt, unfortunately after almost a complete day of browsing the web I haven't found a ready to use and working solution.
    I liked aqmah solution but I didn't want to add OpenCV dependency to my project just for this.

    Unfortunately QtMacExtras is no longer available on iOS.
    I have thus modified aqmah solution to come up with an acceptable solution without OpenCV.

    I know it is far from perfect but still it could be of some help :

    bool saveImgToGallery(const QImage& qimg4Album) {
        UIImage* uiimg4Album = QImage2UIImmage(qimg4Album);
        if ( uiimg4Album){
            UIImageWriteToSavedPhotosAlbum( uiimg4Album, Nil, Nil, Nil);
            return true;
        return false;
    UIImage* QImage2UIImmage(const QImage& img)
        if (img.isNull()) return nullptr;
        CGDataProviderRef provider = CGDataProviderCreateWithData(nullptr, img.bits(), img.byteCount(), nullptr);
        CGColorSpaceRef colorSpace = img.isGrayscale() ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
    CGImageRef imageRef = CGImageCreate( 
            img.width(),  img.height(), 
            8, img.depth(), img.bytesPerLine(), 
            colorSpace, getFlagsFromImageFormat(img.format()),
            provider, NULL, false, kCGRenderingIntentDefault);
        return imgResult;
    uint getFlagsFromImageFormat(QImage::Format frm)
        uint cgFlags = kCGImageAlphaNone;
        switch (frm) {
        case QImage::Format_ARGB32:
            cgFlags = kCGImageAlphaFirst | kCGBitmapByteOrder32Host;
        case QImage::Format_RGB32:
            cgFlags = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host;
        case QImage::Format_RGB888:
            cgFlags = kCGImageAlphaNone | kCGBitmapByteOrder32Big;
        case QImage::Format_RGBA8888_Premultiplied:
            cgFlags = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big;
        case QImage::Format_RGBA8888:
            cgFlags = kCGImageAlphaLast | kCGBitmapByteOrder32Big;
        case QImage::Format_RGBX8888:
            cgFlags = kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big;
        case QImage::Format_ARGB32_Premultiplied:
            cgFlags = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host;
            cgFlags = kCGImageAlphaNone;
        return cgFlags;

  • Hi, and what if I need to download an image and save it in the camera roll?
    I'm using Qt 5.5.1, pictures location seems to be correct and when saving I don't get any error but I can't find the image on the gallery app!

  • @Charby Hi
    I know this is old topic but maybe you could help ?
    I'm trying to save image to iOS gallery using your code, in QImage2UIImmage function there is missing conversion from CGImageRef to UIImage.
    I have created my class based on your example, but application is crashing each time when I want to save photo.
    I have described crash and provided code in this post


  • Hi Marek,
    Sorry I don't see anything obvious from your so post...
    Actually I no longer do mobile development with Qt on iOS since QtC ramped down the Indie licensing program.
    I hope you will find shortly a nice and easy fix.
    Best regards.

  • Lifetime Qt Champion

    @Charby Did you saw the new offering ? Might be an option again.

  • Yes, I heard about its announcement but I don't think it is effective yet (?). I might consider it (even if it is more expensive than indie plan used to be) if one can be confident it won't be dropped without prior notice...

  • Lifetime Qt Champion

    Good question... You should contact the Qt Company directly for a clear answer.

  • @SGaist I will as soon as the new offering will be available. Thanks

Log in to reply