Thread: [Patchanim-commit] SF.net SVN: patchanim: [130] trunk/patchanim/src/com/mebigfatguy
Brought to you by:
dbrosius
From: <dbr...@us...> - 2008-02-10 04:33:37
|
Revision: 130 http://patchanim.svn.sourceforge.net/patchanim/?rev=130&view=rev Author: dbrosius Date: 2008-02-09 20:33:41 -0800 (Sat, 09 Feb 2008) Log Message: ----------- start adding support for apngs Modified Paths: -------------- trunk/patchanim/src/com/mebigfatguy/patchanim/ExportType.java trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java trunk/patchanim/src/com/mebigfatguy/patchanim/main/PatchAnimBundle.java trunk/patchanim/src/com/mebigfatguy/patchanim/resources.properties Added Paths: ----------- trunk/patchanim/src/com/mebigfatguy/apng/ trunk/patchanim/src/com/mebigfatguy/apng/APngEncoder.java Added: trunk/patchanim/src/com/mebigfatguy/apng/APngEncoder.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/apng/APngEncoder.java (rev 0) +++ trunk/patchanim/src/com/mebigfatguy/apng/APngEncoder.java 2008-02-10 04:33:41 UTC (rev 130) @@ -0,0 +1,268 @@ +/* + * patchanim - A bezier surface patch color blend gif builder + * Copyright (C) 2008 Dave Brosius + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package com.mebigfatguy.apng; + +import java.awt.image.BufferedImage; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import javax.imageio.ImageIO; + +import com.mebigfatguy.patchanim.ExportType; + +/** + * generates apng files by simply relying on the built in png encoder of ImageIO + * and sewing together multiple chunks from the underlying pngs. + */ +public class APngEncoder { + private static final byte[] HEADER = new byte[] { -119, 80, 78, 71, 13, 10, 26, 10 }; + private static final int IHDR = 0x49484452; + private static final int IDAT = 0x49444154; + private static final int IEND = 0x49454E44; + private static final int acTL = 0x6163544C; + private static final int fcTL = 0x6663544C; + private static final int fdAT = 0x66644154; + + private DataOutputStream out = null; + private boolean started = false; + private boolean closeStream = false; + private boolean headerWritten = false; + private boolean repeatInfinite = false; + private int delay = 100; + private int frameCount = 1; + private int seqNum = 0; + private boolean processedFirstFrame = false; + + public void setDelay(int ms) { + delay = ms; + } + + public void setRepeat(boolean infinite) { + repeatInfinite = infinite; + } + + public void setNumFrames(int frames) { + frameCount = frames; + } + + public boolean start(OutputStream os) { + if (os == null) + return false; + boolean ok = true; + closeStream = false; + out = new DataOutputStream(os); + try { + out.write(HEADER); + } catch (IOException e) { + ok = false; + } + return started = ok; + } + + public boolean start(String file) { + boolean ok = true; + try { + out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); + ok = start(out); + closeStream = true; + } catch (IOException e) { + ok = false; + } + return started = ok; + } + + public boolean finish() { + if (!started) + return false; + try { + if (closeStream) + out.close(); + } catch (IOException ioe) { + } + + return true; + } + + public boolean addFrame(BufferedImage im) { + if ((im == null) || !started) + return false; + try { + PngStream pStrm; + boolean sawIDAT = false; + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(im.getHeight() * im.getWidth()); //a conservative estimate + ImageIO.write(im, ExportType.Pngs.getExtension(), baos); + pStrm = new PngStream(baos.toByteArray()); + baos.reset(); + } + Chunk chunk = pStrm.readNextChunk(pStrm); + while (chunk != null) { + switch (chunk.type) { + case IHDR: + if (!headerWritten) { + chunk.write(out); + headerWritten = true; + Chunk acTLChunk = new Chunk(8, acTL); + + acTLChunk.injectInt(0, frameCount); + acTLChunk.injectInt(4, repeatInfinite ? 0 : 1); + acTLChunk.calcCRC(); + acTLChunk.write(out); + } + break; + + case IDAT: + if (!sawIDAT) { + Chunk fcTLChunk = new Chunk(26, fcTL); + fcTLChunk.injectInt(0, seqNum); + fcTLChunk.injectInt(4, im.getWidth()); + fcTLChunk.injectInt(8, im.getHeight()); + fcTLChunk.injectInt(12, 0); + fcTLChunk.injectInt(16, 0); + fcTLChunk.injectShort(20, delay); + fcTLChunk.injectShort(22, 1000); + fcTLChunk.injectShort(24, 0); + fcTLChunk.calcCRC(); + fcTLChunk.write(out); + sawIDAT = true; + } + if (!processedFirstFrame) { + chunk.write(out); + } else { + Chunk fdATChunk = new Chunk(chunk.length + 4, fdAT); + fdATChunk.injectInt(0, seqNum); + System.arraycopy(chunk.data, 0, fdATChunk.data, 4, chunk.length); + fdATChunk.calcCRC(); + fdATChunk.write(out); + } + break; + + case IEND: + if (seqNum >= frameCount) + chunk.write(out); + break; + } + chunk = pStrm.readNextChunk(pStrm); + } + processedFirstFrame = true; + seqNum++; + + return true; + } catch (IOException ioe) { + return false; + } finally { + + } + } + + static class PngStream { + public PngStream(byte[] pngData) { + pos = HEADER.length; + data = pngData; + } + + public Chunk readNextChunk(PngStream pStrm) { + if (pos >= data.length) + return null; + + Chunk c = new Chunk(readNextInt(), readNextInt()); + + System.arraycopy(data, pos, c.data, 0, c.length); + pos += c.length; + c.crc = readNextInt(); + return c; + } + + private int readNextInt() { + int val = 0; + for (int i = 0; i < 4; i++) { + val <<= 8; + val |= (0x00FF & data[pos++]); + } + return val; + } + + public int pos; + public byte[] data; + } + + static class Chunk { + private static long crcTable[] = new long[256]; + static { + long c; + int n, k; + + for (n = 0; n < 256; n++) { + c = (long) n; + for (k = 0; k < 8; k++) { + if ((c & 1) != 0) + c = 0xedb88320L ^ (c >> 1); + else + c = c >> 1; + } + crcTable[n] = c; + } + } + + public int length; + public int type; + public byte[] data; + public int crc; + + public Chunk(int len, int chunkType) { + length = len; + type = chunkType; + data = new byte[length]; + crc = 0; + } + + public void write(DataOutputStream out) throws IOException { + out.writeInt(length); + out.writeInt(type); + out.write(data); + out.writeInt(crc); + } + + public void injectInt(int offset, int value) { + data[offset++] = (byte)(value >> 24 & 0x00FF); + data[offset++] = (byte)(value >> 16 & 0x00FF); + data[offset++] = (byte)(value >> 8 & 0x00FF); + data[offset] = (byte)(value & 0x00FF); + } + + public void injectShort(int offset, int value) { + data[offset++] = (byte)(value >> 8 & 0x00FF); + data[offset] = (byte)(value & 0x00FF); + } + + public void calcCRC() { + long c = -1; + for (int n = 0; n < length; n++) { + c = crcTable[(int)((c ^ data[n]) & 0x00FF)] ^ (c >> 8); + } + + c &= -1; + crc = (int)c; + } + } +} Property changes on: trunk/patchanim/src/com/mebigfatguy/apng/APngEncoder.java ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:eol-style + native Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/ExportType.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/ExportType.java 2008-02-10 01:12:47 UTC (rev 129) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/ExportType.java 2008-02-10 04:33:41 UTC (rev 130) @@ -9,6 +9,7 @@ * <li><b>Pngs</b> a series of Png files in a directory</li> * <li><b>Gifs</b> a series of Gif files in a directory</li> * <li><b>AnimatedGif</b> an animated gif file</li> + * <li><b>AnimatedPng</b> an animated png file</li> * <li><b>Mpeg</b> an animated mpeg file</li> * </ul> */ @@ -17,6 +18,7 @@ Pngs("png", true, PatchAnimBundle.PNGSERIESFILTER), Gifs("gif", true, PatchAnimBundle.GIFSERIESFILTER), AnimatedGif("gif", false, PatchAnimBundle.ANIMATEDGIFFILTER), + AnimatedPng("png", false, PatchAnimBundle.ANIMATEDPNGFILTER), MPeg("mpeg", false, PatchAnimBundle.MPEGFILTER); private String ext; Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java 2008-02-10 01:12:47 UTC (rev 129) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java 2008-02-10 04:33:41 UTC (rev 130) @@ -60,6 +60,7 @@ private JMenuItem exportPngsItem; private JMenuItem exportGifsItem; private JMenuItem exportAnimatedGifItem; + private JMenuItem exportAnimatedPngItem; private JMenuItem quitItem; private PatchAnimDocument document; private File documentLocation; @@ -106,11 +107,13 @@ exportPngsItem = new JMenuItem(rb.getString(PatchAnimBundle.PNGSERIES)); exportGifsItem = new JMenuItem(rb.getString(PatchAnimBundle.GIFSERIES)); exportAnimatedGifItem = new JMenuItem(rb.getString(PatchAnimBundle.ANIMATEDGIF)); + exportAnimatedPngItem = new JMenuItem(rb.getString(PatchAnimBundle.ANIMATEDPNG)); exportMenu.add(exportJpgsItem); exportMenu.add(exportPngsItem); exportMenu.add(exportGifsItem); exportMenu.addSeparator(); exportMenu.add(exportAnimatedGifItem); + exportMenu.add(exportAnimatedPngItem); fileMenu.add(exportMenu); fileMenu.addSeparator(); quitItem = new JMenuItem(rb.getString(PatchAnimBundle.QUIT)); @@ -236,6 +239,12 @@ } }); + exportAnimatedPngItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ae) { + export(ExportType.AnimatedPng); + } + }); + quitItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { try { Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java 2008-02-10 01:12:47 UTC (rev 129) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java 2008-02-10 04:33:41 UTC (rev 130) @@ -29,6 +29,7 @@ import javax.imageio.ImageIO; import com.fmsware.gif.AnimatedGifEncoder; +import com.mebigfatguy.apng.APngEncoder; import com.mebigfatguy.patchanim.AnimationType; import com.mebigfatguy.patchanim.ExportType; import com.mebigfatguy.patchanim.OutOfBoundsColor; @@ -42,6 +43,7 @@ private ExportType type; private File loc; private AnimatedGifEncoder agEncoder; + private APngEncoder apngEncoder; private int totalImages; private Set<ExportListener> elisteners = new HashSet<ExportListener>(); @@ -50,6 +52,8 @@ loc = location; if (type == ExportType.AnimatedGif) agEncoder = new AnimatedGifEncoder(); + else if (type == ExportType.AnimatedPng) + apngEncoder = new APngEncoder(); else agEncoder = null; } @@ -70,6 +74,8 @@ baseName = baseName + dotExt; if (type == ExportType.AnimatedGif) agEncoder.start(new File(loc, baseName).getPath()); + else if (type == ExportType.AnimatedPng) + apngEncoder.start(new File(loc, baseName).getPath()); } totalImages = calcImageCount(document); @@ -84,6 +90,9 @@ if (type == ExportType.AnimatedGif) { agEncoder.setRepeat((atype != AnimationType.None) ? 0 : -1); + } else if (type == ExportType.AnimatedPng) { + apngEncoder.setRepeat(atype != AnimationType.None); + apngEncoder.setNumFrames(totalImages); } if (lastPatch == 0) { @@ -118,6 +127,8 @@ } finally { if (type == ExportType.AnimatedGif) { agEncoder.finish(); + } else if (type == ExportType.AnimatedPng) { + apngEncoder.finish(); } } } @@ -137,6 +148,9 @@ } else if (type == ExportType.AnimatedGif) { agEncoder.addFrame(image); agEncoder.setDelay(100); + } else if (type == ExportType.AnimatedPng) { + apngEncoder.setDelay(100); + apngEncoder.addFrame(image); } else ImageIO.write(image, type.getExtension(), imageFile); Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/main/PatchAnimBundle.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/main/PatchAnimBundle.java 2008-02-10 01:12:47 UTC (rev 129) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/main/PatchAnimBundle.java 2008-02-10 04:33:41 UTC (rev 130) @@ -38,6 +38,8 @@ public static final String GIFSERIESFILTER = "patchanim.filter.gifs"; public static final String ANIMATEDGIF = "patchanim.animatedgif"; public static final String ANIMATEDGIFFILTER = "patchanim.filter.animatedgif"; + public static final String ANIMATEDPNG = "patchanim.apng"; + public static final String ANIMATEDPNGFILTER = "patchanim.filter.apng"; public static final String MPEG = "patchanim.mpeg"; public static final String MPEGFILTER = "patchanim.filter.mpeg"; public static final String EXPORTINGFILE = "patchanim.exportfile"; Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/resources.properties =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/resources.properties 2008-02-10 01:12:47 UTC (rev 129) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/resources.properties 2008-02-10 04:33:41 UTC (rev 130) @@ -31,6 +31,8 @@ patchanim.filter.gifs = Gif Files (*.gif) patchanim.animatedgif = an Animated Gif patchanim.filter.animatedgif = Gif Files (*.gif) +patchanim.apng = an Animated Png +patchanim.filter.apng = (Png Files (*.png) patchanim.mpeg = an MPEG patchanim.filter.mpeg = MPEG Files (*.mpg) patchanim.exportfile = Exporting Animation This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dbr...@us...> - 2008-02-10 05:29:47
|
Revision: 131 http://patchanim.svn.sourceforge.net/patchanim/?rev=131&view=rev Author: dbrosius Date: 2008-02-09 21:29:53 -0800 (Sat, 09 Feb 2008) Log Message: ----------- fix image counts, and make sure IEND gets written for APNGS Modified Paths: -------------- trunk/patchanim/src/com/mebigfatguy/apng/APngEncoder.java trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java Modified: trunk/patchanim/src/com/mebigfatguy/apng/APngEncoder.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/apng/APngEncoder.java 2008-02-10 04:33:41 UTC (rev 130) +++ trunk/patchanim/src/com/mebigfatguy/apng/APngEncoder.java 2008-02-10 05:29:53 UTC (rev 131) @@ -158,7 +158,7 @@ break; case IEND: - if (seqNum >= frameCount) + if (seqNum >= (frameCount - 1)) chunk.write(out); break; } Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java 2008-02-10 04:33:41 UTC (rev 130) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java 2008-02-10 05:29:53 UTC (rev 131) @@ -102,22 +102,27 @@ for(int p = 0; p < lastPatch; p++) { CombinedPatch startPatch = patches.get(p); CombinedPatch endPatch = patches.get(p+1); - for (int t = 0; t < tweenCount; t++) { - CombinedPatch tweenPatch = CombinedPatch.tween(startPatch, endPatch, (double)t / (double)tweenCount); + for (int t = 0; t < tweenCount + 1; t++) { + CombinedPatch tweenPatch = CombinedPatch.tween(startPatch, endPatch, (double)t / (double)(tweenCount + 1)); PatchGenerator.recalcCombinedImage(tweenPatch, image, oob); writeSingleFile(image, imageIndex++, loc, baseName, type); } } - if (atype == AnimationType.None) - return; + if ((atype == AnimationType.None) || (atype == AnimationType.Cycle)) { + CombinedPatch patch = patches.get(lastPatch); + PatchGenerator.recalcCombinedImage(patch, image, oob); + writeSingleFile(image, imageIndex++, loc, baseName, type); + if (atype == AnimationType.None) + return; + } if (atype == AnimationType.Wave) { for (int p = lastPatch; p > 0; p--) { CombinedPatch startPatch = patches.get(p-1); CombinedPatch endPatch = patches.get(p); - for (int t = tweenCount - 1; t >= 0; t--) { - CombinedPatch tweenPatch = CombinedPatch.tween(startPatch, endPatch, (double)t / (double)tweenCount); + for (int t = tweenCount + 1; t > 0; t--) { + CombinedPatch tweenPatch = CombinedPatch.tween(startPatch, endPatch, (double)t / (double)(tweenCount + 1)); PatchGenerator.recalcCombinedImage(tweenPatch, image, oob); writeSingleFile(image, imageIndex++, loc, baseName, type); } @@ -166,10 +171,13 @@ } private int calcImageCount(PatchAnimDocument document) { - int total = (document.getPatches().size() - 1) * document.getTweenCount() + 1; + int numPatches = document.getPatches().size(); + int total = (numPatches - 1) * document.getTweenCount() + (numPatches - 1); if (document.getAnimationType() == AnimationType.Wave) - total *= 2; + total = total * 2; + else + total++; return total; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dbr...@us...> - 2008-02-10 17:26:18
|
Revision: 148 http://patchanim.svn.sourceforge.net/patchanim/?rev=148&view=rev Author: dbrosius Date: 2008-02-10 09:26:23 -0800 (Sun, 10 Feb 2008) Log Message: ----------- Renamed apng to encoders Added Paths: ----------- trunk/patchanim/src/com/mebigfatguy/encoders/ Removed Paths: ------------- trunk/patchanim/src/com/mebigfatguy/apng/ Copied: trunk/patchanim/src/com/mebigfatguy/encoders (from rev 147, trunk/patchanim/src/com/mebigfatguy/apng) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dbr...@us...> - 2008-02-10 17:34:21
|
Revision: 149 http://patchanim.svn.sourceforge.net/patchanim/?rev=149&view=rev Author: dbrosius Date: 2008-02-10 09:34:27 -0800 (Sun, 10 Feb 2008) Log Message: ----------- break out Chunk and PrmStream to separate class, remove references to MPeg, and stub in Mng support Modified Paths: -------------- trunk/patchanim/src/com/mebigfatguy/encoders/APngEncoder.java trunk/patchanim/src/com/mebigfatguy/patchanim/ExportType.java trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java trunk/patchanim/src/com/mebigfatguy/patchanim/main/PatchAnimBundle.java trunk/patchanim/src/com/mebigfatguy/patchanim/resources.properties Added Paths: ----------- trunk/patchanim/src/com/mebigfatguy/encoders/Chunk.java trunk/patchanim/src/com/mebigfatguy/encoders/MngEncoder.java trunk/patchanim/src/com/mebigfatguy/encoders/PngStream.java Modified: trunk/patchanim/src/com/mebigfatguy/encoders/APngEncoder.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/encoders/APngEncoder.java 2008-02-10 17:26:23 UTC (rev 148) +++ trunk/patchanim/src/com/mebigfatguy/encoders/APngEncoder.java 2008-02-10 17:34:27 UTC (rev 149) @@ -16,7 +16,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -package com.mebigfatguy.apng; +package com.mebigfatguy.encoders; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; @@ -25,7 +25,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.zip.CRC32; import javax.imageio.ImageIO; @@ -122,7 +121,7 @@ pStrm = new PngStream(baos.toByteArray()); baos.reset(); } - Chunk chunk = pStrm.readNextChunk(pStrm); + Chunk chunk = pStrm.readNextChunk(); while (chunk != null) { switch (chunk.type) { case IHDR: @@ -164,7 +163,7 @@ } break; } - chunk = pStrm.readNextChunk(pStrm); + chunk = pStrm.readNextChunk(); } processedFirstFrame = true; @@ -175,81 +174,4 @@ } } - - static class PngStream { - public PngStream(byte[] pngData) { - pos = HEADER.length; - data = pngData; - } - - public Chunk readNextChunk(PngStream pStrm) { - if (pos >= data.length) - return null; - - Chunk c = new Chunk(readNextInt(), readNextInt()); - - System.arraycopy(data, pos, c.data, 0, c.length); - pos += c.length; - c.crc = readNextInt(); - return c; - } - - private int readNextInt() { - int val = 0; - for (int i = 0; i < 4; i++) { - val <<= 8; - val |= (0x00FF & data[pos++]); - } - return val; - } - - public int pos; - public byte[] data; - } - - static class Chunk { - - public int length; - public int type; - public byte[] data; - public int crc; - - public Chunk(int len, int chunkType) { - length = len; - type = chunkType; - data = new byte[length]; - crc = 0; - } - - public void write(DataOutputStream out) throws IOException { - out.writeInt(length); - out.writeInt(type); - out.write(data); - out.writeInt(crc); - } - - public void injectInt(int offset, int value) { - data[offset++] = (byte)(value >> 24 & 0x00FF); - data[offset++] = (byte)(value >> 16 & 0x00FF); - data[offset++] = (byte)(value >> 8 & 0x00FF); - data[offset] = (byte)(value & 0x00FF); - } - - public void injectShort(int offset, int value) { - data[offset++] = (byte)(value >> 8 & 0x00FF); - data[offset] = (byte)(value & 0x00FF); - } - - public void calcCRC() { - CRC32 crc32 = new CRC32(); - byte[] typeBytes = new byte[4]; - typeBytes[0] = (byte)(type >> 24 & 0x00FF); - typeBytes[1] = (byte)(type >> 16 & 0x00FF); - typeBytes[2] = (byte)(type >> 8 & 0x00FF); - typeBytes[3] = (byte)(type & 0x00FF); - crc32.update(typeBytes); - crc32.update(data); - crc = (int)crc32.getValue(); - } - } } Added: trunk/patchanim/src/com/mebigfatguy/encoders/Chunk.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/encoders/Chunk.java (rev 0) +++ trunk/patchanim/src/com/mebigfatguy/encoders/Chunk.java 2008-02-10 17:34:27 UTC (rev 149) @@ -0,0 +1,69 @@ +/* + * patchanim - A bezier surface patch color blend gif builder + * Copyright (C) 2008 Dave Brosius + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package com.mebigfatguy.encoders; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.zip.CRC32; + +public class Chunk { + + public int length; + public int type; + public byte[] data; + public int crc; + + public Chunk(int len, int chunkType) { + length = len; + type = chunkType; + data = new byte[length]; + crc = 0; + } + + public void write(DataOutputStream out) throws IOException { + out.writeInt(length); + out.writeInt(type); + out.write(data); + out.writeInt(crc); + } + + public void injectInt(int offset, int value) { + data[offset++] = (byte)(value >> 24 & 0x00FF); + data[offset++] = (byte)(value >> 16 & 0x00FF); + data[offset++] = (byte)(value >> 8 & 0x00FF); + data[offset] = (byte)(value & 0x00FF); + } + + public void injectShort(int offset, int value) { + data[offset++] = (byte)(value >> 8 & 0x00FF); + data[offset] = (byte)(value & 0x00FF); + } + + public void calcCRC() { + CRC32 crc32 = new CRC32(); + byte[] typeBytes = new byte[4]; + typeBytes[0] = (byte)(type >> 24 & 0x00FF); + typeBytes[1] = (byte)(type >> 16 & 0x00FF); + typeBytes[2] = (byte)(type >> 8 & 0x00FF); + typeBytes[3] = (byte)(type & 0x00FF); + crc32.update(typeBytes); + crc32.update(data); + crc = (int)crc32.getValue(); + } +} \ No newline at end of file Property changes on: trunk/patchanim/src/com/mebigfatguy/encoders/Chunk.java ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:eol-style + native Added: trunk/patchanim/src/com/mebigfatguy/encoders/MngEncoder.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/encoders/MngEncoder.java (rev 0) +++ trunk/patchanim/src/com/mebigfatguy/encoders/MngEncoder.java 2008-02-10 17:34:27 UTC (rev 149) @@ -0,0 +1,148 @@ +/* + * patchanim - A bezier surface patch color blend gif builder + * Copyright (C) 2008 Dave Brosius + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package com.mebigfatguy.encoders; + +import java.awt.image.BufferedImage; +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import javax.imageio.ImageIO; + +import com.mebigfatguy.patchanim.ExportType; + +/** + * generates mng files by simply relying on the built in png encoder of ImageIO + * and sewing together multiple chunks from the underlying pngs. + */ +public class MngEncoder { + private static final byte[] HEADER = new byte[] { -118, 77, 78, 71, 13, 10, 26, 10 }; + private static final int IHDR = 0x49484452; + private static final int IDAT = 0x49444154; + private static final int IEND = 0x49454E44; + private static final int MHDR = 0; + private static final int MEND = 0; + + private DataOutputStream out = null; + private boolean started = false; + private boolean closeStream = false; + private boolean headerWritten = false; + private boolean repeatInfinite = false; + private int delay = 100; + private int frameCount = 1; + private int seqNum = 0; + private boolean processedFirstFrame = false; + + public void setDelay(int ms) { + delay = ms; + } + + public void setRepeat(boolean infinite) { + repeatInfinite = infinite; + } + + public void setNumFrames(int frames) { + frameCount = frames; + } + + public boolean start(OutputStream os) { + if (os == null) + return false; + boolean ok = true; + closeStream = false; + out = new DataOutputStream(os); + try { + out.write(HEADER); + } catch (IOException e) { + ok = false; + } + return started = ok; + } + + public boolean start(String file) { + boolean ok = true; + try { + out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); + ok = start(out); + closeStream = true; + } catch (IOException e) { + ok = false; + } + return started = ok; + } + + public boolean finish() { + if (!started) + return false; + try { + Chunk iendChunk = new Chunk(0, MEND); + iendChunk.calcCRC(); + iendChunk.write(out); + if (closeStream) + out.close(); + } catch (IOException ioe) { + } finally { + out = null; + started = false; + } + + return true; + } + + public boolean addFrame(BufferedImage im) { + if ((im == null) || !started) + return false; + try { + PngStream pStrm; + boolean sawIDAT = false; + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(im.getHeight() * im.getWidth()); //a conservative estimate + ImageIO.write(im, ExportType.Pngs.getExtension(), baos); + pStrm = new PngStream(baos.toByteArray()); + baos.reset(); + } + Chunk chunk = pStrm.readNextChunk(); + while (chunk != null) { + switch (chunk.type) { + case IHDR: + if (!headerWritten) { + Chunk mhdrChunk = new Chunk(28, MHDR); + mhdrChunk.calcCRC(); + mhdrChunk.write(out); + } + break; + + case IDAT: + break; + } + chunk = pStrm.readNextChunk(); + } + processedFirstFrame = true; + + return true; + } catch (IOException ioe) { + return false; + } finally { + + } + } +} Property changes on: trunk/patchanim/src/com/mebigfatguy/encoders/MngEncoder.java ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:eol-style + native Added: trunk/patchanim/src/com/mebigfatguy/encoders/PngStream.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/encoders/PngStream.java (rev 0) +++ trunk/patchanim/src/com/mebigfatguy/encoders/PngStream.java 2008-02-10 17:34:27 UTC (rev 149) @@ -0,0 +1,52 @@ +/* + * patchanim - A bezier surface patch color blend gif builder + * Copyright (C) 2008 Dave Brosius + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package com.mebigfatguy.encoders; + +public class PngStream { + private static final int HEADERLENGTH = 8; + public int pos; + public byte[] data; + + public PngStream(byte[] pngData) { + pos = HEADERLENGTH; + data = pngData; + } + + public Chunk readNextChunk() { + if (pos >= data.length) + return null; + + Chunk c = new Chunk(readNextInt(), readNextInt()); + + System.arraycopy(data, pos, c.data, 0, c.length); + pos += c.length; + c.crc = readNextInt(); + return c; + } + + private int readNextInt() { + int val = 0; + for (int i = 0; i < 4; i++) { + val <<= 8; + val |= (0x00FF & data[pos++]); + } + return val; + } + +} Property changes on: trunk/patchanim/src/com/mebigfatguy/encoders/PngStream.java ___________________________________________________________________ Name: svn:mime-type + text/plain Name: svn:eol-style + native Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/ExportType.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/ExportType.java 2008-02-10 17:26:23 UTC (rev 148) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/ExportType.java 2008-02-10 17:34:27 UTC (rev 149) @@ -10,7 +10,7 @@ * <li><b>Gifs</b> a series of Gif files in a directory</li> * <li><b>AnimatedGif</b> an animated gif file</li> * <li><b>AnimatedPng</b> an animated png file</li> - * <li><b>Mpeg</b> an animated mpeg file</li> + * <li><b>AnimatedMng</b> an animated mng file</li> * </ul> */ public enum ExportType { @@ -19,7 +19,7 @@ Gifs("gif", true, PatchAnimBundle.GIFSERIESFILTER), AnimatedGif("gif", false, PatchAnimBundle.ANIMATEDGIFFILTER), AnimatedPng("png", false, PatchAnimBundle.ANIMATEDPNGFILTER), - MPeg("mpeg", false, PatchAnimBundle.MPEGFILTER); + AnimatedMng("mng", false, PatchAnimBundle.ANIMATEDMNGFILTER); private String ext; private boolean multi; Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java 2008-02-10 17:26:23 UTC (rev 148) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java 2008-02-10 17:34:27 UTC (rev 149) @@ -61,6 +61,7 @@ private JMenuItem exportGifsItem; private JMenuItem exportAnimatedGifItem; private JMenuItem exportAnimatedPngItem; + private JMenuItem exportAnimatedMngItem; private JMenuItem quitItem; private PatchAnimDocument document; private File documentLocation; @@ -108,12 +109,15 @@ exportGifsItem = new JMenuItem(rb.getString(PatchAnimBundle.GIFSERIES)); exportAnimatedGifItem = new JMenuItem(rb.getString(PatchAnimBundle.ANIMATEDGIF)); exportAnimatedPngItem = new JMenuItem(rb.getString(PatchAnimBundle.ANIMATEDPNG)); + exportAnimatedMngItem = new JMenuItem(rb.getString(PatchAnimBundle.ANIMATEDMNG)); + exportAnimatedMngItem.setEnabled(false); exportMenu.add(exportJpgsItem); exportMenu.add(exportPngsItem); exportMenu.add(exportGifsItem); exportMenu.addSeparator(); exportMenu.add(exportAnimatedGifItem); exportMenu.add(exportAnimatedPngItem); + exportMenu.add(exportAnimatedMngItem); fileMenu.add(exportMenu); fileMenu.addSeparator(); quitItem = new JMenuItem(rb.getString(PatchAnimBundle.QUIT)); @@ -245,6 +249,12 @@ } }); + exportAnimatedMngItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ae) { + export(ExportType.AnimatedMng); + } + }); + quitItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { try { Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java 2008-02-10 17:26:23 UTC (rev 148) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java 2008-02-10 17:34:27 UTC (rev 149) @@ -29,7 +29,8 @@ import javax.imageio.ImageIO; import com.fmsware.gif.AnimatedGifEncoder; -import com.mebigfatguy.apng.APngEncoder; +import com.mebigfatguy.encoders.APngEncoder; +import com.mebigfatguy.encoders.MngEncoder; import com.mebigfatguy.patchanim.AnimationType; import com.mebigfatguy.patchanim.ExportType; import com.mebigfatguy.patchanim.OutOfBoundsColor; @@ -44,6 +45,7 @@ private File loc; private AnimatedGifEncoder agEncoder; private APngEncoder apngEncoder; + private MngEncoder mngEncoder; private int totalImages; private Set<ExportListener> elisteners = new HashSet<ExportListener>(); @@ -54,8 +56,8 @@ agEncoder = new AnimatedGifEncoder(); else if (type == ExportType.AnimatedPng) apngEncoder = new APngEncoder(); - else - agEncoder = null; + else if (type == ExportType.AnimatedMng) + mngEncoder = new MngEncoder(); } public void addExportListener(ExportListener el) { @@ -76,6 +78,8 @@ agEncoder.start(new File(loc, baseName).getPath()); else if (type == ExportType.AnimatedPng) apngEncoder.start(new File(loc, baseName).getPath()); + else if (type == ExportType.AnimatedMng) + mngEncoder.start(new File(loc, baseName).getPath()); } totalImages = calcImageCount(document); @@ -93,6 +97,9 @@ } else if (type == ExportType.AnimatedPng) { apngEncoder.setRepeat(atype != AnimationType.None); apngEncoder.setNumFrames(totalImages); + } else if (type == ExportType.AnimatedMng) { + mngEncoder.setRepeat(atype != AnimationType.None); + mngEncoder.setNumFrames(totalImages); } if (lastPatch == 0) { @@ -134,6 +141,8 @@ agEncoder.finish(); } else if (type == ExportType.AnimatedPng) { apngEncoder.finish(); + } else if (type == ExportType.AnimatedMng) { + mngEncoder.finish(); } } } @@ -157,6 +166,9 @@ } else if (type == ExportType.AnimatedPng) { apngEncoder.setDelay(100); apngEncoder.addFrame(image); + } else if (type == ExportType.AnimatedMng) { + mngEncoder.setDelay(100); + mngEncoder.addFrame(image); } else ImageIO.write(image, type.getExtension(), imageFile); Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/main/PatchAnimBundle.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/main/PatchAnimBundle.java 2008-02-10 17:26:23 UTC (rev 148) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/main/PatchAnimBundle.java 2008-02-10 17:34:27 UTC (rev 149) @@ -40,8 +40,8 @@ public static final String ANIMATEDGIFFILTER = "patchanim.filter.animatedgif"; public static final String ANIMATEDPNG = "patchanim.apng"; public static final String ANIMATEDPNGFILTER = "patchanim.filter.apng"; - public static final String MPEG = "patchanim.mpeg"; - public static final String MPEGFILTER = "patchanim.filter.mpeg"; + public static final String ANIMATEDMNG = "patchanim.mng"; + public static final String ANIMATEDMNGFILTER = "patchanim.filter.mng"; public static final String EXPORTINGFILE = "patchanim.exportfile"; public static final String QUIT = "patchanim.quit"; public static final String CONTROLS = "patchanim.control"; Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/resources.properties =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/resources.properties 2008-02-10 17:26:23 UTC (rev 148) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/resources.properties 2008-02-10 17:34:27 UTC (rev 149) @@ -33,8 +33,8 @@ patchanim.filter.animatedgif = GIF Files (*.gif) patchanim.apng = an Animated PNG patchanim.filter.apng = (PNG Files (*.png) -patchanim.mpeg = an MPEG -patchanim.filter.mpeg = MPEG Files (*.mpg) +patchanim.mng = an Animated MNG +patchanim.filter.mng = (MNG Files (*.mng) patchanim.exportfile = Exporting Animation patchanim.quit = Quit patchanim.control = Controls This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dbr...@us...> - 2008-02-10 18:15:08
|
Revision: 150 http://patchanim.svn.sourceforge.net/patchanim/?rev=150&view=rev Author: dbrosius Date: 2008-02-10 10:15:14 -0800 (Sun, 10 Feb 2008) Log Message: ----------- flush out MNG exporting Modified Paths: -------------- trunk/patchanim/src/com/mebigfatguy/encoders/Chunk.java trunk/patchanim/src/com/mebigfatguy/encoders/MngEncoder.java trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java Modified: trunk/patchanim/src/com/mebigfatguy/encoders/Chunk.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/encoders/Chunk.java 2008-02-10 17:34:27 UTC (rev 149) +++ trunk/patchanim/src/com/mebigfatguy/encoders/Chunk.java 2008-02-10 18:15:14 UTC (rev 150) @@ -55,6 +55,10 @@ data[offset] = (byte)(value & 0x00FF); } + public void injectByte(int offset, int value) { + data[offset] = (byte)(value & 0x00FF); + } + public void calcCRC() { CRC32 crc32 = new CRC32(); byte[] typeBytes = new byte[4]; Modified: trunk/patchanim/src/com/mebigfatguy/encoders/MngEncoder.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/encoders/MngEncoder.java 2008-02-10 17:34:27 UTC (rev 149) +++ trunk/patchanim/src/com/mebigfatguy/encoders/MngEncoder.java 2008-02-10 18:15:14 UTC (rev 150) @@ -39,8 +39,13 @@ private static final int IHDR = 0x49484452; private static final int IDAT = 0x49444154; private static final int IEND = 0x49454E44; - private static final int MHDR = 0; - private static final int MEND = 0; + private static final int MHDR = 0x4D484452; + private static final int DEFI = 0x44454649; + private static final int SAVE = 0x53415645; + private static final int TERM = 0x5445524D; + private static final int SEEK = 0x5345454B; + private static final int SHOW = 0x53484F59; + private static final int MEND = 0x4D454E44; private DataOutputStream out = null; private boolean started = false; @@ -50,7 +55,6 @@ private int delay = 100; private int frameCount = 1; private int seqNum = 0; - private boolean processedFirstFrame = false; public void setDelay(int ms) { delay = ms; @@ -94,6 +98,26 @@ if (!started) return false; try { + Chunk saveChunk = new Chunk(0, SAVE); + saveChunk.calcCRC(); + saveChunk.write(out); + + Chunk termChunk = new Chunk(10, TERM); + termChunk.injectShort(0, 0); + termChunk.injectInt(2, 0); + termChunk.injectInt(6, repeatInfinite ? 0x7FFFFFFF : 0); + + termChunk.calcCRC(); + termChunk.write(out); + + Chunk seekChunk = new Chunk(0, SEEK); + seekChunk.calcCRC(); + seekChunk.write(out); + + Chunk showChunk = new Chunk(0, SHOW); + showChunk.calcCRC(); + showChunk.write(out); + Chunk iendChunk = new Chunk(0, MEND); iendChunk.calcCRC(); iendChunk.write(out); @@ -126,18 +150,34 @@ case IHDR: if (!headerWritten) { Chunk mhdrChunk = new Chunk(28, MHDR); + mhdrChunk.injectInt(0, im.getWidth()); + mhdrChunk.injectInt(4, im.getHeight()); + mhdrChunk.injectInt(8, delay); + mhdrChunk.injectInt(12, 0); + mhdrChunk.injectInt(16, frameCount); + mhdrChunk.injectInt(20, frameCount); + mhdrChunk.injectInt(24, 583); mhdrChunk.calcCRC(); mhdrChunk.write(out); + headerWritten = true; } + Chunk defiChunk = new Chunk(4, DEFI); + defiChunk.injectInt(0, (seqNum++) << 16); + defiChunk.calcCRC(); + defiChunk.write(out); + chunk.write(out); break; case IDAT: + chunk.write(out); break; + + case IEND: + chunk.write(out); + break; } chunk = pStrm.readNextChunk(); } - processedFirstFrame = true; - return true; } catch (IOException ioe) { return false; Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java 2008-02-10 17:34:27 UTC (rev 149) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/gui/JPatchAnimFrame.java 2008-02-10 18:15:14 UTC (rev 150) @@ -110,7 +110,6 @@ exportAnimatedGifItem = new JMenuItem(rb.getString(PatchAnimBundle.ANIMATEDGIF)); exportAnimatedPngItem = new JMenuItem(rb.getString(PatchAnimBundle.ANIMATEDPNG)); exportAnimatedMngItem = new JMenuItem(rb.getString(PatchAnimBundle.ANIMATEDMNG)); - exportAnimatedMngItem.setEnabled(false); exportMenu.add(exportJpgsItem); exportMenu.add(exportPngsItem); exportMenu.add(exportGifsItem); Modified: trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java =================================================================== --- trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java 2008-02-10 17:34:27 UTC (rev 149) +++ trunk/patchanim/src/com/mebigfatguy/patchanim/io/PatchExporter.java 2008-02-10 18:15:14 UTC (rev 150) @@ -100,6 +100,7 @@ } else if (type == ExportType.AnimatedMng) { mngEncoder.setRepeat(atype != AnimationType.None); mngEncoder.setNumFrames(totalImages); + mngEncoder.setDelay(100); } if (lastPatch == 0) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dbr...@us...> - 2008-02-12 04:55:33
|
Revision: 171 http://patchanim.svn.sourceforge.net/patchanim/?rev=171&view=rev Author: dbrosius Date: 2008-02-11 20:55:36 -0800 (Mon, 11 Feb 2008) Log Message: ----------- move encoders under patchanim Added Paths: ----------- trunk/patchanim/src/com/mebigfatguy/patchanim/encoders/ Removed Paths: ------------- trunk/patchanim/src/com/mebigfatguy/encoders/ Copied: trunk/patchanim/src/com/mebigfatguy/patchanim/encoders (from rev 170, trunk/patchanim/src/com/mebigfatguy/encoders) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |