How to fix rotated image from camera in Flutter?

1 minute read

When using camera package in Flutter it often happens that the picture rotation is messed up. For instance the image may be rotated by 90 degrees in the Image.file() widget.

Note: This article was written in March 2020. Since then many things have changed around how camera works in Flutter. This solution may not be optimal for your case as it’s essentially copying the file.

There were many issues on GitHub and SO that mention this like this, this, this and this.

There are multiple solutions for this (e.g. using native plugins), but my favorite is just to check for image size and exif data, and then just rotate the image accordingly with the image package. All in Dart without the need of a native plugin.

Let’s get straight to the code. There are some explanations in the comments.

import 'dart:io';
import 'package:exif/exif.dart';
import 'package:image/image.dart' as img;

Future<File> fixExifRotation(String imagePath) async {
    final originalFile = File(imagePath);
    List<int> imageBytes = await originalFile.readAsBytes();

    final originalImage = img.decodeImage(imageBytes);

    final height = originalImage.height;
    final width = originalImage.width;

    // Let's check for the image size
    if (height >= width) {
      // I'm interested in portrait photos so
      // I'll just return here
      return originalFile;
    }

    // We'll use the exif package to read exif data
    // This is map of several exif properties
    // Let's check 'Image Orientation'
    final exifData = await readExifFromBytes(imageBytes);

    img.Image fixedImage;

    if (height < width) {
      logger.logInfo('Rotating image necessary');
      // rotate
      if (exifData['Image Orientation'].printable.contains('Horizontal')) {
        fixedImage = img.copyRotate(originalImage, 90);
      } else if (exifData['Image Orientation'].printable.contains('180')) {
        fixedImage = img.copyRotate(originalImage, -90);
      } else {
        fixedImage = img.copyRotate(originalImage, 0);
      }
    }

    // Here you can select whether you'd like to save it as png
    // or jpg with some compression
    // I choose jpg with 100% quality
    final fixedFile =
        await originalFile.writeAsBytes(img.encodeJpg(fixedImage));

    return fixedFile;
  }

I hope this helped you.

Updated: