├── .gitignore ├── LICENSE ├── Landscape_0.jpg ├── Landscape_1.jpg ├── Landscape_2.jpg ├── Landscape_3.jpg ├── Landscape_4.jpg ├── Landscape_5.jpg ├── Landscape_6.jpg ├── Landscape_7.jpg ├── Landscape_8.jpg ├── Makefile ├── Portrait_0.jpg ├── Portrait_1.jpg ├── Portrait_2.jpg ├── Portrait_3.jpg ├── Portrait_4.jpg ├── Portrait_5.jpg ├── Portrait_6.jpg ├── Portrait_7.jpg ├── Portrait_8.jpg ├── README.markdown ├── VERSION └── generator ├── Gemfile └── generate.rb /.gitignore: -------------------------------------------------------------------------------- 1 | /.ruby-gemset 2 | /.ruby-version 3 | /generator/Gemfile.lock 4 | /Landscape.jpg 5 | /Portrait.jpg 6 | /sources 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Dave Perrett, http://recursive-design.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /Landscape_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Landscape_0.jpg -------------------------------------------------------------------------------- /Landscape_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Landscape_1.jpg -------------------------------------------------------------------------------- /Landscape_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Landscape_2.jpg -------------------------------------------------------------------------------- /Landscape_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Landscape_3.jpg -------------------------------------------------------------------------------- /Landscape_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Landscape_4.jpg -------------------------------------------------------------------------------- /Landscape_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Landscape_5.jpg -------------------------------------------------------------------------------- /Landscape_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Landscape_6.jpg -------------------------------------------------------------------------------- /Landscape_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Landscape_7.jpg -------------------------------------------------------------------------------- /Landscape_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Landscape_8.jpg -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: portrait landscape 2 | 3 | portrait: 4 | curl --location https://source.unsplash.com/random/1200x1600 --output ./Portrait.jpg 5 | bash -c "cd generator && ./generate.rb ../Portrait.jpg" 6 | rm -f ./Portrait.jpg 7 | 8 | landscape: 9 | curl --location https://source.unsplash.com/random/1600x1200 --output ./Landscape.jpg 10 | bash -c "cd generator && ./generate.rb ../Landscape.jpg" 11 | rm -f ./Landscape.jpg 12 | -------------------------------------------------------------------------------- /Portrait_0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Portrait_0.jpg -------------------------------------------------------------------------------- /Portrait_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Portrait_1.jpg -------------------------------------------------------------------------------- /Portrait_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Portrait_2.jpg -------------------------------------------------------------------------------- /Portrait_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Portrait_3.jpg -------------------------------------------------------------------------------- /Portrait_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Portrait_4.jpg -------------------------------------------------------------------------------- /Portrait_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Portrait_5.jpg -------------------------------------------------------------------------------- /Portrait_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Portrait_6.jpg -------------------------------------------------------------------------------- /Portrait_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Portrait_7.jpg -------------------------------------------------------------------------------- /Portrait_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recurser/exif-orientation-examples/219294e144531b0c01247913cb58b6f5531b5081/Portrait_8.jpg -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | EXIF Orientation-flag example images 2 | ==================================== 3 | 4 | Example images using each of the EXIF orientation flags (0-to-8), in both landscape and portrait orientations. 5 | 6 | [See here](http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/) for more information. 7 | 8 | 9 | Generating your own images 10 | -------------------------- 11 | 12 | If you would like to generate test images based on your own photos, you can use the `generate.rb` script included in the `generator` folder. 13 | 14 | The instructions below assume you are running on macOS - if not, you will need to install the Ghostscript fonts (`brew install gs`) some other way. 15 | 16 | To install the dependencies: 17 | 18 | ``` 19 | > brew install gs exiftool imagemagick@6 20 | > cd generator 21 | > gem install bundler 22 | > bundle install 23 | ``` 24 | 25 | To generate test images: 26 | 27 | ``` 28 | > cd generator 29 | > ./generate.rb path/to/image.jpg 30 | ``` 31 | 32 | This will create images `image_0.jpg` through to `image_8.jpg`. 33 | 34 | 35 | Re-generating sample images 36 | --------------------------- 37 | 38 | Simply run `make` to regenerate the included sample images. This will download random portrait and landscape orientation images from [unsplash.com](https://unsplash.com/) and generate sample images for each of them. 39 | 40 | Generating these images depends on having the generator dependencies installed - see the *Generating your own images* section for instructions on installing dependencies. 41 | 42 | 43 | Alternatives 44 | ------- 45 | 46 | - [@zchrissirhcz](https://github.com/zchrissirhcz) has [implemented the generator script in Python](https://github.com/zchrissirhcz/exif-orientation-examples/blob/master/generator/generate.py) 47 | 48 | 49 | Credits 50 | ------- 51 | 52 | * The sample landscape image is by [Pierre Bouillot](https://unsplash.com/photos/v15iOM6pWgI). 53 | * The sample portrait image is by [John Salvino](https://unsplash.com/photos/1PPpwrTNkJI). 54 | 55 | 56 | Change history 57 | -------------- 58 | 59 | * **Version 2.0.0 (2017-08-05)** : Add a script to generate example images from the command line. 60 | * **Version 1.0.2 (2017-03-06)** : Remove Apple Copyrighted ICC profile from orientations 2-8 (thanks @mans0954!). 61 | * **Version 1.0.1 (2013-03-10)** : Add MIT license and some contact details. 62 | * **Version 1.0.0 (2012-07-28)** : 1.0 release. 63 | 64 | 65 | Contributing 66 | ------------ 67 | 68 | Once you've made your commits: 69 | 70 | 1. [Fork](http://help.github.com/fork-a-repo/) exif-orientation-examples 71 | 2. Create a topic branch - `git checkout -b my_branch` 72 | 3. Push to your branch - `git push origin my_branch` 73 | 4. Create a [Pull Request](http://help.github.com/pull-requests/) from your branch 74 | 5. That's it! 75 | 76 | 77 | Author 78 | ------ 79 | 80 | Dave Perrett :: hello@daveperrett.com :: [@daveperrett](http://twitter.com/daveperrett) 81 | 82 | 83 | Copyright 84 | --------- 85 | 86 | These images are licensed under the [MIT License](http://opensource.org/licenses/MIT). 87 | 88 | Copyright (c) 2010 Dave Perrett. See [License](https://github.com/recurser/exif-orientation-examples/blob/master/LICENSE) for details. 89 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 2.0.1 2 | -------------------------------------------------------------------------------- /generator/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | ruby '2.6.3' 3 | 4 | gem 'rmagick' 5 | -------------------------------------------------------------------------------- /generator/generate.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Make sure to 'brew install gs' before running this. 4 | 5 | require 'RMagick' 6 | require 'tempfile' 7 | 8 | if ARGV.length != 1 9 | abort "Usage: #{$PROGRAM_NAME} /path/to/image" 10 | end 11 | 12 | # Make sure the file exists. 13 | source = ARGV[0] 14 | abort "Error: File '#{source}' not found" unless File.exist?(source) && File.file?(source) 15 | 16 | # Copy it to the temp directory. 17 | path = Tempfile.new('to-convert').path 18 | FileUtils.cp source, path 19 | 20 | # Make sure it's an image. 21 | image = begin 22 | Magick::Image::read(path).first 23 | rescue Magick::ImageMagickError 24 | abort "Error: File '#{source}' does not appear to be an image." 25 | end 26 | 27 | # Make sure exiftool and convert are available. 28 | abort 'Error: The exiftool command does not appear to be available' if `which exiftool` == '' 29 | abort 'Error: The convert command does not appear to be available' if `which convert` == '' 30 | abort 'Error: the input file must be a JPEG' unless image.format == 'JPEG' 31 | 32 | # Decide where we'll put the output. 33 | dest_folder = File.dirname(source) 34 | dest_file_base = File.basename(source, '.*') 35 | dest_extention = File.extname(source) 36 | 37 | # Strip all exif data. 38 | `exiftool -all= #{path}` 39 | 40 | # Strip color profile info. 41 | FileUtils.cp path, "#{path}.convert" 42 | `convert #{path}.convert +profile "*" #{path}` 43 | FileUtils.rm_f "#{path}.convert" 44 | 45 | # Decide on a suitable font size. 46 | dimension = [image.rows, image.columns].max 47 | font_size = dimension / 20 48 | 49 | # Add top / right / bottom / left text. 50 | text = Magick::Draw.new 51 | text.font_family = 'helvetica' 52 | text.pointsize = font_size 53 | text.fill = 'white' 54 | text.stroke = 'black' 55 | text.stroke_width = 1 56 | edge_padding = font_size / 4 57 | 58 | text.annotate(image, 0, 0, 0, edge_padding, 'top') do 59 | self.gravity = Magick::NorthGravity 60 | end 61 | 62 | text.annotate(image, 0, 0, 0, edge_padding, 'bottom') do 63 | self.gravity = Magick::SouthGravity 64 | end 65 | 66 | text.annotate(image, 0, 0, edge_padding, 0, 'right') do 67 | self.gravity = Magick::EastGravity 68 | end 69 | 70 | text.annotate(image, 0, 0, edge_padding, 0, 'left') do 71 | self.gravity = Magick::WestGravity 72 | end 73 | 74 | transformations = [ 75 | { 76 | exif_tag: 0, 77 | rotation_degrees: 0, 78 | flop: false, 79 | }, 80 | { 81 | exif_tag: 1, 82 | rotation_degrees: 0, 83 | flop: false, 84 | }, 85 | { 86 | exif_tag: 2, 87 | rotation_degrees: 0, 88 | flop: true, 89 | }, 90 | 91 | { 92 | exif_tag: 3, 93 | rotation_degrees: 180, 94 | flop: false, 95 | }, 96 | { 97 | exif_tag: 4, 98 | rotation_degrees: 180, 99 | flop: true, 100 | }, 101 | { 102 | exif_tag: 5, 103 | rotation_degrees: -90, 104 | flop: true, 105 | }, 106 | { 107 | exif_tag: 6, 108 | rotation_degrees: -90, 109 | flop: false, 110 | }, 111 | { 112 | exif_tag: 7, 113 | rotation_degrees: 90, 114 | flop: true, 115 | }, 116 | { 117 | exif_tag: 8, 118 | rotation_degrees: 90, 119 | flop: false, 120 | }, 121 | ] 122 | 123 | transformations.each do |t| 124 | tmp_image = image.dup 125 | 126 | # Add centered text displaying the orientation tag number. 127 | text.annotate(tmp_image, 0, 0, 0, 0, t[:exif_tag].to_s) do 128 | self.gravity = Magick::CenterGravity 129 | text.pointsize = font_size * 2 130 | end 131 | 132 | # Rotate and transform the image. 133 | tmp_image.flop! if t[:flop] 134 | tmp_image.rotate! t[:rotation_degrees] if t[:rotation_degrees] != 0 135 | out_path = File.join(dest_folder, "#{dest_file_base}_#{t[:exif_tag]}#{dest_extention}") 136 | tmp_image.write(out_path) 137 | 138 | # Set the EXIF Orientation tag. 139 | `exiftool -overwrite_original -orientation=#{t[:exif_tag]} -n #{out_path}` 140 | end 141 | --------------------------------------------------------------------------------