Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
Developer
Posts: 358
Registered: ‎04-13-2013
My Device: Z10
My Carrier: Telus
Accepted Solution

Pictures oriented wrong when taken from filepicker

In my app I allow users to take a picture or select a picture using the filepicker.  But when showing the images in an imageView they show up sideways and never in the correct position, regardless of if they were taken without orientation lock, or whatever.  When I invoke the image viewer, howeverm the images are always perfectly oriented.

 

Is there anything I can do in my code to accomodate for this?  The orientation is off in different ways so it's no tlike it's always oritented to the left, sometimes it's to the right, sometimes it's upside down, sometimes it's to the left.

Developer
Posts: 579
Registered: ‎04-01-2009
My Device: Z10, PlayBook
My Carrier: NA

Re: Pictures oriented wrong when taken from filepicker

Hi there,

 

I know exactly what is going on -- I've been working on a photo app for the last year, and I had the same issue.

 

When the camera takes a photo, it adds some EXIF meta data to the JPEG file that indicates its "orientation".

 

In my oppinion, BB should add an option to ImageView such as "autoOrient" so that this would automatically be read and the photo rotated as appropriate before display, but I don't believe such a property exists. Thus, every developer who wants to display photos must add this logic to their app. (inefficient or what?)

 

The good news is that there is a sample app that demonstrates how to do this.  Take a look at the "photobomber" sample app.

 

I will copy and paste some of the relevant code here:

 

QImage PhotoBomberApp::getRotateImage(const QString imageFilePath)
{
    //Load the image using QImage.
    QImage image = QImage(imageFilePath);

    ExifData *exifData = 0;
    ExifEntry *exifEntry = 0;
    int exifOrientation = 1;

    // Since the image will loose its exif data when its opened in a QImage
    // it has to be manually rotated according to the exif orientation.
    exifData = exif_data_new_from_file(imageFilePath.toLatin1().data());

    // Locate the orientation exif information.
    if (exifData != NULL) {
        for (int i = 0; i < EXIF_IFD_COUNT; i++) {
            exifEntry = exif_content_get_entry(exifData->ifd[i], EXIF_TAG_ORIENTATION);

            // If the entry corresponds to the orientation it will be a non zero pointer.
            if (exifEntry) {
                exifOrientation = exif_get_short(exifEntry->data, exif_data_get_byte_order(exifData));
                break;
            }
        }
    }

    // A transform will be used to rotate the image according to device and exif orientation.
    QTransform transform;

    qDebug() << "Exif data&colon;" << exifOrientation;


    // It's a bit tricky to get the correct orientation of the image. A combination of
    // the way the the device is oriented and what the actual exif data says has to be used
    // in order to rotate it in the correct way.
    switch(exifOrientation) {
        case 1:
            // 0 degree rotation
            break;
        case 3:
            // 180 degree rotation
            transform.rotate(180);
            break;
        case 6:
            // 90 degree rotation
            transform.rotate(90);
            break;
        case 8:
            // 270 degree rotation
            transform.rotate(270);
            break;
        default:
            // Other orientations are mirrored orientations, do nothing.
            break;
    }

    // Perform the rotation of the image before its saved.
    image = image.transformed(transform);

    return image;
}

 

This code returns you a QImage, so you may or may not know how to then take that and display it in an ImageView. Incase it's helpful, here's some sample code from my app pertaining to that:

 

QImage thisQImage = getRotateImage(...);

bb::ImageData imageData = bb::ImageData&colon;:fromPixels(thisQImage.rgbSwapped().bits(), bb::PixelFormat::RGBX, thisQImage.width(), thisQImage.height(), thisQImage.bytesPerLine());

bb::cascades::Image cascadesImage = imageData;

imageView->setImage(cascadesImage);

 

One final caution is that doing each of these conversions between image data types takes a bit of time, and so if you do it in the application's main thread, you might or might not slow down the UI.  I've tried moving my image loading into another thread where possible, although I have found (I think) that the conversion to bb::cascades::Image doesn't work properly if it's not in the main thread, so I do that part and the call to setImage in the main thread.

 

Hope that helps. Wish the answer was simpler.

Developer
Posts: 358
Registered: ‎04-13-2013
My Device: Z10
My Carrier: Telus

Re: Pictures oriented wrong when taken from filepicker

Wow thanks! I'll try it when I get home later tonight and mark it accordingly.

Developer
Posts: 358
Registered: ‎04-13-2013
My Device: Z10
My Carrier: Telus

Re: Pictures oriented wrong when taken from filepicker

how would I access the function return in my QML?

Developer
Posts: 579
Registered: ‎04-01-2009
My Device: Z10, PlayBook
My Carrier: NA

Re: Pictures oriented wrong when taken from filepicker

If you're wanting to do this from QML, then you could create a C++ function to do everything, not requring a return value to QML.

 

For example:

 

void MyClass::loadPhoto(QString filePath, ImageView* imageView)

{

...

}

 

 

 

 

Developer
Posts: 824
Registered: ‎10-16-2012
My Device: Red Z10
My Carrier: Telus

