Ok… So I have a solution, but I’m not sure where it would logically sit in your code so I’ll just paste it here.
To get the rotation of a JPEG in degrees:
// load exif and get rotation for photo
int rotation = 0;
FileInputStream inputStream (file);
if (inputStream.openedOk()) {
juce::OwnedArray<gin::ImageMetadata> metadata;
if (gin::ImageMetadata::getFromImage(inputStream, metadata)) {
for (int i = 0; i < metadata.size(); ++i) {
auto pair = metadata.getUnchecked(i);
if (pair->getType() == "EXIF") {
auto data = pair->getAllMetadata();
auto orientation = data.getValue("Orientation", "-1");
if (orientation == "6") {
rotation = 90;
} else if (orientation == "3") {
rotation = 180;
} else if (orientation == "8") {
rotation = 270;
}
break;
}
}
}
}
I then tried two methods of rotating the photo. The first is to actually change the image data. I do this to my thumbnails before saving them. The trouble is, this is SLOW. It takes 3 seconds in debug mode to rotate a decent sized DLSR jpeg.
void rotateImage(Image &image, int degrees){
auto start = Time::getMillisecondCounter();
if(degrees == 90){
auto rotated = Image(Image::PixelFormat::RGB, image.getHeight(), image.getWidth(), true);
for (int y = 0; y < rotated.getHeight(); ++y) {
for (int x = 0; x < rotated.getWidth(); ++x) {
rotated.setPixelAt(rotated.getWidth() - x,y,image.getPixelAt(y,x));
}
}
image = rotated;
}
else if(degrees == 180){
auto rotated = Image(Image::PixelFormat::RGB, image.getWidth(), image.getHeight(), true);
for (int x = 0; x < rotated.getWidth(); ++x) {
for (int y = 0; y < rotated.getHeight(); ++y) {
rotated.setPixelAt( rotated.getWidth() - x,rotated.getHeight() - y,image.getPixelAt(x,y));
}
}
image = rotated;
}
else if(degrees == 270){
auto rotated = Image(Image::PixelFormat::RGB, image.getHeight(), image.getWidth(), true);
for (int x = 0; x < rotated.getWidth(); ++x) {
for (int y = 0; y < rotated.getHeight(); ++y) {
rotated.setPixelAt( x,rotated.getHeight() - y,image.getPixelAt(y,x));
}
}
image = rotated;
}
else{
jassertfalse;
}
DBG("ImageFunctions::rotateImage() "+ String(degrees) +" "+ String(Time::getMillisecondCounter()- start)+" ms");
}
I think doing the rotation work using Image::BitmapData would be faster, but researching this, I found a better way to do it, which is to rotate the image when drawing it in the paint method, which seems to me to be exactly what the flag was designed for.
auto rotate = AffineTransform::rotation(2 * M_PI * (rotation / 360.0), image.getWidth() / 2.0,image.getHeight() / 0.2);
g.drawImageTransformed(image, rotate);
This is much faster than my original approach. Hope it’s useful to someone.