ZomoXYZ
ZomoXYZ

Reputation: 1852

FFMPEG rotates images

I am trying to mass-resize images using FFMPEG, and I successfully did it using bash, but I noticed that some of the portrait images got rotated to landscape. Here is the original image, but as you see below, it gets rotated.

Rotated image

As you see above, the image is rotated. At first, I thought this was due to the -vf scale flag that I was using to resize the images, but I tried the following command and it still rotated the image.

ffmpeg -i input.jpg output.jpg

This doesn't happen with every image, and even not all the portrait images. Also, some images rotate clockwise, while some rotate counter-clockwise. And this isn't a random occurrence, all the images that originally rotated still rotate no matter how many times I run the command.

Console Output

ffmpeg version N-79942-gdc34fa6-tessus Copyright (c) 2000-2016 the FFmpeg developers
  built with Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
  configuration: --cc=/usr/bin/clang --prefix=/opt/ffmpeg --as=yasm --extra-version=tessus --enable-avisynth --enable-fontconfig --enable-gpl --enable-libass --enable-libbluray --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopus --enable-libschroedinger --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzmq --enable-version3 --disable-ffplay --disable-indev=qtkit --disable-indev=x11grab_xcb
  libavutil      55. 23.100 / 55. 23.100
  libavcodec     57. 38.100 / 57. 38.100
  libavformat    57. 35.100 / 57. 35.100
  libavdevice    57.  0.101 / 57.  0.101
  libavfilter     6. 44.100 /  6. 44.100
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  0.101 /  2.  0.101
  libpostproc    54.  0.100 / 54.  0.100
Input #0, image2, from '/Users/jaketr00/Desktop/IMG_1902.JPG':
  Duration: 00:00:00.04, start: 0.000000, bitrate: 1025494 kb/s
    Stream #0:0: Video: mjpeg, yuvj422p(pc, bt470bg/unknown/unknown), 5184x3456, 25 tbr, 25 tbn
[image2 @ 0x7ff751803e00] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
Output #0, image2, to '/Users/jaketr00/Desktop/IMG_19022.JPG':
  Metadata:
    encoder         : Lavf57.35.100
    Stream #0:0: Video: mjpeg, yuvj422p(pc), 5184x3456, q=2-31, 200 kb/s, 25 fps, 25 tbn
    Metadata:
      encoder         : Lavc57.38.100 mjpeg
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
Stream mapping:
  Stream #0:0 -> #0:0 (mjpeg (native) -> mjpeg (native))
Press [q] to stop, [?] for help
frame=    1 fps=0.0 q=8.2 size=N/A time=00:00:00.04 bitrate=N/A speed=0.0753x   frame=    1 fps=0.0 q=8.2 Lsize=N/A time=00:00:00.04 bitrate=N/A speed=0.0752x    
video:554kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown

Is there any way to stop this from happening?

Upvotes: 11

Views: 9625

Answers (7)

mivk
mivk

Reputation: 14824

ffmpeg doesn't seem to be the right tool for the job. Except maybe at the end, if you want to assemble the .jpg images into a video.

If you do use ffmpeg to make a video with your images, you don't need to first resize them. ffmpeg can scale them to the video size you want.

To rotate the images according to their Exif Orientation tag, and do it losslessly, you can for example use exiftran:

exiftran -a -i -b *.jpg

The meaning of the flags used:

-a     Automatic (using exif orientation tag).
-i     Enable in-place editing of the images.
-b     Create a backup file when doing in-place editing 

After that, you can use ffmpeg to assemble them into a video. For example:

ffmpeg -framerate 1/3 -pattern_type glob -i '*.jpg' \
 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2,setsar=1" \
 -c:v libx264 -crf 20 -r 25 -pix_fmt yuv420p \
 OUTPUT.MP4

If you do need resized jpegs with the correct orientation, you could use ImageMagick's mogrify. For example :

mogrify -path /path/to/new_images \
 -auto-orient -resize "1920x1080>" \
 -background black -gravity center -extent 1920x1080 *.jpg

The > at the end of the resize dimensions means to only resize larger images, not smaller ones.

Upvotes: 0

kernel panic
kernel panic

Reputation: 1

