You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by da...@apache.org on 2016/09/06 17:16:49 UTC

svn commit: r1759460 - in /commons/proper/imaging/trunk/src: changes/changes.xml main/java/org/apache/commons/imaging/formats/tiff/taginfos/TagInfoXpString.java test/java/org/apache/commons/imaging/formats/jpeg/exif/MicrosoftTagTest.java

Author: damjan
Date: Tue Sep  6 17:16:48 2016
New Revision: 1759460

URL: http://svn.apache.org/viewvc?rev=1759460&view=rev
Log:
IMAGING-172: Microsoft tags are not seen in MS Windows Properties/Details dialog

Null-terminate the XpString tag, and store it in the root directory where
Windows looks for it instead of the EXIF directory. Also deletes the
IPTC and XMP metadata which contains conflicting tags which Windows
uses instead when present.


Modified:
    commons/proper/imaging/trunk/src/changes/changes.xml
    commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/taginfos/TagInfoXpString.java
    commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/MicrosoftTagTest.java

Modified: commons/proper/imaging/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/changes/changes.xml?rev=1759460&r1=1759459&r2=1759460&view=diff
==============================================================================
--- commons/proper/imaging/trunk/src/changes/changes.xml (original)
+++ commons/proper/imaging/trunk/src/changes/changes.xml Tue Sep  6 17:16:48 2016
@@ -46,6 +46,9 @@ The <action> type attribute can be add,u
   <body>
 
     <release version="1.0" date="TBA" description="First major release">
+      <action issue="IMAGING-172" dev="damjan" type="fix">
+        Microsoft tags are not seen in MS Windows Properties/Details dialog.
+      </action>
       <action issue="IMAGING-186" dev="britter" type="update" due-to="Ric Emery">
         Add sCAL support to PNG reading and writing.
       </action>

Modified: commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/taginfos/TagInfoXpString.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/taginfos/TagInfoXpString.java?rev=1759460&r1=1759459&r2=1759460&view=diff
==============================================================================
--- commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/taginfos/TagInfoXpString.java (original)
+++ commons/proper/imaging/trunk/src/main/java/org/apache/commons/imaging/formats/tiff/taginfos/TagInfoXpString.java Tue Sep  6 17:16:48 2016
@@ -43,7 +43,10 @@ public class TagInfoXpString extends Tag
         }
         final String s = (String) value;
         try {
-            return s.getBytes("UTF-16LE");
+            final byte[] bytes = s.getBytes("UTF-16LE");
+            final byte[] paddedBytes = new byte[bytes.length + 2];
+            System.arraycopy(bytes, 0, paddedBytes, 0, bytes.length);
+            return paddedBytes;
         } catch (final UnsupportedEncodingException cannotHappen) {
             return null;
         }
@@ -55,7 +58,14 @@ public class TagInfoXpString extends Tag
             throw new ImageReadException("Text field not encoded as bytes.");
         }
         try {
-            return new String(entry.getByteArrayValue(), "UTF-16LE");
+            final byte[] bytes = entry.getByteArrayValue();
+            final int length;
+            if (bytes.length >= 2 && bytes[bytes.length - 1] == 0 && bytes[bytes.length - 2] == 0) {
+                length = bytes.length - 2;
+            } else {
+                length = bytes.length;
+            }
+            return new String(bytes, 0, length, "UTF-16LE");
         } catch (final UnsupportedEncodingException cannotHappen) {
             return null;
         }

Modified: commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/MicrosoftTagTest.java
URL: http://svn.apache.org/viewvc/commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/MicrosoftTagTest.java?rev=1759460&r1=1759459&r2=1759460&view=diff
==============================================================================
--- commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/MicrosoftTagTest.java (original)
+++ commons/proper/imaging/trunk/src/test/java/org/apache/commons/imaging/formats/jpeg/exif/MicrosoftTagTest.java Tue Sep  6 17:16:48 2016
@@ -21,19 +21,27 @@ import static org.junit.Assert.assertTru
 import java.awt.image.BufferedImage;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
 import org.apache.commons.imaging.ImageFormats;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
 import org.apache.commons.imaging.Imaging;
 import org.apache.commons.imaging.ImagingConstants;
 import org.apache.commons.imaging.common.ImageMetadata;
 import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.jpeg.iptc.JpegIptcRewriter;
