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).
   
   
![20220514_102409](https://github.com/apache/commons-imaging/assets/304786/5d17f03b-7cda-4564-8536-f36d015a4dbf)
   
   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]

Reply via email to