diff --git a/imageio/imageio-clippath/src/main/java/com/twelvemonkeys/imageio/path/AdobePathWriter.java b/imageio/imageio-clippath/src/main/java/com/twelvemonkeys/imageio/path/AdobePathWriter.java
index 493305f8..f3f01baf 100755
--- a/imageio/imageio-clippath/src/main/java/com/twelvemonkeys/imageio/path/AdobePathWriter.java
+++ b/imageio/imageio-clippath/src/main/java/com/twelvemonkeys/imageio/path/AdobePathWriter.java
@@ -67,11 +67,12 @@ public final class AdobePathWriter {
* regardless of image dimensions.
*
*
- * @param path A {@code Shape} instance that has {@link Path2D#WIND_EVEN_ODD WIND_EVEN_ODD} rule
- * and is contained within the rectangle [x=0.0,y=0.0,w=1.0,h=1.0].
+ * @param path A {@code Shape} instance that has {@link Path2D#WIND_EVEN_ODD WIND_EVEN_ODD} rule,
+ * is contained within the rectangle [x=0.0,y=0.0,w=1.0,h=1.0], and is closed.
* @throws IllegalArgumentException if {@code path} is {@code null},
* the paths winding rule is not @link Path2D#WIND_EVEN_ODD} or
- * the paths bounding box is outside [x=0.0,y=0.0,w=1.0,h=1.0].
+ * the paths bounding box is outside [x=0.0,y=0.0,w=1.0,h=1.0] or
+ * the path is not closed.
*/
public AdobePathWriter(final Shape path) {
notNull(path, "path");
@@ -128,8 +129,8 @@ public final class AdobePathWriter {
break;
case PathIterator.SEG_CLOSE:
- // Replace initial point.
AdobePathSegment initial = subpath.get(0);
+
if (initial.apx != prev.apx || initial.apy != prev.apy) {
// Line back to initial if last anchor point does not equal initial anchor
collinear = isCollinear(prev.cppx, prev.cppy, initial.apx, initial.apy, initial.apx, initial.apy);
@@ -137,13 +138,7 @@ public final class AdobePathWriter {
prev = new AdobePathSegment(CLOSED_SUBPATH_BEZIER_LINKED, initial.apy, initial.apx, initial.apy, initial.apx, 0, 0);
}
- collinear = isCollinear(prev.cppx, prev.cppy, initial.apx, initial.apy, initial.cplx, initial.cply);
- subpath.set(0, new AdobePathSegment(collinear ? CLOSED_SUBPATH_BEZIER_LINKED : CLOSED_SUBPATH_BEZIER_UNLINKED, prev.cppy, prev.cppx, initial.apy, initial.apx, initial.cply, initial.cplx));
-
- // Add to full path
- segments.add(new AdobePathSegment(CLOSED_SUBPATH_LENGTH_RECORD, subpath.size()));
- segments.addAll(subpath);
-
+ close(initial, prev, subpath, segments);
subpath.clear();
break;
@@ -152,12 +147,31 @@ public final class AdobePathWriter {
pathIterator.next();
}
- // TODO: If subpath is not empty at this point, there was no close segment...
- // Either wrap up (if coordinates match), or throw exception (otherwise)
+ // If subpath is not empty at this point, there was no close segment...
+ // Wrap up if coordinates match, otherwise throw exception
+ if (!subpath.isEmpty()) {
+ AdobePathSegment initial = subpath.get(0);
+
+ if (initial.apx != prev.apx || initial.apy != prev.apy) {
+ throw new IllegalArgumentException("Path must be closed");
+ }
+
+ close(initial, prev, subpath, segments);
+ }
return segments;
}
+ private static void close(AdobePathSegment initial, AdobePathSegment prev, List subpath, List segments) {
+ // Replace initial point.
+ boolean collinear = isCollinear(prev.cppx, prev.cppy, initial.apx, initial.apy, initial.cplx, initial.cply);
+ subpath.set(0, new AdobePathSegment(collinear ? CLOSED_SUBPATH_BEZIER_LINKED : CLOSED_SUBPATH_BEZIER_UNLINKED, prev.cppy, prev.cppx, initial.apy, initial.apx, initial.cply, initial.cplx));
+
+ // Add to full path
+ segments.add(new AdobePathSegment(CLOSED_SUBPATH_LENGTH_RECORD, subpath.size()));
+ segments.addAll(subpath);
+ }
+
private static boolean isCollinear(double x1, double y1, double x2, double y2, double x3, double y3) {
// Photoshop seems to write as linked if all points are the same....
return (x1 == x2 && x2 == x3 && y1 == y2 && y2 == y3) ||
@@ -248,5 +262,4 @@ public final class AdobePathWriter {
return bytes.toByteArray();
}
-
}
diff --git a/imageio/imageio-clippath/src/main/java/com/twelvemonkeys/imageio/path/Paths.java b/imageio/imageio-clippath/src/main/java/com/twelvemonkeys/imageio/path/Paths.java
index 4562dd67..ce95a4f8 100755
--- a/imageio/imageio-clippath/src/main/java/com/twelvemonkeys/imageio/path/Paths.java
+++ b/imageio/imageio-clippath/src/main/java/com/twelvemonkeys/imageio/path/Paths.java
@@ -53,6 +53,7 @@ import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;
+import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -258,7 +259,30 @@ public final class Paths {
return applyClippingPath(clip, image);
}
- public static boolean writeClipped(final BufferedImage image, Shape clipPath, final String formatName, final ImageOutputStream output) throws IOException {
+ /**
+ * Writes the image along with a clipping path resource, in the given format to the supplied output.
+ * The image is written to the
+ * {@code ImageOutputStream} starting at the current stream
+ * pointer, overwriting existing stream data from that point
+ * forward, if present.
+ *
+ * Note: As {@link ImageIO#write(RenderedImage, String, ImageOutputStream)}, this method does
+ * not close the output stream.
+ * It is the responsibility of the caller to close the stream, if desired.
+ *
+ *
+ * @param image the image to be written, may not be {@code null}.
+ * @param clipPath the clip path, may not be {@code null}.
+ * @param formatName the informal format name, may not be {@code null}.
+ * @param output the stream to write to, may not be {@code null}.
+ *
+ * @return {@code true} if the image was written,
+ * otherwise {@code false} (ie. no writer was found for the specified format).
+ *
+ * @exception IllegalArgumentException if any parameter is {@code null}.
+ * @exception IOException if an error occurs during writing.
+ */
+ public static boolean writeClipped(final RenderedImage image, Shape clipPath, final String formatName, final ImageOutputStream output) throws IOException {
if (image == null) {
throw new IllegalArgumentException("image == null!");
}
@@ -269,74 +293,75 @@ public final class Paths {
throw new IllegalArgumentException("output == null!");
}
- String format = "JPG".equalsIgnoreCase(formatName) ? "JPEG" : formatName.toUpperCase();
+ ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(image);
+ Iterator writers = ImageIO.getImageWriters(type, formatName);
- if ("TIFF".equals(format) || "JPEG".equals(format)) {
- ImageTypeSpecifier type = ImageTypeSpecifier.createFromRenderedImage(image);
- Iterator writers = ImageIO.getImageWriters(type, formatName);
+ if (writers.hasNext()) {
+ ImageWriter writer = writers.next();
- if (writers.hasNext()) {
- ImageWriter writer = writers.next();
+ ImageWriteParam param = writer.getDefaultWriteParam();
+ IIOMetadata metadata = writer.getDefaultImageMetadata(type, param);
+ List metadataFormats = asList(metadata.getMetadataFormatNames());
- ImageWriteParam param = writer.getDefaultWriteParam();
- IIOMetadata metadata = writer.getDefaultImageMetadata(type, param);
- List metadataFormats = asList(metadata.getMetadataFormatNames());
+ byte[] pathResource = new AdobePathWriter(clipPath).writePathResource();
- byte[] pathResource = new AdobePathWriter(clipPath).writePathResource();
+ if (metadataFormats.contains("javax_imageio_tiff_image_1.0") || metadataFormats.contains("com_sun_media_imageio_plugins_tiff_image_1.0")) {
+ param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ param.setCompressionType("Deflate");
- if ("TIFF".equals(format)) {
- param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
- param.setCompressionType("Deflate");
+ // Check if the format is that of the bundled TIFF writer, otherwise use JAI format
+ String metadataFormat = metadataFormats.contains("javax_imageio_tiff_image_1.0")
+ ? "javax_imageio_tiff_image_1.0"
+ : "com_sun_media_imageio_plugins_tiff_image_1.0"; // Fails in mergeTree, if not supported
+ IIOMetadataNode root = new IIOMetadataNode(metadataFormat);
+ IIOMetadataNode ifd = new IIOMetadataNode("TIFFIFD");
- // Check if the format is that of the bundled TIFF writer, otherwise use JAI format
- String metadataFormat = metadataFormats.contains("javax_imageio_tiff_image_1.0")
- ? "javax_imageio_tiff_image_1.0"
- : "com_sun_media_imageio_plugins_tiff_image_1.0"; // Fails in mergeTree, if not supported
- IIOMetadataNode root = new IIOMetadataNode(metadataFormat);
- IIOMetadataNode ifd = new IIOMetadataNode("TIFFIFD");
+ IIOMetadataNode pathField = new IIOMetadataNode("TIFFField");
+ pathField.setAttribute("number", String.valueOf(TIFF.TAG_PHOTOSHOP));
+ IIOMetadataNode pathValue = new IIOMetadataNode("TIFFUndefined"); // Use undefined for simplicity, could also use bytes
+ pathValue.setAttribute("value", arrayAsString(pathResource));
- IIOMetadataNode pathField = new IIOMetadataNode("TIFFField");
- pathField.setAttribute("number", String.valueOf(TIFF.TAG_PHOTOSHOP));
- IIOMetadataNode pathValue = new IIOMetadataNode("TIFFUndefined"); // Use undefined for simplicity, could also use bytes
- pathValue.setAttribute("value", arrayAsString(pathResource));
+ pathField.appendChild(pathValue);
+ ifd.appendChild(pathField);
+ root.appendChild(ifd);
- pathField.appendChild(pathValue);
- ifd.appendChild(pathField);
- root.appendChild(ifd);
-
- metadata.mergeTree(metadataFormat, root);
- }
- else if ("JPEG".equals(format)) {
- String metadataFormat = "javax_imageio_jpeg_image_1.0";
- IIOMetadataNode root = new IIOMetadataNode(metadataFormat);
-
- root.appendChild(new IIOMetadataNode("JPEGvariety"));
-
- IIOMetadataNode sequence = new IIOMetadataNode("markerSequence");
-
- // App13/Photshop 3.0
- IIOMetadataNode unknown = new IIOMetadataNode("unknown");
- unknown.setAttribute("MarkerTag", Integer.toString(JPEG.APP13 & 0xFF));
-
- byte[] identfier = "Photoshop 3.0".getBytes(StandardCharsets.US_ASCII);
- byte[] data = new byte[identfier.length + 1 + pathResource.length];
- System.arraycopy(identfier, 0, data, 0, identfier.length);
- System.arraycopy(pathResource, 0, data, identfier.length + 1, pathResource.length);
-
- unknown.setUserObject(data);
-
- sequence.appendChild(unknown);
- root.appendChild(sequence);
-
- metadata.mergeTree(metadataFormat, root);
- }
- // TODO: Else if PSD... Requires PSD write + new metadata format...
+ metadata.mergeTree(metadataFormat, root);
writer.setOutput(output);
writer.write(null, new IIOImage(image, null, metadata), param);
return true;
}
+ else if (metadataFormats.contains("javax_imageio_jpeg_image_1.0")) {
+ String metadataFormat = "javax_imageio_jpeg_image_1.0";
+ IIOMetadataNode root = new IIOMetadataNode(metadataFormat);
+
+ root.appendChild(new IIOMetadataNode("JPEGvariety"));
+
+ IIOMetadataNode sequence = new IIOMetadataNode("markerSequence");
+
+ // App13/Photshop 3.0
+ IIOMetadataNode unknown = new IIOMetadataNode("unknown");
+ unknown.setAttribute("MarkerTag", Integer.toString(JPEG.APP13 & 0xFF));
+
+ byte[] identfier = "Photoshop 3.0".getBytes(StandardCharsets.US_ASCII);
+ byte[] data = new byte[identfier.length + 1 + pathResource.length];
+ System.arraycopy(identfier, 0, data, 0, identfier.length);
+ System.arraycopy(pathResource, 0, data, identfier.length + 1, pathResource.length);
+
+ unknown.setUserObject(data);
+
+ sequence.appendChild(unknown);
+ root.appendChild(sequence);
+
+ metadata.mergeTree(metadataFormat, root);
+
+ writer.setOutput(output);
+ writer.write(null, new IIOImage(image, null, metadata), param);
+
+ return true;
+ }
+ // TODO: Else if PSD... Requires PSD write + new metadata format...
}
return false;
diff --git a/imageio/imageio-clippath/src/test/java/com/twelvemonkeys/imageio/path/AdobePathWriterTest.java b/imageio/imageio-clippath/src/test/java/com/twelvemonkeys/imageio/path/AdobePathWriterTest.java
index ad515e33..5179ed1e 100644
--- a/imageio/imageio-clippath/src/test/java/com/twelvemonkeys/imageio/path/AdobePathWriterTest.java
+++ b/imageio/imageio-clippath/src/test/java/com/twelvemonkeys/imageio/path/AdobePathWriterTest.java
@@ -44,7 +44,8 @@ import java.util.Arrays;
import static com.twelvemonkeys.imageio.path.AdobePathSegment.*;
import static com.twelvemonkeys.imageio.path.PathsTest.assertPathEquals;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
/**
* AdobePathWriterTest.
@@ -92,6 +93,16 @@ public class AdobePathWriterTest {
new AdobePathWriter(path);
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateNotClosed() {
+ GeneralPath path = new GeneralPath(Path2D.WIND_EVEN_ODD);
+ path.moveTo(.5, .5);
+ path.lineTo(1, .5);
+ path.curveTo(1, 1, 1, 1, .5, 1);
+
+ new AdobePathWriter(path).writePath();
+ }
+
@Test
public void testCreateClosed() {
GeneralPath path = new GeneralPath(Path2D.WIND_EVEN_ODD);
@@ -100,9 +111,30 @@ public class AdobePathWriterTest {
path.curveTo(1, 1, 1, 1, .5, 1);
path.closePath();
- new AdobePathWriter(path).writePath();
+ byte[] bytes = new AdobePathWriter(path).writePath();
- fail("Test that we have 4 segments");
+ assertEquals(6 * 26, bytes.length);
+
+ int off = 0;
+
+ // Path/initial fill rule: Even-Odd (0)
+ assertArrayEquals(new byte[] {0, PATH_FILL_RULE_RECORD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, INITIAL_FILL_RULE_RECORD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+
+ // Rectangle 1: 0, 0, 1, .5
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_LENGTH_RECORD, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_BEZIER_UNLINKED, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 1, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_BEZIER_UNLINKED, 0, -128, 0, 0, 1, 0, 0, 0, 0, -128, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_BEZIER_UNLINKED, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+
+ // Sanity
+ assertEquals(bytes.length, off);
}
@Test
@@ -113,9 +145,31 @@ public class AdobePathWriterTest {
path.curveTo(1, 1, 1, 1, .5, 1);
path.lineTo(.5, .5);
- new AdobePathWriter(path).writePath(); // TODO: Should we allow this?
+ byte[] bytes = new AdobePathWriter(path).writePath();
+
+ assertEquals(6 * 26, bytes.length);
+
+ int off = 0;
+
+ // Path/initial fill rule: Even-Odd (0)
+ assertArrayEquals(new byte[] {0, PATH_FILL_RULE_RECORD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, INITIAL_FILL_RULE_RECORD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+
+ // Rectangle 1: 0, 0, 1, .5
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_LENGTH_RECORD, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_BEZIER_UNLINKED, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 1, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_BEZIER_UNLINKED, 0, -128, 0, 0, 1, 0, 0, 0, 0, -128, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_BEZIER_UNLINKED, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+
+ // Sanity
+ assertEquals(bytes.length, off);
- fail("Test that we have 4 segments, and that it is equal to the one above");
}
@Test
@@ -127,9 +181,30 @@ public class AdobePathWriterTest {
path.lineTo(.5, .5);
path.closePath();
- new AdobePathWriter(path).writePath();
+ byte[] bytes = new AdobePathWriter(path).writePath();
- fail("Test that we have 4 segments, and that it is equal to the one above");
+ assertEquals(6 * 26, bytes.length);
+
+ int off = 0;
+
+ // Path/initial fill rule: Even-Odd (0)
+ assertArrayEquals(new byte[] {0, PATH_FILL_RULE_RECORD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, INITIAL_FILL_RULE_RECORD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+
+ // Rectangle 1: 0, 0, 1, .5
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_LENGTH_RECORD, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_BEZIER_UNLINKED, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 1, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_BEZIER_UNLINKED, 0, -128, 0, 0, 1, 0, 0, 0, 0, -128, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+ assertArrayEquals(new byte[] {0, CLOSED_SUBPATH_BEZIER_UNLINKED, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0},
+ Arrays.copyOfRange(bytes, off, off += 26));
+
+ // Sanity
+ assertEquals(bytes.length, off);
}
@Test
@@ -207,7 +282,6 @@ public class AdobePathWriterTest {
AdobePathWriter pathCreator = new AdobePathWriter(path);
byte[] bytes = pathCreator.writePath();
-// System.err.println(Arrays.toString(bytes));
assertEquals(12 * 26, bytes.length);
diff --git a/imageio/imageio-clippath/src/test/java/com/twelvemonkeys/imageio/path/PathsTest.java b/imageio/imageio-clippath/src/test/java/com/twelvemonkeys/imageio/path/PathsTest.java
index e40e034b..9f5b373b 100644
--- a/imageio/imageio-clippath/src/test/java/com/twelvemonkeys/imageio/path/PathsTest.java
+++ b/imageio/imageio-clippath/src/test/java/com/twelvemonkeys/imageio/path/PathsTest.java
@@ -38,15 +38,18 @@ import org.junit.Test;
import javax.imageio.ImageIO;
import javax.imageio.spi.IIORegistry;
import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
/**
* PathsTest.
@@ -240,6 +243,9 @@ public class PathsTest {
}
static void assertPathEquals(final Path2D expectedPath, final Path2D actualPath) {
+ assertNotNull("Expected path is null, check your tests...", expectedPath);
+ assertNotNull(actualPath);
+
PathIterator expectedIterator = expectedPath.getPathIterator(null);
PathIterator actualIterator = actualPath.getPathIterator(null);
@@ -261,4 +267,37 @@ public class PathsTest {
assertTrue("More points than expected", actualIterator.isDone());
}
+
+ @Test
+ public void testWriteJPEG() throws IOException {
+ Path2D originalPath = readExpectedPath("/ser/multiple-clips.ser");
+
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ BufferedImage image = new BufferedImage(2, 2, BufferedImage.TYPE_3BYTE_BGR);
+ try (ImageOutputStream stream = ImageIO.createImageOutputStream(bytes)) {
+ boolean written = Paths.writeClipped(image, originalPath, "JPEG", stream);
+ assertTrue(written);
+ }
+ assertTrue(bytes.size() > 1024); // Actual size may be plugin specific...
+
+ Path2D actualPath = Paths.readPath(new ByteArrayImageInputStream(bytes.toByteArray()));
+ assertPathEquals(originalPath, actualPath);
+ }
+
+ @Test
+ public void testWriteTIFF() throws IOException {
+ Path2D originalPath = readExpectedPath("/ser/grape-path.ser");
+
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ BufferedImage image = new BufferedImage(2, 2, BufferedImage.TYPE_INT_ARGB);
+ try (ImageOutputStream stream = ImageIO.createImageOutputStream(bytes)) {
+ boolean written = Paths.writeClipped(image, originalPath, "TIFF", stream);
+ assumeTrue(written); // TIFF support is optional
+ }
+
+ assertTrue(bytes.size() > 1024); // Actual size may be plugin specific...
+
+ Path2D actualPath = Paths.readPath(new ByteArrayImageInputStream(bytes.toByteArray()));
+ assertPathEquals(originalPath, actualPath);
+ }
}