I had a similar problem when tried to make thumbnails from photos and got wrong orientation
So i found that ffmpeg transpose works perfectly for me
But i have no idea how it is optimal from point of performance
What i did:

   std::string transpose = buildTransposeCommand(exif);
   sprintf((char *) commandBuf,
        "%s -i \"%s\" -vf \"scale=320:-1:sws_flags=sinc, %s\" \"%s\" -y\n",
        FFMPEG_PATH,
        in_path_.c_str(),
        transpose.c_str(),
        out_path_.c_str()
   );
    std::string Thumbnail::buildTransposeCommand(int & exif) {
        std::string transpose;
        if (exif == 6) transpose = "transpose=clock";
        else if (exif == 8) transpose = "transpose=cclock";
        else if (exif == 3) transpose = "transpose=clock,transpose=clock";
        else if (exif == 2) transpose = "transpose=clock_flip,transpose=cclock";
        else if (exif == 5) transpose = "transpose=cclock_flip";
        else if (exif == 7) transpose = "transpose=cclock_flip,transpose=clock,transpose=clock";
        else if (exif == 4) transpose = "transpose=clock_flip,transpose=clock";
        return transpose;
    }

I highly recommend uses that https://github.com/ianare/exif-samples samples for testing it helped me a lot
Take a look at the orientation folder

Upvotes: 0

rampanwar
rampanwar

Reputation: 318

You will have to run for all existing images on your system directory. Because there is no option available with ffmpeg to remove the need of exiftool for keeping orientation. I didn't want to install and include ImageMagick just for this particular issue. As I was already using ffmpeg for video conversion.

Adding -noautorotate has no effect in the ffmpeg command. So here is a bit more detailed version of @alijandro answer, with nodejs script I've got to preserve meta-data for orientation using example code from here. Also this works great with your sample image.

const ffmpeg = require("ffmpeg");
const exiftool = require("node-exiftool");
const exiftoolBin = require("dist-exiftool");
const sizeOf = require("image-size");

const ep = new exiftool.ExiftoolProcess(exiftoolBin);
let metaData = {};
ep.open()
  .then(() => ep.readMetadata('input-img.jpeg', ["-File:all"]))
  .then((data) => {
    console.log("meta read");
    metaData = data;
  }, console.error)
  .then((data) => {
    const d = sizeOf('input-img.jpeg');
    const sizeFactor = d.height > d.width ? `-1:${maxH}` : `${maxW}:-1`;
    exec(
     `ffmpeg -noautorotate -i input-img.jpeg -vf scale="${sizeFactor}" -y output-img.jpeg`, 
      (err) => {
        // handle error
        console.log("resized");
        ep.open()
          .then((data) => {
            console.log("meta write");
            ep.writeMetadata('output-img.jpeg', metaData.data[0], ["overwrite_original"]);
          }, console.error)
          .then(() => ep.close())
          .catch(console.error);
      }
    );
  }, console.error)
  .then(() => ep.close())
  .catch(console.error);

Upvotes: -1

nzwlm
nzwlm

Reputation: 147

i ran into the same problem and realised that the image's orientation tag was not preserved when using ffmpeg.

original image

$ exiftool -Orientation input.jpg 
Orientation                     : Rotate 90 CW

full output:

