You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "snumlautoken (via GitHub)" <gi...@apache.org> on 2023/03/07 09:38:24 UTC

[GitHub] [commons-imaging] snumlautoken opened a new pull request, #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

snumlautoken opened a new pull request, #283:
URL: https://github.com/apache/commons-imaging/pull/283

   This PR is for an issue whose 10th anniversary was a week ago, so might not be the most important issue.
   
   Nevertheless, we feel as though, among metadata operations, rotation is probably the one most commonly used, and thus most deserving of a more streamlined process.
    
   We also feel that our contribution could serve as a base for other streamlinings of exif-data manipulation, such as for GPS-data.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] snumlautoken commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "snumlautoken (via GitHub)" <gi...@apache.org>.
snumlautoken commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1461802204

   Re-requesting review as the change is still requested
   Just making sure that a misunderstandiung has not occured


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] snumlautoken commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "snumlautoken (via GitHub)" <gi...@apache.org>.
snumlautoken commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1457939519

   @kinow 
   We have been working as a group, and have thus been aiming to work in a very fractured manner, with many small commits. So no error on that front.
   But a squash may have been appropriate...


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] kinow commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "kinow (via GitHub)" <gi...@apache.org>.
kinow commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1461849986

   No misunderstanding. Just busy, sorry. Thanks for checking though đź‘Ť


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files [commons-imaging]

Posted by "StefanOltmann (via GitHub)" <gi...@apache.org>.
StefanOltmann commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1802449985

   @snumlautoken I share your opinion about the importance about the orientation flag. That’s why I recently wrote a logic dedicated to finding and updating that flag.
   
   You may want to rewrite https://github.com/Ashampoo/kim/blob/main/src/commonMain/kotlin/com/ashampoo/kim/format/jpeg/JpegOrientationOffsetFinder.kt in Java and contribute this. :)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] kinow commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "kinow (via GitHub)" <gi...@apache.org>.
kinow commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1457978163

   >We have been working as a group (school project)
   
   Interesting!
   
   >and have thus been aiming to work in a very fractured manner, with many small commits. So no error on that front.
   
   Got it.
   
   >But a squash may have been appropriate... 
   
   Yes, please it is alright to have multiple commits as long as it is intentional and with a good reason.but otherwise squashed it is.
   
   Thanks!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] kinow commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "kinow (via GitHub)" <gi...@apache.org>.
kinow commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1458336767

   > Maybe not the ideal way to add co-authors, but this will hopefully work
   
   If you would like to credit others, we can add it to the `src/changes/changes.xml`. That's where we record the entry for the issue (`IMAGING-105`). Alternatively, you can add multiple authors to a commit too - e.g. https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors (feel free to edit your commit and `push -f` to this branch as you did, until you are happy with the code :+1: )


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] snumlautoken commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "snumlautoken (via GitHub)" <gi...@apache.org>.
snumlautoken commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1458341847

   > e.g. https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors
   
   That was the way I added them, so it should be fine as it is!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] codecov-commenter commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "codecov-commenter (via GitHub)" <gi...@apache.org>.
