kinow commented on PR #359:
URL: https://github.com/apache/commons-imaging/pull/359#issuecomment-2053782645
Thanks for searching @StefanOltmann !
I modified the script to search for any field in the `diff` output that is
empty, and ran on some personal photos and found one!
Code:
```java
package org.apache.commons.imaging;
import org.apache.commons.imaging.common.ImageMetadata;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
import org.apache.commons.io.IOUtils;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Search for images that cause the bug in IMAGING-319.
*/
public class LibraryTest {
//
// public static void main2(String[] args) throws ImagingException,
IOException {
// File source = new
File("/home/kinow/Desktop/haystack/20220514_102409.jpg");
// File result = new
File("/home/kinow/Desktop/haystack/editted-20220514_102409.jpg");
// final ImageMetadata metadata = Imaging.getMetadata(source);
// final JpegImageMetadata jpegMetadata = (JpegImageMetadata)
metadata;
// final TiffImageMetadata exif = jpegMetadata.getExif();
// TiffOutputSet outputSet = exif.getOutputSet();
// BufferedOutputStream bufferedOutputStream = new
BufferedOutputStream(Files.newOutputStream(result.toPath()));
// new ExifRewriter().updateExifMetadataLossless(source,
bufferedOutputStream, outputSet);
// }
public static void main(String[] args) throws ImagingException,
IOException, InterruptedException {
File path = new File("/home/kinow/Desktop/haystack/");
String needle = ".*([\\s+])*\\s+:\\s+";
Pattern pattern = Pattern.compile(String.format("^%s$", needle),
Pattern.MULTILINE);
for (File source : Objects.requireNonNull(path.listFiles(s ->
s.getName().toLowerCase().endsWith(".jpg")))) {
File result = Files.createTempFile("test_", ".jpg").toFile();
try {
final ImageMetadata metadata = Imaging.getMetadata(source);
final JpegImageMetadata jpegMetadata = (JpegImageMetadata)
metadata;
if (jpegMetadata != null) {
final TiffImageMetadata exif = jpegMetadata.getExif();
if (exif != null) {
TiffOutputSet outputSet = exif.getOutputSet();
BufferedOutputStream bufferedOutputStream = new
BufferedOutputStream(Files.newOutputStream(result.toPath()));
new
ExifRewriter().updateExifMetadataLossless(source, bufferedOutputStream,
outputSet);
String[] cmd = {
"/bin/sh",
"-c",
String.format("/home/kinow/Desktop/haystack/test.sh %s %s",
source.getAbsolutePath(), result.getAbsolutePath())
// String.format("exiftool %s | grep
\"Offset Time\"", result.getAbsolutePath())
};
Process process = Runtime.getRuntime().exec(cmd);
process.waitFor();
String output =
IOUtils.toString(process.getInputStream(), Charset.defaultCharset());
// System.out.println(output);
Matcher m = pattern.matcher(output);
if (m.find()) {
System.out.printf("Bug detected in %s%n",
source.getAbsolutePath());
}
}
}
} catch (RuntimeException|ImagingException ignore) {
ignore.printStackTrace();
} // invalid metadata or bad format
}
}
}
```
Test image (I drew something some years ago, covered parts of it that were
irrelevant).

To confirm this is causing the issue, I tried the following:
- Copied it in `data.images.jpg.8`, ran `ExifRewriterRoundtripTest` and it
failed for that file (`master`)
- Changed to the code of this pull request, all tests passed! :tada:
- Then re-ran the sample code from JIRA, then compared EXIF metadata with
`exiftool` + `diff`
```bash
kinow@ranma:~/Desktop/haystack$ diff <(exiftool 20220514_102409.jpg)
<(exiftool editted-20220514_102409.jpg)
2c2
< File Name : 20220514_102409.jpg
---
> File Name : editted-20220514_102409.jpg
5,8c5,8
< File Modification Date/Time : 2024:04:14 00:29:34+02:00
< File Access Date/Time : 2024:04:14 00:29:37+02:00
< File Inode Change Date/Time : 2024:04:14 00:29:34+02:00
< File Permissions : -rwxrwxrwx
---
> File Modification Date/Time : 2024:04:14 00:36:13+02:00
> File Access Date/Time : 2024:04:14 00:36:13+02:00
> File Inode Change Date/Time : 2024:04:14 00:36:13+02:00
> File Permissions : -rw-rw-r--
15c15
< Camera Model Name : SM-S901E
---
> Camera Model Name :
29c29
< Offset Time : +12:00
---
> Offset Time : +12:00.
40c40
< Thumbnail Offset : 586
---
> Thumbnail Offset : 38
```
(Camera Model Name ended up being replaced by empty string, like the JIRA
example)
- Finally, added a quick test code in `TiffImageWriterLossless.java` (fixed
in this branch) with the condition where the bug was fixed, see below
```java
if (offset != length && (offset & 1L) != 0 && length >
outputItemLength) {
int i = 1; // breakpoint here to just confirm the file
triggers this...
}
```
And the breakpoint was reached for the iPhone photo from JIRA, and also for
my image file :tada:
I will clean up my local modifications, and add my test image to this
branch, then rebase + squash. Feel free to check the image file and confirm it
if you'd like, @StefanOltmann. Thank you for the help, and for the JIRA OP for
providing a useful code snippet to verify the issue.
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]