Code Monkey home page Code Monkey logo

jpeg-autorotate's Introduction

Logo

Build Status Maven Central with version prefix filter javadoc

JPEG Autorotate is a Java library to rotate JPEG images based on EXIF orientation.


Features

Applies the right orientation to a JPEG image, based on its EXIF tag. More precisely, it:

  • Rotates the pixels
  • Rotates the thumbnail, if present
  • Sets the Orientation EXIF tag to 1 (default orientation value)
  • Updates the following metadata values, if present:
    • EXIF
      • ExifImageWidth
      • ExifImageLength
      • RelatedImageWidth
      • RelatedImageHeight
    • XMP
      • tiff:Orientation
      • tiff:ImageWidth
      • tiff:ImageLength
      • exif:PixelXDimension
      • exif:PixelYDimension
      • xmp:ThumbnailsWidth
      • xmp:ThumbnailsHeight
  • Retains and does not alter other metadata tags
  • Currently does not support updating MakerNotes metadata

More information about EXIF metadata is available at:

Installation

Requires Java 8 or later

You can download source from the releases page

Alternatively, you can install the library via its Maven package

<dependency>
    <groupId>com.domenicseccareccia</groupId>
    <artifactId>jpeg-autorotate</artifactId>
    <version>1.1.0</version>
</dependency>

Usage

The library will load an image by either a String file path, File or InputStream, apply rotation, update metadata and return the image as a byte array.

File Path

byte[] image = JpegAutorotate.rotate("path/to/directory");

File

byte[] image = JpegAutorotate.rotate(new File("path/to/directory"));

InputStream

byte[] image = JpegAutorotate.rotate(new FileInputStream(new File("path/to/directory")));

Error Handling

The library throws the following exceptions:

  • JpegAutorotateException
  • FileNotFoundException
    • Only thrown if loading image by either a String file path or File)

Contributing

Contributions are welcome and will be fully credited.

See CONTRIBUTING.md for information on how to contribute to JPEG Autorotate.

Credits

Libraries

This library uses the following libraries:

Logo

The JPEG Autorotate logo uses the following icons from Font Awesome, available under the Creative Commons Attribution 4.0 International License:

The following icon changes were made:

  • Stroke width decreased for all icons by 0.25
  • Detached arrows from sync-alt

Other

License

This code is under the Apache License v2

jpeg-autorotate's People

Contributors

domsec avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

jpeg-autorotate's Issues

Add orientation value exception message for unknown EXIF orientation metadata tag

Description

When a JPEG image does not have a valid EXIF orientation metadata tag value (1 to 8), the exception message thrown does not include the orientation value contained inside the metadata tag. As such, there is lose of information for the error related to the image EXIF metadata.

Propose Solution

Change the exception message as follows:

