Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Cannot safe image on android with camera



  • I have the following Issue.

    In my app I use QtMultimedia 5.14 and use its Camera class.

    However when I take a picture and try to safe it I get a exception like this in the Application Output:

    W libcamera_armeabi-v7a.so: qrc:/main.qml:55:19: QML Image: Cannot open: qrc:/data/user/0/org.qtproject.example.camera/files/IMG_00000015.jpg
    

    Does it mean I don't have the user rights on android to safe?

    The image safe code looks like this:

    Camera {
        id: camera
    }
    
    //...
    
    Connections {
        target: camera.imageCapture
    
        onImageSaved: {
            imagePaths.append({"path": path})
            listView.positionViewAtEnd();
        }
    }

  • Moderators

    @sandro4912 said in Cannot safe image on android with camera:

    qrc:/

    QRC storage is read-only. Choose a different path.

    App data location, cache location and temp locations are writable even if you do not get any storage permissions from your user.



  • stupid question. How can I change to a different path? What would be a valid path?


  • Lifetime Qt Champion

    @sandro4912 See https://doc.qt.io/qt-5/qstandardpaths.html using it you can get the paths @sierdzio already mentioned



  • @jsulm So I have to make a C++ class with QStandardPaths or is it available directly in QML?


  • Lifetime Qt Champion



  • I tryed it with the path but still no images. show up. Atleast the error does not appear anymore.

    I changed the path here.

    delegate: Image {
                height: 100
                //source: path
                source: Labs.StandardPaths.writableLocation(Labs.StandardPaths.ApplicationsLocation)
                fillMode: Image.PreserveAspectFit
            }
    

    Full code:

    import QtQuick 2.14
    import QtQuick.Controls 2.14
    import QtMultimedia 5.14
    import Qt.labs.platform 1.1 as Labs
    
    ApplicationWindow {
        visible: true
    
        id: root
    
        width: 1024
        height: 600
    
    
    
    Rectangle {
        width: parent.width
        height: parent.height
    
        color: "black"
    
        VideoOutput {
            anchors.fill: parent
            source: camera
        }
    
        Camera {
            id: camera
        }
    
        ListModel {
            id: imagePaths
        }
    
        ListView {
            id: listView
    
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 10
    
            height: 100
    
            orientation: ListView.Horizontal
            spacing: 10
    
            model: imagePaths
    
            delegate: Image {
                height: 100
                //source: path
                source: Labs.StandardPaths.writableLocation(Labs.StandardPaths.ApplicationsLocation)
                fillMode: Image.PreserveAspectFit
            }
    
            Rectangle {
                anchors.fill: parent
                anchors.topMargin: -10
    
                color: "black"
                opacity: 0.5
            }
        }
    
        Image {
            id: image
            anchors.fill: parent
        }
    
        Connections {
            target: camera.imageCapture
    
            onImageSaved: {
                imagePaths.append({"path": path})
                listView.positionViewAtEnd();
            }
        }
    
        Column {
            id: buttons
    
            anchors.top: parent.top
            anchors.right: parent.right
            anchors.margins: 10
    
            spacing: 10
    
            Button {
                id: shotButton
    
                text: "Take Photo"
                onClicked: {
                    camera.imageCapture.capture();
                }
            }
    
            Button {
                id: playButton
    
                text: "Play Sequence"
                onClicked: {
                    parent.parent.startPlayback();
                }
            }
    
            Button {
                id: clearButton
    
                text: "ClearSequence"
                onClicked: {
                    imagePaths.clear()
                }
            }
        }
    
        property int _imageIndex: -1
    
        function startPlayback()
        {
            root.state = "playing"
            setImageIndex(0);
            playTimer.start();
        }
    
        function setImageIndex(i)
        {
            _imageIndex = i;
    
            if(_imageIndex >= 0 && _imageIndex < imagePaths.count) {
                image.source = imagePaths.get(_imageIndex).path;
            }
            else {
                image.source = "";
            }
        }
    
        Timer {
            id: playTimer
    
            interval: 200
            repeat: false
    
            onTriggered: {
                if (_imageIndex + 1 < imagePaths.count) {
                    setImageIndex(_imageIndex + 1);
                    playTimer.start();
                }
                else {
                    setImageIndex(-1);
                    root.state = "";
                }
            }
        }
    
        states: [
            State {
                name: "playing"
                PropertyChanges {
                    target: buttons
                    opacity: 0
                }
                PropertyChanges {
                    target: listView
                    opacity: 0
                }
            }
        ]
    
        transitions: [
            Transition {
                PropertyAnimation { properties: "opacity"; duration: 200; }
            }
        ]
    }
    
    }
    

  • Lifetime Qt Champion

    Hi,

    Did you check that the folder exist ?
    The path returned by QStandardPaths will be valid but you have to create some of these folders on first use.



  • What do you mean by that I have to create the standard folder?


  • Lifetime Qt Champion

    Check if the folder exist and if not well create it before creating the image file.



  • how could I achieve that in the code above?


  • Lifetime Qt Champion

    Create the folder ? I would do that in the C++ part on startup using QDir.



  • I think the path should already exist since it is the ApplicationsLocation.

    I tryed this:

        Camera {
            id: camera
        }
        ListModel {
            id: imagePaths
        }
    
    ```
    ListView {
        id: listView
    
        //...
    
        model: imagePaths
    
        delegate: Image {
            height: 100
            source: path
            fillMode: Image.PreserveAspectFit
        }
    
        Rectangle {
            anchors.fill: parent
            anchors.topMargin: -10
    
            color: "black"
            opacity: 0.5
        }
    }
    
    
        ```
    Image {
            id: image
            anchors.fill: parent
        }
    
        Connections {
            target: camera.imageCapture
    
            onImageSaved: {
                imagePaths.append({"path": Labs.StandardPaths.writableLocation(Labs.StandardPaths.ApplicationsLocation)})
                listView.positionViewAtEnd();
            }
        }
    

    So my idea was when camera takes the picture i append in the model imagePaths the ApplicationsLocation Path.

    Then when the delegate is used in the view it should load the Image from path.

    If I try this it sayes QJSValue is not convertible to QDir

    So what is wrong here?


Log in to reply