+import org.apache.commons.imaging.formats.jpeg.xmp.JpegXmpRewriter;
 import org.apache.commons.imaging.formats.tiff.TiffDirectory;
 import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
 import org.apache.commons.imaging.formats.tiff.constants.MicrosoftTagConstants;
+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.TiffOutputSet;
 import org.junit.Test;
@@ -48,11 +56,11 @@ public class MicrosoftTagTest extends Ex
     public void testWrite() throws Exception {
         final BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
         final TiffOutputSet exifSet = new TiffOutputSet();
-        final TiffOutputDirectory exif = exifSet.getOrCreateExifDirectory();
-        exif.add(MicrosoftTagConstants.EXIF_TAG_XPAUTHOR, AUTHOR);
-        exif.add(MicrosoftTagConstants.EXIF_TAG_XPCOMMENT, COMMENT);
-        exif.add(MicrosoftTagConstants.EXIF_TAG_XPSUBJECT, SUBJECT);
-        exif.add(MicrosoftTagConstants.EXIF_TAG_XPTITLE, TITLE);
+        final TiffOutputDirectory root = exifSet.getOrCreateRootDirectory();
+        root.add(MicrosoftTagConstants.EXIF_TAG_XPAUTHOR, AUTHOR);
+        root.add(MicrosoftTagConstants.EXIF_TAG_XPCOMMENT, COMMENT);
+        root.add(MicrosoftTagConstants.EXIF_TAG_XPSUBJECT, SUBJECT);
+        root.add(MicrosoftTagConstants.EXIF_TAG_XPTITLE, TITLE);
         final Map<String, Object> params = new TreeMap<>();
         params.put(ImagingConstants.PARAM_KEY_EXIF, exifSet);
         final byte[] bytes = Imaging.writeImageToBytes(image, ImageFormats.TIFF, params);
@@ -69,17 +77,32 @@ public class MicrosoftTagTest extends Ex
         }
     }
 
+    private byte[] cleanImage(File imageWithExif) throws ImageReadException, ImageWriteException, IOException {
+        // Windows doesn't show XP tags if same-meaning tags exist in IPTC or XMP. Remove them: 
+        final ByteArrayOutputStream noXmp = new ByteArrayOutputStream();
+        new JpegXmpRewriter().removeXmpXml(imageWithExif, noXmp);
+        final ByteArrayOutputStream noXmpNoIptc = new ByteArrayOutputStream();
+        new JpegIptcRewriter().removeIPTC(noXmp.toByteArray(), noXmpNoIptc);
+        return noXmpNoIptc.toByteArray();
+    }
+
     @Test
     public void testRewrite() throws Exception {
-        final File imageWithExif = getImageWithExifData();
+        final byte[] imageWithExif = cleanImage(getImageWithExifData());
+
         final TiffImageMetadata metadata = toTiffMetadata(Imaging.getMetadata(imageWithExif));
         final ExifRewriter rewriter = new ExifRewriter();
         final TiffOutputSet outputSet = metadata.getOutputSet();
-        final TiffOutputDirectory exif = outputSet.getOrCreateExifDirectory();
-        exif.add(MicrosoftTagConstants.EXIF_TAG_XPAUTHOR, AUTHOR);
-        exif.add(MicrosoftTagConstants.EXIF_TAG_XPCOMMENT, COMMENT);
-        exif.add(MicrosoftTagConstants.EXIF_TAG_XPSUBJECT, SUBJECT);
-        exif.add(MicrosoftTagConstants.EXIF_TAG_XPTITLE, TITLE);
+        final TiffOutputDirectory root = outputSet.getOrCreateRootDirectory();
+        
+        // In Windows these will also hide XP fields:
+        root.removeField(TiffTagConstants.TIFF_TAG_IMAGE_DESCRIPTION);
+        root.removeField(TiffTagConstants.TIFF_TAG_ARTIST);
+        
+        root.add(MicrosoftTagConstants.EXIF_TAG_XPAUTHOR, AUTHOR);
+        root.add(MicrosoftTagConstants.EXIF_TAG_XPCOMMENT, COMMENT);
+        root.add(MicrosoftTagConstants.EXIF_TAG_XPSUBJECT, SUBJECT);
+        root.add(MicrosoftTagConstants.EXIF_TAG_XPTITLE, TITLE);
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         rewriter.updateExifMetadataLossy(imageWithExif, baos, outputSet);
         checkFields(baos.toByteArray());