001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.image; 031 032import java.awt.geom.AffineTransform; 033import java.awt.image.BufferedImage; 034import java.io.ByteArrayInputStream; 035import java.io.ByteArrayOutputStream; 036import java.io.IOException; 037import java.io.OutputStreamWriter; 038import java.util.Comparator; 039 040import org.apache.batik.svggen.SVGGraphics2DIOException; 041import org.apache.batik.transcoder.TranscoderException; 042import org.apache.batik.transcoder.TranscoderInput; 043import org.apache.batik.transcoder.TranscoderOutput; 044import org.apache.batik.transcoder.image.ImageTranscoder; 045import org.apache.batik.transcoder.image.PNGTranscoder; 046import org.openimaj.image.colour.RGBColour; 047import org.openimaj.image.renderer.ImageRenderer; 048import org.openimaj.image.renderer.RenderHints; 049import org.openimaj.image.renderer.SVGRenderHints; 050import org.openimaj.image.renderer.SVGRenderer; 051import org.openimaj.math.geometry.point.Point2dImpl; 052import org.openimaj.math.geometry.shape.Rectangle; 053 054public class SVGImage extends Image<Float[], SVGImage> { 055 private SVGRenderer renderer; 056 057 /** 058 * @param hints 059 */ 060 public SVGImage(SVGRenderHints hints) { 061 this.renderer = new SVGRenderer(hints); 062 } 063 064 private SVGImage() { 065 // TODO Auto-generated constructor stub 066 } 067 068 /** 069 * Construct an empty SVG-backed image of the given size 070 * 071 * @param w 072 * the width 073 * @param h 074 * the height 075 */ 076 public SVGImage(int w, int h) { 077 this(new SVGRenderHints(w, h)); 078 } 079 080 @Override 081 public SVGImage abs() { 082 return this; 083 } 084 085 @Override 086 public SVGImage addInplace(Image<?, ?> im) { 087 if (!(im instanceof SVGImage)) { 088 this.renderer.drawOIImage(im); 089 } else { 090 this.renderer.drawImage((SVGImage) im, 0, 0); 091 } 092 return null; 093 } 094 095 @Override 096 public SVGImage addInplace(Float[] num) { 097 return this; 098 } 099 100 @Override 101 public SVGImage clip(Float[] min, Float[] max) { 102 return this; 103 } 104 105 @Override 106 public SVGImage clipMax(Float[] thresh) { 107 return this; 108 } 109 110 @Override 111 public SVGImage clipMin(Float[] thresh) { 112 return this; 113 } 114 115 @Override 116 public SVGImage clone() { 117 final SVGImage svgImage = new SVGImage(); 118 svgImage.renderer = new SVGRenderer(svgImage, this.renderer.getGraphics2D().create()); 119 return svgImage; 120 } 121 122 @Override 123 public SVGRenderer createRenderer() { 124 return this.renderer; 125 } 126 127 @Override 128 public ImageRenderer<Float[], SVGImage> createRenderer(RenderHints options) { 129 return this.renderer; 130 } 131 132 @Override 133 public SVGImage divideInplace(Image<?, ?> im) { 134 throw new UnsupportedOperationException(); 135 } 136 137 @Override 138 public SVGImage divideInplace(Float[] val) { 139 throw new UnsupportedOperationException(); 140 } 141 142 @Override 143 public SVGImage extractROI(int x, int y, SVGImage img) { 144 img.renderer = new SVGRenderer(img, img.renderer.getRenderHints(), this.renderer.getGraphics2D().create(x, y, 145 img.getWidth(), img.getHeight())); 146 return img; 147 } 148 149 @Override 150 public SVGImage extractROI(int x, int y, int w, int h) { 151 final SVGImage ret = new SVGImage(w, h); 152 return extractROI(x, y, ret); 153 } 154 155 @Override 156 public SVGImage extractCentreSubPix(float cx, float cy, SVGImage out) { 157 return extractCenter((int) cx, (int) cy, out.getWidth(), out.getHeight()); 158 } 159 160 @Override 161 public SVGImage fill(Float[] colour) { 162 final SVGRenderHints hint = (SVGRenderHints) this.renderer.getRenderHints(); 163 this.renderer = new SVGRenderer(hint); 164 this.renderer.drawShapeFilled(this.getBounds(), colour); 165 return this; 166 } 167 168 @Override 169 public SVGImage flipX() { 170 final AffineTransform tx = AffineTransform.getScaleInstance(-1, 1); 171 tx.translate(this.getWidth(), 0); 172 this.renderer.getGraphics2D().transform(tx); 173 return this; 174 } 175 176 @Override 177 public SVGImage flipY() { 178 final AffineTransform tx = AffineTransform.getScaleInstance(1, -1); 179 tx.translate(0, -this.getHeight()); 180 this.renderer.getGraphics2D().transform(tx); 181 return this; 182 } 183 184 @Override 185 public Rectangle getContentArea() { 186 return new Rectangle(0, 0, getWidth(), getHeight()); 187 } 188 189 @Override 190 public SVGImage getField(org.openimaj.image.Image.Field f) { 191 throw new UnsupportedOperationException(); 192 } 193 194 @Override 195 public SVGImage getFieldCopy(org.openimaj.image.Image.Field f) { 196 throw new UnsupportedOperationException(); 197 } 198 199 @Override 200 public SVGImage getFieldInterpolate(org.openimaj.image.Image.Field f) { 201 throw new UnsupportedOperationException(); 202 } 203 204 @Override 205 public int getHeight() { 206 return this.renderer.getGraphics2D().getSVGCanvasSize().height; 207 } 208 209 @Override 210 public Float[] getPixel(int x, int y) { 211 throw new UnsupportedOperationException(); 212 } 213 214 @Override 215 public Comparator<? super Float[]> getPixelComparator() { 216 throw new UnsupportedOperationException(); 217 } 218 219 @Override 220 public Float[] getPixelInterp(double x, double y) { 221 throw new UnsupportedOperationException(); 222 } 223 224 @Override 225 public Float[] getPixelInterp(double x, double y, Float[] backgroundColour) { 226 throw new UnsupportedOperationException(); 227 } 228 229 @Override 230 public int getWidth() { 231 return this.renderer.getGraphics2D().getSVGCanvasSize().width; 232 } 233 234 @Override 235 public SVGImage internalCopy(SVGImage im) { 236 this.renderer = im.renderer.clone(); 237 this.renderer.setImage(this); 238 return this; 239 } 240 241 @Override 242 public SVGImage internalAssign(SVGImage im) { 243 this.renderer = im.renderer; 244 return this; 245 } 246 247 @Override 248 public SVGImage internalAssign(int[] pixelData, int width, int height) { 249 throw new UnsupportedOperationException(); 250 } 251 252 @Override 253 public SVGImage inverse() { 254 throw new UnsupportedOperationException(); 255 } 256 257 @Override 258 public Float[] max() { 259 throw new UnsupportedOperationException(); 260 } 261 262 @Override 263 public Float[] min() { 264 throw new UnsupportedOperationException(); 265 } 266 267 @Override 268 public SVGImage multiplyInplace(Image<?, ?> im) { 269 throw new UnsupportedOperationException(); 270 } 271 272 @Override 273 public SVGImage multiplyInplace(Float[] num) { 274 throw new UnsupportedOperationException(); 275 } 276 277 @Override 278 public SVGImage newInstance(int width, int height) { 279 return new SVGImage(width, height); 280 } 281 282 @Override 283 public SVGImage normalise() { 284 throw new UnsupportedOperationException(); 285 } 286 287 @Override 288 public void setPixel(int x, int y, Float[] val) { 289 this.renderer.drawPoint(new Point2dImpl(x, y), val, 1); 290 } 291 292 @Override 293 public SVGImage subtractInplace(Image<?, ?> im) { 294 throw new UnsupportedOperationException(); 295 } 296 297 @Override 298 public SVGImage subtractInplace(Float[] num) { 299 throw new UnsupportedOperationException(); 300 } 301 302 @Override 303 public SVGImage threshold(Float[] thresh) { 304 throw new UnsupportedOperationException(); 305 } 306 307 private static class BufferedImageTranscoder extends ImageTranscoder { 308 309 private BufferedImage img; 310 311 @Override 312 public BufferedImage createImage(int w, int h) { 313 final BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 314 return bi; 315 } 316 317 @Override 318 public void writeImage(BufferedImage img, TranscoderOutput arg1) 319 throws TranscoderException 320 { 321 this.img = img; 322 } 323 324 public BufferedImage getBufferedImage() { 325 return this.img; 326 } 327 328 } 329 330 @Override 331 public byte[] toByteImage() { 332 final MBFImage mbf = createMBFImage(); 333 return mbf.toByteImage(); 334 } 335 336 public MBFImage createMBFImage() { 337 final BufferedImageTranscoder t = new BufferedImageTranscoder(); 338 t.addTranscodingHint(PNGTranscoder.KEY_WIDTH, (float) getWidth()); 339 t.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, (float) getHeight()); 340 final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 341 try { 342 this.renderer.write(new OutputStreamWriter(baos)); 343 baos.flush(); 344 baos.close(); 345 final byte[] barr = baos.toByteArray(); 346 final TranscoderInput input = new TranscoderInput(new ByteArrayInputStream(barr)); 347 t.transcode(input, null); 348 } catch (final SVGGraphics2DIOException e) { 349 } catch (final IOException e) { 350 } catch (final TranscoderException e) { 351 } 352 final MBFImage mbf = ImageUtilities.createMBFImage(t.getBufferedImage(), true); 353 return mbf; 354 } 355 356 @Override 357 public int[] toPackedARGBPixels() { 358 final MBFImage mbf = createMBFImage(); 359 return mbf.toPackedARGBPixels(); 360 } 361 362 @Override 363 public SVGImage zero() { 364 final SVGRenderHints hint = (SVGRenderHints) this.renderer.getRenderHints(); 365 this.renderer = new SVGRenderer(hint); 366 this.renderer.drawShapeFilled(this.getBounds(), RGBColour.BLACK); 367 return this; 368 } 369 370 @Override 371 public SVGImage overlayInplace(SVGImage image, int x, int y) { 372 throw new UnsupportedOperationException(); 373 } 374 375 @Override 376 public SVGImage replace(Float[] target, Float[] replacement) { 377 throw new UnsupportedOperationException(); 378 } 379}