$ identify -verbose input.jpg 
Image: input.jpg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Mime type: image/jpeg
  Class: DirectClass
  Geometry: 4160x3120+0+0
  Resolution: 72x72
  Print size: 57.7778x43.3333
  Units: PixelsPerInch
  Colorspace: sRGB
  Type: TrueColor
  Base type: Undefined
  Endianess: Undefined
  Depth: 8-bit
  Channel depth:
    Red: 8-bit
    Green: 8-bit
    Blue: 8-bit
  Channel statistics:
    Pixels: 12979200
    Red:
      min: 0  (0)
      max: 255 (1)
      mean: 108.185 (0.424255)
      standard deviation: 61.0896 (0.239567)
      kurtosis: -0.901126
      skewness: -0.248333
      entropy: 0.945001
    Green:
      min: 0  (0)
      max: 255 (1)
      mean: 105.661 (0.414356)
      standard deviation: 60.1866 (0.236026)
      kurtosis: -0.9917
      skewness: -0.0344804
      entropy: 0.963995
    Blue:
      min: 0  (0)
      max: 255 (1)
      mean: 93.8873 (0.368186)
      standard deviation: 63.4227 (0.248716)
      kurtosis: -1.00629
      skewness: 0.325207
      entropy: 0.958324
  Image statistics:
    Overall:
      min: 0  (0)
      max: 255 (1)
      mean: 102.578 (0.402265)
      standard deviation: 61.5663 (0.241436)
      kurtosis: -1.03922
      skewness: 0.0137682
      entropy: 0.955774
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Matte color: grey74
  Background color: white
  Border color: srgb(223,223,223)
  Transparent color: none
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 4160x3120+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: JPEG
  Quality: 98
  Orientation: RightTop
  Properties:
    date:create: 2019-05-01T16:09:43+00:00
    date:modify: 2019-05-01T16:09:43+00:00
    exif:ApertureValue: 200/100
    exif:BrightnessValue: 0/100
    exif:ColorSpace: 1
    exif:ComponentsConfiguration: 1, 2, 3, 0
    exif:DateTime: 2019:05:01 10:15:04
    exif:DateTimeDigitized: 2019:05:01 10:15:04
    exif:DateTimeOriginal: 2019:05:01 10:15:04
    exif:ExifOffset: 285
    exif:ExifVersion: 48, 50, 50, 48
    exif:ExposureBiasValue: 0/6
    exif:ExposureMode: 0
    exif:ExposureProgram: 0
    exif:ExposureTime: 9994945/1000000000
    exif:Flash: 0
    exif:FlashPixVersion: 48, 49, 48, 48
    exif:FNumber: 200/100
    exif:FocalLength: 3580/1000
    exif:FocalLengthIn35mmFilm: 0
    exif:GPSInfo: 831
    exif:ImageLength: 3120
    exif:ImageWidth: 4160
    exif:InteroperabilityOffset: 801
    exif:Make: HMD Global
    exif:MakerNote: 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 131, 37, 0, 0, 208, 7, 33, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 203, 2, 104, 1, 0, 0, 0, 0
    exif:MeteringMode: 0
    exif:Model: Nokia 8
    exif:Orientation: 6
    exif:PhotographicSensitivity: 100
    exif:PixelXDimension: 4160
    exif:PixelYDimension: 3120
    exif:ResolutionUnit: 2
    exif:SceneCaptureType: 0
    exif:SceneType: 0
    exif:SensingMethod: 0
    exif:ShutterSpeedValue: 6644/1000
    exif:Software: TA-1004_00WW-user 9 PPR1.180610.011 00WW_5_14A release-keys
    exif:SubSecTime: 733
    exif:SubSecTimeDigitized: 733
    exif:SubSecTimeOriginal: 733
    exif:thumbnail:Compression: 6
    exif:thumbnail:InteroperabilityIndex: R98
    exif:thumbnail:InteroperabilityVersion: 48, 49, 48, 48
    exif:thumbnail:JPEGInterchangeFormat: 943
    exif:thumbnail:JPEGInterchangeFormatLength: 6845
    exif:thumbnail:Orientation: 6
    exif:thumbnail:ResolutionUnit: 2
    exif:thumbnail:XResolution: 72/1
    exif:thumbnail:YResolution: 72/1
    exif:WhiteBalance: 0
    exif:XResolution: 72/1
    exif:YCbCrPositioning: 1
    exif:YResolution: 72/1
    jpeg:colorspace: 2
    jpeg:sampling-factor: 2x2,1x1,1x1
    signature: d450d8dbb135c549364b3663c8195164a73698999b8104e75c8b74564835986f
  Profiles:
    Profile-exif: 7794 bytes
  Artifacts:
    verbose: true
  Tainted: False
  Filesize: 6.05972MiB
  Number pixels: 12979200
  Pixels per second: 82.8219MP
  User time: 0.150u
  Elapsed time: 0:01.156
  Version: ImageMagick 7.0.8-42 Q16 x86_64 2019-04-24 https://imagemagick.org

modified image

$ exiftool -Orientation output.jpg 

full output:

$ identify -verbose output.jpg 
Image: output.jpg
  Format: JPEG (Joint Photographic Experts Group JFIF format)
  Mime type: image/jpeg
  Class: DirectClass
  Geometry: 1800x1350+0+0
  Units: Undefined
  Colorspace: sRGB
  Type: TrueColor
  Base type: Undefined
  Endianess: Undefined
  Depth: 8-bit
  Channel depth:
    Red: 8-bit
    Green: 8-bit
    Blue: 8-bit
  Channel statistics:
    Pixels: 2430000
    Red:
      min: 0  (0)
      max: 255 (1)
      mean: 108.075 (0.423823)
      standard deviation: 60.7286 (0.238152)
      kurtosis: -0.889179
      skewness: -0.260768
      entropy: 0.940096
    Green:
      min: 0  (0)
      max: 255 (1)
      mean: 105.629 (0.414232)
      standard deviation: 59.6505 (0.233924)
      kurtosis: -0.993155
      skewness: -0.0409431
      entropy: 0.957277
    Blue:
      min: 0  (0)
      max: 255 (1)
      mean: 93.7942 (0.367821)
      standard deviation: 63.0086 (0.247093)
      kurtosis: -1.00904
      skewness: 0.322794
      entropy: 0.957105
  Image statistics:
    Overall:
      min: 0  (0)
      max: 255 (1)
      mean: 102.499 (0.401958)
      standard deviation: 61.1293 (0.239723)
      kurtosis: -1.03828
      skewness: 0.00662106
      entropy: 0.951493
  Rendering intent: Perceptual
  Gamma: 0.454545
  Chromaticity:
    red primary: (0.64,0.33)
    green primary: (0.3,0.6)
    blue primary: (0.15,0.06)
    white point: (0.3127,0.329)
  Matte color: grey74
  Background color: white
  Border color: srgb(223,223,223)
  Transparent color: none
  Interlace: None
  Intensity: Undefined
  Compose: Over
  Page geometry: 1800x1350+0+0
  Dispose: Undefined
  Iterations: 0
  Compression: JPEG
  Quality: 72
  Orientation: Undefined
  Properties:
    comment: Lavc58.35.100
    date:create: 2019-05-01T16:09:44+00:00
    date:modify: 2019-05-01T16:09:44+00:00
    jpeg:colorspace: 2
    jpeg:sampling-factor: 2x2,1x1,1x1
    signature: 76f0debf16f9a958b603a08a706b825e4700093b28b57470a34361b396da612d
  Artifacts:
    verbose: true
  Tainted: False
  Filesize: 105397B
  Number pixels: 2430000
  Pixels per second: 117.945MP
  User time: 0.020u
  Elapsed time: 0:01.020
  Version: ImageMagick 7.0.8-42 Q16 x86_64 2019-04-24 https://imagemagick.org

solution

to fix this i did included some code in my bash script to read the orientation from the original file ($file). then i update the orientation for the output file ($outfile).

# read orientation from original image
orientation=$(exiftool -Orientation -n -S $file | grep -Eo '[0-9]{1,4}')

# scale image
ffmpeg -i $file -vf "scale='min($ffmpeg_maxwidth,iw)':-1" $outfile

# set orientation value for the new image
exiftool -n -Orientation=$orientation $outfile

Upvotes: 5

Majid
Majid

Reputation: 336

@Jaketr00, I know this might be too late for you finding this answer, but I hope it may help others with the same problem. All you need to do to avoid this problem is using "transpose" feature. Lets say you want to draw a Red horizontal line in the middle of your portrait image. the following command will do the job without unwanted rotating. The output will have the same scales as your input file.

ffmpeg -i test.jpg -filter_complex "[0]transpose=1[tr]; color=red:s=300x500,geq=lum='p(X,Y)':a='if(eq(250,Y),255,0)'[c]; [tr][c]overlay=0:0:shortest=1" test_out.jpg`

The same works for any other filter as well. you just need to adapt this command with your filter of choice.

Upvotes: 2

alijandro
alijandro

Reputation: 12147

Try to add the options -noautorotate to your ffmpeg commandline.

Besides, use exiftool to backup the exif information, after apply the scale by ffmpeg, resotre the backup exif information.

for f in *.jpg
do 
    # save exif information
    ffmpeg -noautorotate -i input.jpg -vf "scale=w:h" output.jpg
    # retore exif information
done

Upvotes: 1

user149341
user149341

Reputation:

What's probably the case here is that your files are all stored in landscape format, but some of them have EXIF tags indicating that they should be displayed rotated. (Many cameras will automatically generate these tags for pictures you take based on the orientation of the camera.) ffmpeg does not recognize these tags, so the images are read exactly as they're stored in the file.

ffmpeg is primarily a video conversion tool, not an image conversion tool, so I don't think it has any way to read EXIF tags. However, the convert tool (part of ImageMagick) does; you can use the -auto-orient flag to activate this feature.

Upvotes: 6

Related Questions