codecov-commenter commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1457855371

   # [Codecov](https://codecov.io/gh/apache/commons-imaging/pull/283?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) Report
   > Merging [#283](https://codecov.io/gh/apache/commons-imaging/pull/283?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (ff4045d) into [master](https://codecov.io/gh/apache/commons-imaging/commit/ff13fa4f70d162f0be685e8a94e3706cfa71f989?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) (ff13fa4) will **increase** coverage by `0.03%`.
   > The diff coverage is `72.88%`.
   
   ```diff
   @@             Coverage Diff              @@
   ##             master     #283      +/-   ##
   ============================================
   + Coverage     70.74%   70.78%   +0.03%     
   - Complexity     3369     3381      +12     
   ============================================
     Files           332      333       +1     
     Lines         16942    17001      +59     
     Branches       2647     2655       +8     
   ============================================
   + Hits          11986    12034      +48     
   - Misses         3910     3918       +8     
   - Partials       1046     1049       +3     
   ```
   
   
   | [Impacted Files](https://codecov.io/gh/apache/commons-imaging/pull/283?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation) | Coverage Δ | |
   |---|---|---|
   | [...ing/formats/jpeg/exif/ExifOrientationRewriter.java](https://codecov.io/gh/apache/commons-imaging/pull/283?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL21haW4vamF2YS9vcmcvYXBhY2hlL2NvbW1vbnMvaW1hZ2luZy9mb3JtYXRzL2pwZWcvZXhpZi9FeGlmT3JpZW50YXRpb25SZXdyaXRlci5qYXZh) | `72.88% <72.88%> (ø)` | |
   | [.../commons/imaging/formats/jpeg/JpegImageParser.java](https://codecov.io/gh/apache/commons-imaging/pull/283?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL21haW4vamF2YS9vcmcvYXBhY2hlL2NvbW1vbnMvaW1hZ2luZy9mb3JtYXRzL2pwZWcvSnBlZ0ltYWdlUGFyc2VyLmphdmE=) | `55.17% <0.00%> (+0.49%)` | :arrow_up: |
   | [...ommons/imaging/formats/tiff/TiffImageMetadata.java](https://codecov.io/gh/apache/commons-imaging/pull/283?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL21haW4vamF2YS9vcmcvYXBhY2hlL2NvbW1vbnMvaW1hZ2luZy9mb3JtYXRzL3RpZmYvVGlmZkltYWdlTWV0YWRhdGEuamF2YQ==) | `29.08% <0.00%> (+0.79%)` | :arrow_up: |
   | [...ons/imaging/common/bytesource/ByteSourceArray.java](https://codecov.io/gh/apache/commons-imaging/pull/283?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation#diff-c3JjL21haW4vamF2YS9vcmcvYXBhY2hlL2NvbW1vbnMvaW1hZ2luZy9jb21tb24vYnl0ZXNvdXJjZS9CeXRlU291cmNlQXJyYXkuamF2YQ==) | `76.92% <0.00%> (+7.69%)` | :arrow_up: |
   
   :mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=The+Apache+Software+Foundation)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] snumlautoken commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "snumlautoken (via GitHub)" <gi...@apache.org>.
snumlautoken commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1458009069

   Should we send in a new, squashed, PR?
   Or just let it be?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] snumlautoken commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "snumlautoken (via GitHub)" <gi...@apache.org>.
snumlautoken commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1458299315

   Maybe not the ideal way to add co-authors, but this will hopefully work


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] kinow commented on pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "kinow (via GitHub)" <gi...@apache.org>.
kinow commented on PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#issuecomment-1458151846

   > Should we send in a new, squashed, PR? Or just let it be?
   
   We can use this PR. You should be able to squash the commits in this PR, then `push -f` to your branch. 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


[GitHub] [commons-imaging] kinow commented on a diff in pull request #283: [IMAGING-105] Add methods for editing EXIF-value for rotation for jpeg-files

Posted by "kinow (via GitHub)" <gi...@apache.org>.
kinow commented on code in PR #283:
URL: https://github.com/apache/commons-imaging/pull/283#discussion_r1139419012


##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {
+
+    public enum Orientation {
+        HORIZONTAL((short)1),
+        MIRROR_HORIZONTAL((short)2),
+        ROTATE_180((short)3),
+        MIRROR_VERTICAL((short)4),
+        MIRROR_HORIZONTAL_AND_ROTATE_270((short)5),
+        ROTATE_90((short)6),
+        MIRROR_HORIZONTAL_AND_ROTATE_90((short)7),
+        ROTATE_270((short)8);
+
+        private short val;
+
+        Orientation(short orVal) {
+            this.val = orVal;
+        }
+
+        public short getVal() {
+            return val;
+        }
+    }
+
+    private ByteSource fileSrc;
+
+    public ExifOrientationRewriter(File imageFile) {
+        fileSrc = new ByteSourceFile(imageFile);
+    }
+    public ExifOrientationRewriter(byte[] byteArray) {
+        fileSrc = new ByteSourceArray(byteArray);
+    }
+    public ExifOrientationRewriter(ByteSource byteSource) {
+        fileSrc = byteSource;
+    }
+
+    /***
+     * Get the orientation (enum) of the current image
+     * Returns horizontal by default
+     * @return Orientation enum
+     * @throws IOException
+     * @throws ImageReadException
+     * @throws ImageWriteException

Review Comment:
   These also need a comment explaining the exceptions.



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {
+
+    public enum Orientation {
+        HORIZONTAL((short)1),
+        MIRROR_HORIZONTAL((short)2),
+        ROTATE_180((short)3),
+        MIRROR_VERTICAL((short)4),
+        MIRROR_HORIZONTAL_AND_ROTATE_270((short)5),
+        ROTATE_90((short)6),
+        MIRROR_HORIZONTAL_AND_ROTATE_90((short)7),
+        ROTATE_270((short)8);
+
+        private short val;
+
+        Orientation(short orVal) {
+            this.val = orVal;
+        }
+
+        public short getVal() {
+            return val;
+        }
+    }
+
+    private ByteSource fileSrc;
+
+    public ExifOrientationRewriter(File imageFile) {
+        fileSrc = new ByteSourceFile(imageFile);
+    }
+    public ExifOrientationRewriter(byte[] byteArray) {
+        fileSrc = new ByteSourceArray(byteArray);
+    }
+    public ExifOrientationRewriter(ByteSource byteSource) {
+        fileSrc = byteSource;
+    }
+
+    /***
+     * Get the orientation (enum) of the current image
+     * Returns horizontal by default
+     * @return Orientation enum
+     * @throws IOException
+     * @throws ImageReadException
+     * @throws ImageWriteException
+     */
+    public Orientation getExifOrientation() throws IOException, ImageReadException, ImageWriteException {
+
+        final JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffImageMetadata exifMetadata = metadata.getExif();
+
+        if (exifMetadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffOutputSet outputSet = exifMetadata.getOutputSet();
+
+        TiffOutputDirectory tod = outputSet.getRootDirectory();
+        if (tod == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        TiffOutputField tof = tod.findField(TiffTagConstants.TIFF_TAG_ORIENTATION);
+        if (tof == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        short imageOrientationVal = (short) exifMetadata.getFieldValue(TiffTagConstants.TIFF_TAG_ORIENTATION);
+
+        for (Orientation orientation : Orientation.values()) {
+            if(orientation.getVal() == imageOrientationVal) {
+                return orientation;
+            }
+        }
+
+        return Orientation.HORIZONTAL;
+    }
+
+    /**
+     * A method that sets a new value to the orientation field in the EXIF metadata of a JPEG file.
+     * @param orientation the value as a enum of the direction to set as the new EXIF orientation
+     *
+     */
+    public void setExifOrientation(Orientation orientation) throws ImageWriteException, IOException, ImageReadException {
+
+        JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            metadata = new JpegImageMetadata(null, new TiffImageMetadata(new TiffContents(new TiffHeader(ByteOrder.BIG_ENDIAN, 0, 0), new ArrayList<>(), new ArrayList<>())));
+        }
+
+        TiffImageMetadata exifMetadata = metadata.getExif();
+
+        if (exifMetadata == null) {
+            exifMetadata = new TiffImageMetadata(new TiffContents(new TiffHeader(ByteOrder.BIG_ENDIAN, 0, 0), new ArrayList<>(), new ArrayList<>()));
+        }
+
+        final TiffOutputSet outputSet = exifMetadata.getOutputSet();
+
+        TiffOutputDirectory tod =  outputSet.getOrCreateRootDirectory();
+        tod.removeField(TiffTagConstants.TIFF_TAG_ORIENTATION);
+        tod.add(TiffTagConstants.TIFF_TAG_ORIENTATION, orientation.getVal());
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        new ExifRewriter().updateExifMetadataLossy(this.fileSrc, baos, outputSet);
+
+        this.fileSrc = new ByteSourceArray(baos.toByteArray());
+    }
+
+    /**
+     * @return the ByteSource of the current file
+     */
+    public ByteSource getOutput() {
+        return fileSrc;
+    }
+
+    /**
+     *  Writes Bytesource to file with given path

Review Comment:
   Extra space before Writes, and s/Bytesource/ByteSource



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {
+
+    public enum Orientation {
+        HORIZONTAL((short)1),
+        MIRROR_HORIZONTAL((short)2),
+        ROTATE_180((short)3),
+        MIRROR_VERTICAL((short)4),
+        MIRROR_HORIZONTAL_AND_ROTATE_270((short)5),
+        ROTATE_90((short)6),
+        MIRROR_HORIZONTAL_AND_ROTATE_90((short)7),
+        ROTATE_270((short)8);
+
+        private short val;
+
+        Orientation(short orVal) {
+            this.val = orVal;
+        }
+
+        public short getVal() {
+            return val;
+        }
+    }
+
+    private ByteSource fileSrc;
+
+    public ExifOrientationRewriter(File imageFile) {
+        fileSrc = new ByteSourceFile(imageFile);
+    }
+    public ExifOrientationRewriter(byte[] byteArray) {
+        fileSrc = new ByteSourceArray(byteArray);
+    }
+    public ExifOrientationRewriter(ByteSource byteSource) {
+        fileSrc = byteSource;
+    }
+
+    /***
+     * Get the orientation (enum) of the current image

Review Comment:
   Needs a dot. The other sentence can come directly after this one, or leave it in the next line (or if you intended to have two lines, use HTML to add a break line, new paragraph, etc.).



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {

Review Comment:
   Missing javadoc with `@since` tag (see other classes).



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {
+
+    public enum Orientation {
+        HORIZONTAL((short)1),
+        MIRROR_HORIZONTAL((short)2),
+        ROTATE_180((short)3),
+        MIRROR_VERTICAL((short)4),
+        MIRROR_HORIZONTAL_AND_ROTATE_270((short)5),
+        ROTATE_90((short)6),
+        MIRROR_HORIZONTAL_AND_ROTATE_90((short)7),
+        ROTATE_270((short)8);
+
+        private short val;
+
+        Orientation(short orVal) {
+            this.val = orVal;
+        }
+
+        public short getVal() {
+            return val;
+        }
+    }
+
+    private ByteSource fileSrc;
+
+    public ExifOrientationRewriter(File imageFile) {
+        fileSrc = new ByteSourceFile(imageFile);
+    }
+    public ExifOrientationRewriter(byte[] byteArray) {
+        fileSrc = new ByteSourceArray(byteArray);
+    }
+    public ExifOrientationRewriter(ByteSource byteSource) {
+        fileSrc = byteSource;
+    }
+
+    /***
+     * Get the orientation (enum) of the current image
+     * Returns horizontal by default
+     * @return Orientation enum
+     * @throws IOException
+     * @throws ImageReadException
+     * @throws ImageWriteException
+     */
+    public Orientation getExifOrientation() throws IOException, ImageReadException, ImageWriteException {
+
+        final JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffImageMetadata exifMetadata = metadata.getExif();
+
+        if (exifMetadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffOutputSet outputSet = exifMetadata.getOutputSet();
+
+        TiffOutputDirectory tod = outputSet.getRootDirectory();
+        if (tod == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        TiffOutputField tof = tod.findField(TiffTagConstants.TIFF_TAG_ORIENTATION);
+        if (tof == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        short imageOrientationVal = (short) exifMetadata.getFieldValue(TiffTagConstants.TIFF_TAG_ORIENTATION);
+
+        for (Orientation orientation : Orientation.values()) {
+            if(orientation.getVal() == imageOrientationVal) {
+                return orientation;
+            }
+        }
+
+        return Orientation.HORIZONTAL;
+    }
+
+    /**
+     * A method that sets a new value to the orientation field in the EXIF metadata of a JPEG file.
+     * @param orientation the value as a enum of the direction to set as the new EXIF orientation
+     *
+     */
+    public void setExifOrientation(Orientation orientation) throws ImageWriteException, IOException, ImageReadException {
+
+        JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            metadata = new JpegImageMetadata(null, new TiffImageMetadata(new TiffContents(new TiffHeader(ByteOrder.BIG_ENDIAN, 0, 0), new ArrayList<>(), new ArrayList<>())));
+        }
+
+        TiffImageMetadata exifMetadata = metadata.getExif();
+
+        if (exifMetadata == null) {
+            exifMetadata = new TiffImageMetadata(new TiffContents(new TiffHeader(ByteOrder.BIG_ENDIAN, 0, 0), new ArrayList<>(), new ArrayList<>()));
+        }
+
+        final TiffOutputSet outputSet = exifMetadata.getOutputSet();
+
+        TiffOutputDirectory tod =  outputSet.getOrCreateRootDirectory();
+        tod.removeField(TiffTagConstants.TIFF_TAG_ORIENTATION);
+        tod.add(TiffTagConstants.TIFF_TAG_ORIENTATION, orientation.getVal());
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        new ExifRewriter().updateExifMetadataLossy(this.fileSrc, baos, outputSet);
+
+        this.fileSrc = new ByteSourceArray(baos.toByteArray());
+    }
+
+    /**
+     * @return the ByteSource of the current file
+     */
+    public ByteSource getOutput() {
+        return fileSrc;
+    }
+
+    /**
+     *  Writes Bytesource to file with given path
+     * @param path String of the path in which the file is written
+     * @throws IOException
+     */
+    public void getOutput(String path)

Review Comment:
   I think this is never tested?



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {
+
+    public enum Orientation {

Review Comment:
   At least everything `public` must have a Javadoc :point_down:  (tests should be fine as we don't have that in other tests, unless you have time to add it too).



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {
+
+    public enum Orientation {
+        HORIZONTAL((short)1),
+        MIRROR_HORIZONTAL((short)2),
+        ROTATE_180((short)3),
+        MIRROR_VERTICAL((short)4),
+        MIRROR_HORIZONTAL_AND_ROTATE_270((short)5),
+        ROTATE_90((short)6),
+        MIRROR_HORIZONTAL_AND_ROTATE_90((short)7),
+        ROTATE_270((short)8);
+
+        private short val;
+
+        Orientation(short orVal) {
+            this.val = orVal;
+        }
+
+        public short getVal() {
+            return val;
+        }
+    }
+
+    private ByteSource fileSrc;
+
+    public ExifOrientationRewriter(File imageFile) {
+        fileSrc = new ByteSourceFile(imageFile);
+    }
+    public ExifOrientationRewriter(byte[] byteArray) {
+        fileSrc = new ByteSourceArray(byteArray);
+    }
+    public ExifOrientationRewriter(ByteSource byteSource) {
+        fileSrc = byteSource;
+    }
+
+    /***
+     * Get the orientation (enum) of the current image
+     * Returns horizontal by default
+     * @return Orientation enum
+     * @throws IOException
+     * @throws ImageReadException
+     * @throws ImageWriteException
+     */
+    public Orientation getExifOrientation() throws IOException, ImageReadException, ImageWriteException {
+
+        final JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffImageMetadata exifMetadata = metadata.getExif();
+
+        if (exifMetadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffOutputSet outputSet = exifMetadata.getOutputSet();
+
+        TiffOutputDirectory tod = outputSet.getRootDirectory();
+        if (tod == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        TiffOutputField tof = tod.findField(TiffTagConstants.TIFF_TAG_ORIENTATION);
+        if (tof == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        short imageOrientationVal = (short) exifMetadata.getFieldValue(TiffTagConstants.TIFF_TAG_ORIENTATION);
+
+        for (Orientation orientation : Orientation.values()) {
+            if(orientation.getVal() == imageOrientationVal) {
+                return orientation;
+            }
+        }
+
+        return Orientation.HORIZONTAL;
+    }
+
+    /**
+     * A method that sets a new value to the orientation field in the EXIF metadata of a JPEG file.
+     * @param orientation the value as a enum of the direction to set as the new EXIF orientation
+     *

Review Comment:
   Missing `@throws` here...



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {
+
+    public enum Orientation {
+        HORIZONTAL((short)1),
+        MIRROR_HORIZONTAL((short)2),
+        ROTATE_180((short)3),
+        MIRROR_VERTICAL((short)4),
+        MIRROR_HORIZONTAL_AND_ROTATE_270((short)5),
+        ROTATE_90((short)6),
+        MIRROR_HORIZONTAL_AND_ROTATE_90((short)7),
+        ROTATE_270((short)8);
+
+        private short val;
+
+        Orientation(short orVal) {
+            this.val = orVal;
+        }
+
+        public short getVal() {
+            return val;
+        }
+    }
+
+    private ByteSource fileSrc;
+
+    public ExifOrientationRewriter(File imageFile) {
+        fileSrc = new ByteSourceFile(imageFile);
+    }
+    public ExifOrientationRewriter(byte[] byteArray) {
+        fileSrc = new ByteSourceArray(byteArray);
+    }
+    public ExifOrientationRewriter(ByteSource byteSource) {
+        fileSrc = byteSource;
+    }
+
+    /***
+     * Get the orientation (enum) of the current image
+     * Returns horizontal by default
+     * @return Orientation enum
+     * @throws IOException
+     * @throws ImageReadException
+     * @throws ImageWriteException
+     */
+    public Orientation getExifOrientation() throws IOException, ImageReadException, ImageWriteException {
+
+        final JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            return Orientation.HORIZONTAL;
+        }

Review Comment:
   Isn't that dangerous to return horizontal? Wouldn't it be better to return `null` instead? This way you have the three valid states, 1) data has horizontal orientation, 2) data has vertical orientation, or 3) no metadata about orientation.



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {
+
+    public enum Orientation {
+        HORIZONTAL((short)1),
+        MIRROR_HORIZONTAL((short)2),
+        ROTATE_180((short)3),
+        MIRROR_VERTICAL((short)4),
+        MIRROR_HORIZONTAL_AND_ROTATE_270((short)5),
+        ROTATE_90((short)6),
+        MIRROR_HORIZONTAL_AND_ROTATE_90((short)7),
+        ROTATE_270((short)8);
+
+        private short val;
+
+        Orientation(short orVal) {
+            this.val = orVal;
+        }
+
+        public short getVal() {
+            return val;
+        }
+    }
+
+    private ByteSource fileSrc;
+
+    public ExifOrientationRewriter(File imageFile) {
+        fileSrc = new ByteSourceFile(imageFile);
+    }
+    public ExifOrientationRewriter(byte[] byteArray) {
+        fileSrc = new ByteSourceArray(byteArray);
+    }
+    public ExifOrientationRewriter(ByteSource byteSource) {
+        fileSrc = byteSource;
+    }
+
+    /***
+     * Get the orientation (enum) of the current image
+     * Returns horizontal by default
+     * @return Orientation enum
+     * @throws IOException
+     * @throws ImageReadException
+     * @throws ImageWriteException
+     */
+    public Orientation getExifOrientation() throws IOException, ImageReadException, ImageWriteException {
+
+        final JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffImageMetadata exifMetadata = metadata.getExif();
+
+        if (exifMetadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffOutputSet outputSet = exifMetadata.getOutputSet();
+
+        TiffOutputDirectory tod = outputSet.getRootDirectory();
+        if (tod == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        TiffOutputField tof = tod.findField(TiffTagConstants.TIFF_TAG_ORIENTATION);
+        if (tof == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        short imageOrientationVal = (short) exifMetadata.getFieldValue(TiffTagConstants.TIFF_TAG_ORIENTATION);
+
+        for (Orientation orientation : Orientation.values()) {
+            if(orientation.getVal() == imageOrientationVal) {
+                return orientation;
+            }
+        }
+
+        return Orientation.HORIZONTAL;
+    }
+
+    /**
+     * A method that sets a new value to the orientation field in the EXIF metadata of a JPEG file.
+     * @param orientation the value as a enum of the direction to set as the new EXIF orientation
+     *
+     */
+    public void setExifOrientation(Orientation orientation) throws ImageWriteException, IOException, ImageReadException {
+
+        JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            metadata = new JpegImageMetadata(null, new TiffImageMetadata(new TiffContents(new TiffHeader(ByteOrder.BIG_ENDIAN, 0, 0), new ArrayList<>(), new ArrayList<>())));

Review Comment:
   I think `ExifRewriter` allows big and little endian. But it looks like `ExifOrientationRewriter` uses big endian if no metadata found? Wouldn't be better if we had the same behavior as in `ExifRewriter`? Letting the user choose the endianess.



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########


Review Comment:
   Did you try to design the EXIF rotation as part of `ExifRewriter`, @snumlautoken ? What was the rationale for creating a new class instead? I guess that could mean that for other metadata rewriting/editing we would need other `Exif$MetadataRewriter`? Ditto for other metadata/formats? That sounds like it could become problematic in the long run, I think? WDYT?



##########
src/main/java/org/apache/commons/imaging/formats/jpeg/exif/ExifOrientationRewriter.java:
##########
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.imaging.formats.jpeg.exif;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffHeader;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputField;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+public class ExifOrientationRewriter {
+
+    public enum Orientation {
+        HORIZONTAL((short)1),
+        MIRROR_HORIZONTAL((short)2),
+        ROTATE_180((short)3),
+        MIRROR_VERTICAL((short)4),
+        MIRROR_HORIZONTAL_AND_ROTATE_270((short)5),
+        ROTATE_90((short)6),
+        MIRROR_HORIZONTAL_AND_ROTATE_90((short)7),
+        ROTATE_270((short)8);
+
+        private short val;
+
+        Orientation(short orVal) {
+            this.val = orVal;
+        }
+
+        public short getVal() {
+            return val;
+        }
+    }
+
+    private ByteSource fileSrc;
+
+    public ExifOrientationRewriter(File imageFile) {
+        fileSrc = new ByteSourceFile(imageFile);
+    }
+    public ExifOrientationRewriter(byte[] byteArray) {
+        fileSrc = new ByteSourceArray(byteArray);
+    }
+    public ExifOrientationRewriter(ByteSource byteSource) {
+        fileSrc = byteSource;
+    }
+
+    /***
+     * Get the orientation (enum) of the current image
+     * Returns horizontal by default
+     * @return Orientation enum
+     * @throws IOException
+     * @throws ImageReadException
+     * @throws ImageWriteException
+     */
+    public Orientation getExifOrientation() throws IOException, ImageReadException, ImageWriteException {
+
+        final JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffImageMetadata exifMetadata = metadata.getExif();
+
+        if (exifMetadata == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        final TiffOutputSet outputSet = exifMetadata.getOutputSet();
+
+        TiffOutputDirectory tod = outputSet.getRootDirectory();
+        if (tod == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        TiffOutputField tof = tod.findField(TiffTagConstants.TIFF_TAG_ORIENTATION);
+        if (tof == null) {
+            return Orientation.HORIZONTAL;
+        }
+
+        short imageOrientationVal = (short) exifMetadata.getFieldValue(TiffTagConstants.TIFF_TAG_ORIENTATION);
+
+        for (Orientation orientation : Orientation.values()) {
+            if(orientation.getVal() == imageOrientationVal) {
+                return orientation;
+            }
+        }
+
+        return Orientation.HORIZONTAL;
+    }
+
+    /**
+     * A method that sets a new value to the orientation field in the EXIF metadata of a JPEG file.
+     * @param orientation the value as a enum of the direction to set as the new EXIF orientation
+     *
+     */
+    public void setExifOrientation(Orientation orientation) throws ImageWriteException, IOException, ImageReadException {
+
+        JpegImageMetadata metadata = (JpegImageMetadata) Imaging.getMetadata(this.fileSrc.getAll());
+
+        if (metadata == null) {
+            metadata = new JpegImageMetadata(null, new TiffImageMetadata(new TiffContents(new TiffHeader(ByteOrder.BIG_ENDIAN, 0, 0), new ArrayList<>(), new ArrayList<>())));

Review Comment:
   s/new ArrayList()/Collections.emptyList()
   
   That should create that empty `EmptyList` instead of an `ArrayList`, and I think further down the pipe the `new ArrayList` will become an unmodifiable collection, so that should be fine.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@commons.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org