/* * JSwiff is an open source Java API for Macromedia Flash file generation * and manipulation * * Copyright (C) 2004-2006 Ralf Terdic (contact@jswiff.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.jswiff.hl.factories; import com.jswiff.SWFDocument; import com.jswiff.SWFWriter; import com.jswiff.swfrecords.AlphaBitmapData; import com.jswiff.swfrecords.FillStyle; import com.jswiff.swfrecords.FillStyleArray; import com.jswiff.swfrecords.LineStyleArray; import com.jswiff.swfrecords.Matrix; import com.jswiff.swfrecords.RGB; import com.jswiff.swfrecords.RGBA; import com.jswiff.swfrecords.Rect; import com.jswiff.swfrecords.ShapeRecord; import com.jswiff.swfrecords.ShapeWithStyle; import com.jswiff.swfrecords.StraightEdgeRecord; import com.jswiff.swfrecords.StyleChangeRecord; import com.jswiff.swfrecords.tags.DefineBitsJPEG2; import com.jswiff.swfrecords.tags.DefineBitsLossless2; import com.jswiff.swfrecords.tags.DefineShape; import com.jswiff.swfrecords.tags.DefinitionTag; import com.jswiff.swfrecords.tags.PlaceObject2; import com.jswiff.swfrecords.tags.ShowFrame; import com.jswiff.util.ImageUtilities; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /** * Creates a SWF document from a BufferedImage instance. * * @author <a href="mailto:ralf@terdic.de">Ralf Terdic</a> */ public class ImageDocumentFactory { private static final byte[] JPEG_DATA_HEADER = new byte[] { (byte) 0xff, (byte) 0xd9, (byte) 0xff, (byte) 0xd8 }; private BufferedImage image; private int docWidth; private int docHeight; private boolean dimensionsSet; private RGB backgroundColor; private SWFDocument doc; private int quality = -1; private boolean lossless; /** * Creates a new ImageDocFactory instance. * * @param image BufferedImage instance */ public ImageDocumentFactory(BufferedImage image) { this.image = image; } /** * Sets the background color of the document. Default is white. * * @param backgroundColor background color */ public void setBackgroundColor(RGB backgroundColor) { this.backgroundColor = backgroundColor; } /** * Sets the dimensions of the document. The default dimensions are the * dimesions of the image. * * @param docWidth doc width (pixels) * @param docHeight doc height (pixels) */ public void setDimensions(int docWidth, int docHeight) { this.docWidth = docWidth; this.docHeight = docHeight; dimensionsSet = true; } /** * Creates the SWF document and returns it. * * @return SWF doc */ public SWFDocument getDocument() { initDocument(); return doc; } /** * Sets the lossless flag. If this flag is set, the image is saved as * lossless bitmap in the generated SWF. * * @param lossless lossless flag */ public void setLossless(boolean lossless) { this.lossless = lossless; } /** * Sets the quality of the picture. This affects the JPEG compression used. * This is obviously not relevant when the lossless flag is set. * * @param percent image quality in percent */ public void setQuality(int percent) { quality = percent; } /** * Main method for quick tests, pass input file (image format, e.g. jpg or * bmp) and output file (swf). * * @param args image, swf files * * @throws IOException if an I/O error occured */ public static void main(String[] args) throws IOException { String imgFileName = args[0]; String swfFileName = args[1]; BufferedImage img = ImageUtilities.loadImage( new FileInputStream(imgFileName)); ImageDocumentFactory documentFactory = new ImageDocumentFactory(img); //documentFactory.setDimensions(200, 150); //documentFactory.setQuality(80); documentFactory.setLossless(true); // use DefineBitsLossless2 SWFDocument document = documentFactory.getDocument(); SWFWriter writer = new SWFWriter( document, new FileOutputStream(swfFileName)); writer.write(); } private Rect getShapeBounds() { int imageWidth = image.getWidth(); int imageHeight = image.getHeight(); if (!dimensionsSet) { return new Rect(0, imageWidth * 20, 0, imageHeight * 20); } // make shape fit into document int shapeWidth; int shapeHeight; if ( (((double) docWidth) / docHeight) > (((double) imageWidth) / imageHeight)) { shapeHeight = docHeight * 20; shapeWidth = (shapeHeight * imageWidth) / imageHeight; } else { shapeWidth = docWidth * 20; shapeHeight = (shapeWidth * imageHeight) / imageWidth; } return new Rect(0, shapeWidth, 0, shapeHeight); } private DefineBitsJPEG2 createBitsJPEG2() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { if (quality >= 0) { ImageUtilities.saveImageAsJPEG(image, baos, quality); } else { ImageUtilities.saveImageAsJPEG(image, baos); } } catch (IOException e) { // ignore } byte[] imageData = baos.toByteArray(); int imageDataLength = imageData.length; int headerLength = JPEG_DATA_HEADER.length; byte[] extendedImageData = new byte[headerLength + imageDataLength]; System.arraycopy(JPEG_DATA_HEADER, 0, extendedImageData, 0, headerLength); System.arraycopy( imageData, 0, extendedImageData, headerLength, imageDataLength); DefineBitsJPEG2 bitsJPEG2 = new DefineBitsJPEG2( doc.getNewCharacterId(), extendedImageData); return bitsJPEG2; } private DefineBitsLossless2 createBitsLossless2() { RGBA[] rgbaArray = ImageUtilities.getRGBAArray(image); AlphaBitmapData alphaBitmap = new AlphaBitmapData(rgbaArray); DefineBitsLossless2 bitsLossless2 = new DefineBitsLossless2( doc.getNewCharacterId(), DefineBitsLossless2.FORMAT_32_BIT_RGBA, docWidth, docHeight, alphaBitmap); return bitsLossless2; } private DefineShape createImageShape(int imageCharacterId) { Rect shapeBounds = getShapeBounds(); ShapeWithStyle styles = createShapeWithStyle(shapeBounds, imageCharacterId); DefineShape shape = new DefineShape( doc.getNewCharacterId(), shapeBounds, styles); return shape; } private PlaceObject2 createPlaceObject2Tag(int imageShapeCharacterId) { PlaceObject2 placeObject2 = new PlaceObject2(1); placeObject2.setCharacterId(imageShapeCharacterId); placeObject2.setMatrix(new Matrix(0, 0)); return placeObject2; } private ShapeWithStyle createShapeWithStyle( Rect shapeBounds, int imageCharacterId) { Matrix bitmapMatrix = new Matrix(0, 0); int shapeXMax = (int) shapeBounds.getXMax(); int shapeYMax = (int) shapeBounds.getYMax(); bitmapMatrix.setScale( (float) shapeXMax / (image.getWidth()), (float) shapeYMax / (image.getHeight())); FillStyle fillStyle = new FillStyle( imageCharacterId, bitmapMatrix, FillStyle.TYPE_CLIPPED_BITMAP); FillStyleArray fillStyles = new FillStyleArray(); fillStyles.addStyle(fillStyle); ShapeRecord[] shapeRecords = new ShapeRecord[5]; StyleChangeRecord styleChangeRecord = new StyleChangeRecord(); styleChangeRecord.setFillStyle1(1); styleChangeRecord.setMoveTo(shapeXMax, shapeYMax); shapeRecords[0] = styleChangeRecord; shapeRecords[1] = new StraightEdgeRecord(-shapeXMax, 0); shapeRecords[2] = new StraightEdgeRecord(0, -shapeYMax); shapeRecords[3] = new StraightEdgeRecord(shapeXMax, 0); shapeRecords[4] = new StraightEdgeRecord(0, shapeYMax); ShapeWithStyle shapeWithStyle = new ShapeWithStyle( fillStyles, new LineStyleArray(), shapeRecords); return shapeWithStyle; } private void initDocument() { doc = new SWFDocument(); if (!dimensionsSet) { docWidth = image.getWidth(); docHeight = image.getHeight(); } doc.setFrameSize(new Rect(0, docWidth * 20, 0, docHeight * 20)); doc.setCompressed(true); if (backgroundColor != null) { doc.setBackgroundColor(backgroundColor); } DefinitionTag bitmapTag; if (lossless) { bitmapTag = createBitsLossless2(); } else { bitmapTag = createBitsJPEG2(); } int imageCharacterId = bitmapTag.getCharacterId(); doc.addTag(bitmapTag); DefineShape imageShape = createImageShape(imageCharacterId); doc.addTag(imageShape); doc.addTag(createPlaceObject2Tag(imageShape.getCharacterId())); doc.addTag(new ShowFrame()); } }