Re: Pictures oriented wrong when taken from filepicker

[ Edited ]

If it's only a few images you're showing, or simply 1 at a time it may be easier to just rotate the container that the image is in so it's facing the proper direction (use the previous code to find your orientation and then set a value for rotationZ and then send it to qml).... This eliminates the need to process each image just to make sure its properly orientated.

 

 

 

A auto orientation option for imagviews would be increadibly useful but for that reason alone I doubt we will ever get it.

Developer
Posts: 358
Registered: ‎04-13-2013
My Device: Z10
My Carrier: Telus

Re: Pictures oriented wrong when taken from filepicker

Hmm sending the rotation values might be a bit easier. It's just one temporary image. I invoke the photo viewer in other instances which auto-orients the saved image.

Thanks for the help guys. Will mark accordingly once I figure it out.
Developer
Posts: 824
Registered: ‎10-16-2012
My Device: Red Z10
My Carrier: Telus

Re: Pictures oriented wrong when taken from filepicker

[ Edited ]

This is the code I use to rotate a preview image.

 

**You must set an objectName property to your imageview, in this case I used "preview"

 

What I do is when the source of the image is changed i also notify c++ with the file string from qml

 

QML

ImageView {
id: previewImage
objectName: "preview"
}
onCreationCompleted: {
previewImage.imageSource = imagePath
 
//(cpp. is a context property)
cpp.imagePath(imagePath)
}

 

ApplicationUI.cpp

 

//preview
#include <bb/cascades/ImageView>
#include <libexif/exif-data.h>
 
QString ApplicationUI::imagePath() const
{
return m_imagePath;
}
 
void ApplicationUI::setImagePath(const QString &imagePath)
{
if (m_imagePath== imagePath)
return;
m_imagePath = imagePath;
qDebug() << "m_imagePath - " << imagePath;
emit imagePathChanged();
rotateImage();
}
 
//If the string was the same nothing happens, if it was different it continues on to rotateImage
 
void ApplicationUI::rotateImage()
{
ImageView *image = bb::cascades::Application::instance()->findChild<ImageView*>("preview");
QString url = imagePath().toLatin1();
url.remove("file://");
//qDebug() << "Right FilePath: " << url;
// hold onto this so constData() is valid
QByteArray ba = url.toLocal8Bit();
ExifData* exifData = exif_data_new_from_file(ba.constData());
if (exifData != NULL) {
qDebug() << "exifData is !NULL";
ExifEntry* exifEntry = exif_content_get_entry(exifData->ifd[EXIF_IFD_0],
EXIF_TAG_ORIENTATION);
if (exifEntry != NULL) {
qDebug() << "entry is !NULL";
char value[256] = { 0, };
memset(value, 0, sizeof(value));
exif_entry_get_value(exifEntry, value, sizeof(value));
qDebug() << "Orientation: " << value << endl;
QString orient = QString::fromLocal8Bit(value);
if (orient.compare("bottom-right", Qt::CaseInsensitive) == 0) {
qDebug() << "setting 180";
image->setRotationZ(180);
} else if (orient.compare("right-top", Qt::CaseInsensitive) == 0) {
qDebug() << "setting 90";
image->setRotationZ(90);
} else if (orient.compare("left-bottom", Qt::CaseInsensitive) == 0) {
qDebug() << "setting 270";
image->setRotationZ(270);
} else if (orient.compare("top-left", Qt::CaseInsensitive) == 0){
qDebug() << "setting 0";
image->setRotationZ(0);
} else {
qDebug() << "Unknown Rotation to set";
}
delete exifEntry;
} else {
//qDebug() << "entry is NULL";
}
delete exifData;
} else {
//qDebug() << "exifData is NULL";
}
}

 

 ApplicatinUI.hpp

 

class ApplicationUI : public QObject
{
Q_OBJECT
 
//Set the QProperty for imagePath
Q_PROPERTY(QString imagePath READ imagePath WRITE setImagePath NOTIFY imagePathChanged)
public:
ApplicationUI(bb::cascades::Application *app);
virtual ~ApplicationUI() {}
 
Q_SIGNALS:
// The change notification signals for the properties
void imagePathChanged();
 
private:
// The accessor methods for the properties
void setImagePath(const QString &imagePath);
QString imagePath() const;
void rotateImage();
 

private:
QString m_imagePath;
};

 

Developer
Posts: 358
Registered: ‎04-13-2013
My Device: Z10
My Carrier: Telus

Re: Pictures oriented wrong when taken from filepicker

Wow thanks for the detailed reply. Hopefully I get to it tonight. I really appreciate the responses guys!
Developer
Posts: 824
Registered: ‎10-16-2012
My Device: Red Z10
My Carrier: Telus

Re: Pictures oriented wrong when taken from filepicker

If your interested i put forward a jira request 7 months ago regarding the need for an auto-orientation option in imageviews.  Currently it hasn't been looked into yet

 

https://www.blackberry.com/jira/browse/BBTEN-2091