Location: JpegImageTransform.rotateAndFlip()`

Old Message: "JPEG image has an unknown EXIF Orientation metadata tag."
New Message: "JPEG image has an unknown EXIF Orientation metadata tag value: " + orientation

NPE on images without iccBytes

  • JPEG Autorotate Version: 1.1.0
  • Java Version: 17

It fails on NullPointerException while processing some (any image from Pixel 6 Pro) images, here is the stack trace:

Caused by: java.lang.NullPointerException: Cannot invoke "[B.clone()" because "this.iccBytes" is null at org.apache.commons.imaging.formats.jpeg.segments.App2Segment.getIccBytes(App2Segment.java:90) at org.apache.commons.imaging.formats.jpeg.JpegImageParser.getICCProfileBytes(JpegImageParser.java:295) at org.apache.commons.imaging.Imaging.getICCProfileBytes(Imaging.java:545) at org.apache.commons.imaging.Imaging.getICCProfile(Imaging.java:440) at org.apache.commons.imaging.Imaging.getICCProfile(Imaging.java:363) at org.apache.commons.imaging.Imaging.getICCProfile(Imaging.java:345) at com.domenicseccareccia.jpegautorotate.imaging.JpegImageMetadataReader.readIccProfile(JpegImageMetadataReader.java:118) at com.domenicseccareccia.jpegautorotate.imaging.JpegImageMetadata.<init>(JpegImageMetadata.java:55) at com.domenicseccareccia.jpegautorotate.imaging.JpegImage.<init>(JpegImage.java:35) at com.domenicseccareccia.jpegautorotate.imaging.JpegImageProcessor.process(JpegImageProcessor.java:65) at com.domenicseccareccia.jpegautorotate.JpegAutorotate.rotate(JpegAutorotate.java:157)

JPEG image files
If applicable, add jpeg image files causing the error when processed with JPEG Autorotate.
IMG_20240329_154929_653

Release v1.0.1

Maven

  • Update <version></version> in pom.xml to 1.0.1
  • Deploy to Nexus mvn clean deploy
    • Verify deployed files
  • Release library in Nexus to Maven Central repository (Takes up to 10-15 mins)
    • Verify Maven package is searchable in Maven Central repository (Takes up to 2 hours)

Github

After project is released in Maven Central repository

  • Update README.md
    • Maven dependency version to 1.0.1 in Installation
    • maven-central badge link
    • javadoc badge link
  • Compile jar with dependencies in Maven mvn clean compile assembly:single
  • Create source files .zip and tar.gz
  • Create a new Release
    • Title v1.0.0
    • Changelog
    • Assets
      • jar with dependencies
      • Source files .zip and tar.gz

Automatically rotate JPEG image

Description

Automatically rotate a JPEG image file to the correct orientation based on the EXIF Orientation tag.

Business Rules

Component Description
Image - If metadata Orientation EXIF tag does not equal 1 then rotate to correct orientation
- If metadata Orientation EXIF tag equals 1 then do NOT rotate image
Input - Single image file at a time
- Directory is NOT supported
- java.io.File
- String file path
- InputStream

Supported File Types:
- jpg
- jpeg
- JPG
- JPEG
Output byte[]
Metadata - Update if image is rotated

Update:
- Orientation EXIF tag = 1
- ExifImageWidth EXIF tag
- ExifImageLength EXIF tag
- ImageWidth File tag
- ImageHeight File tag
- XMP metadata

- Remaining metadata must not be altered (ICC Profile, Photoshop, etc)
Thumbnail - If present then rotate to correct orientation
- Rotation based on metadata Orientation EXIF tag not equaling 1

Todo

Image

  • Process image
    • Rotate image
  • Update metadata

Rotations

  • Vertical flip
  • Horizontal flip
  • 90 degrees clockwise
  • 90 degrees counterclockwise

Other

  • Test cases

Java streams not properly closed

  • JPEG Autorotate Version: 1.0.1
  • Java Version: 8

Describe the bug
Java streams (i.e. ByteArrayOutputStream) are either not closed in a finally block or closed at all.

Affected areas:

  • JpegImageProcessor.writeThumbnail
  • JpegImageProcessor.writeImage
  • JpegImageReader.readImage
  • ImageUtils.writeImageToBytes
  • ImageUtilsTest.testWriteImageToBytes
  • JpegAutorotateTest.testRotateAndFlipImage
  • JpegAutorotateTest.testMetadata

Expected behavior
All Java streams no longer in use are to be closed within either a finally or try-with-resources block.

Temp files are not deleted after use

  • JPEG Autorotate Version: [e.g. 1.0.1]
  • Java Version: [11]

Describe the bug
Temp files are not deleted during application runtime, even after they will no longer be used again.

This causes full copies of the every rotated file to be stored in a temporary folder never to be deleted until the application closes. Potentially is causing problems with ethereal storage limits on kubernetes pods that restart/evict pod when using too much temporary disk usage.

Expected behavior
Temp files that are no longer used are cleaned up/deleted.

JPEG image files
All files

Screenshots
temp_file_buildup

Release v1.1.0

Maven

  • Update <version></version> in pom.xml to 1.1.0
  • Deploy to Nexus mvn clean deploy
    • Verify deployed files
  • Release library in Nexus to Maven Central repository (Takes up to 10-15 mins)
    • Verify Maven package is searchable in Maven Central repository (Takes up to 2 hours)

Github

After project is released in Maven Central repository

  • Update README.md
    • Maven dependency version to 1.1.0 in Installation
    • maven-central badge link
    • javadoc badge link
  • Compile jar with dependencies in Maven mvn clean compile assembly:single
  • Create a new Release
    • Title v1.1.0
    • Changelog
    • Assets
      • jar with dependencies

A non JPEG file extension manually changed to .jpg is not rejected

Version

  • JPEG Autorotate Version: 1.0.1
  • Java Version: 8

Describe the Bug

If a non JPEG file (i.e. .png, .doc, .pdf) were to have its extension changed either programically or manually before being passed as a parameter - path or file - to the library, said file will not be rejected as a non JPEG file. As such, the file will be processed instead of being rejected and throwing an exception.

Steps to Reproduce:

  1. Manually change the extension of blue_box.png from .png to .jpg (i.e. blue_box.jpg)
  2. In the ImageUtilsTest class, change the PNG_IMAGE string value from "src/test/resources/blue_box.png" to "src/test/resources/blue_box.jpg"
  3. Run the ImageUtilsTest.testIsJpeg() test case

Expected Behavior

Any non JPEG file where the file extension changes programically or manually before processing by the library should be rejected during initial file type validation and subsequently throw a corresponding exception.

As such, ImageUtilsTest.testIsJpeg() does not fail as the non JPEG image after having its extension manually changed gets rejected.

Actual Behavior

Non JPEG images with manually changed extensions to .jpg are not being rejected and subsequently continue to be processed by the library only to get rejected later on when updating the associated metadata.

When doing such a change to a non JPEG file and then running the ImageUtilsTest.testIsJpeg() test case, it fails.

JPEG Image Files

Screenshots

image
image

Additional Context

N/A

Release v1.0.0

Tasks

Maven

  • Update <version></version> in pom.xml to 1.0.0
  • Deploy to Nexus mvn clean deploy
    • Verify deployed files
  • Release library in Nexus to Maven Central repository (Takes up to 10-15 mins)
    • Verify Maven package is searchable in Maven Central repository (Takes up to 2 hours)

Github

After project is released in Maven Central repository

  • Update README.md
    • Maven dependency version to 1.0.0 in Installation
    • maven-central badge link
    • javadoc badge link
  • Compile jar with dependencies in Maven mvn clean compile assembly:single
  • Create source files .zip and tar.gz
  • Create a new Release
    • Title v1.0.0
    • Changelog
    • Assets
      • jar with dependencies
      • Source files .zip and tar.gz

Update all dependencies

Executed following command in command prompt: mvn versions:display-dependency-updates

The following dependencies in Dependencies have newer versions:
[INFO]   commons-io:commons-io ................................... 2.6 -> 2.8.0
[INFO]   org.apache.commons:commons-imaging .......... 1.0-alpha1 -> 1.0-alpha2
[INFO]   org.junit.jupiter:junit-jupiter-api ................... 5.5.2 -> 5.7.0
[INFO]   org.junit.jupiter:junit-jupiter-engine ................ 5.5.2 -> 5.7.0

Initialize Project

Libraries

  • Java SE 11 (LTS)
  • Apache Commons Imaging (1.0-alpha1)
  • Basic folder structure
  • Main class

Avoiding temp file I/O operations when reading JPEG image byte array

Description

Currently when getting a JPEG image BufferedImage from a byte array, temporary files are being created, read and subsequently deleted. As such, we are creating unnecessary I/O operations (write, read and delete) that could be avoided while also avoiding potential file system permissions problems.

Describe the solution you'd like
Obtain the BufferedImage by reading the byte array using a ByteArrayInputStream. This in turn would both drastically improve performance and reduce the total number of I/O operations.

Such an implementation would have avoided #10 .

Describe alternatives you've considered
N/A

Additional context
Such a refactor must also be done in the respective test cases.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.