1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| public class GifFrame { public static final String NONE = "none"; public static final String DO_NOT_DISPOSE = "doNotDispose"; public static final String RESTORE_TO_BGCOLOR = "restoreToBackgroundColor"; public static final String RESTORE_TO_PREVIOUS = "restoreToPrevious";
public final BufferedImage img; public final long delay; public final String disposalMethod;
public GifFrame(BufferedImage img, long delay) { this(img, delay, NONE); }
public GifFrame(BufferedImage img, long delay, String disposalMethod) { this.img = img; this.delay = delay; this.disposalMethod = disposalMethod; } }
public class ImageUtil { public static BufferedImage convertRGBAToGIF(BufferedImage src, int transColor) { BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_BYTE_INDEXED); Graphics g = dst.getGraphics(); g.setColor(new Color(transColor)); g.fillRect(0, 0, dst.getWidth(), dst.getHeight()); { IndexColorModel indexedModel = (IndexColorModel) dst.getColorModel(); WritableRaster raster = dst.getRaster(); int sample = raster.getSample(0, 0, 0); int size = indexedModel.getMapSize(); byte[] rr = new byte[size]; byte[] gg = new byte[size]; byte[] bb = new byte[size]; indexedModel.getReds(rr); indexedModel.getGreens(gg); indexedModel.getBlues(bb); IndexColorModel newModel = new IndexColorModel(8, size, rr, gg, bb, sample); dst = new BufferedImage(newModel, raster, dst.isAlphaPremultiplied(), null); } dst.createGraphics().drawImage(src, 0, 0, null); return dst; }
public static void saveAnimatedGIF(OutputStream out, List<GifFrame> frames, int loopCount) throws Exception { ImageWriter iw = ImageIO.getImageWritersByFormatName("gif").next();
ImageOutputStream ios = ImageIO.createImageOutputStream(out); iw.setOutput(ios); iw.prepareWriteSequence(null);
int p = 0; for (GifFrame frame : frames) { ImageWriteParam iwp = iw.getDefaultWriteParam(); IIOMetadata metadata = iw.getDefaultImageMetadata(new ImageTypeSpecifier(frame.img), iwp); ImageUtil.configureGIFFrame(metadata, String.valueOf(frame.delay / 10L), p++, frame.disposalMethod, loopCount); IIOImage ii = new IIOImage(frame.img, null, metadata); iw.writeToSequence(ii, null); }
iw.endWriteSequence(); ios.close(); }
private static void configureGIFFrame(IIOMetadata meta, String delayTime, int imageIndex, String disposalMethod, int loopCount) { String metaFormat = meta.getNativeMetadataFormatName();
if (!"javax_imageio_gif_image_1.0".equals(metaFormat)) { throw new IllegalArgumentException("Unfamiliar gif metadata format: " + metaFormat); }
Node root = meta.getAsTree(metaFormat);
Node child = root.getFirstChild(); while (child != null) { if ("GraphicControlExtension".equals(child.getNodeName())) break; child = child.getNextSibling(); }
IIOMetadataNode gce = (IIOMetadataNode) child; gce.setAttribute("userDelay", "FALSE"); gce.setAttribute("delayTime", delayTime); gce.setAttribute("disposalMethod", disposalMethod);
if (imageIndex == 0) { IIOMetadataNode aes = new IIOMetadataNode("ApplicationExtensions"); IIOMetadataNode ae = new IIOMetadataNode("ApplicationExtension"); ae.setAttribute("applicationID", "NETSCAPE"); ae.setAttribute("authenticationCode", "2.0"); byte[] uo = new byte[] { 0x1, (byte) (loopCount & 0xFF), (byte) ((loopCount >> 8) & 0xFF) }; ae.setUserObject(uo); aes.appendChild(ae); root.appendChild(aes); }
try { meta.setFromTree(metaFormat, root); } catch (IIOInvalidTreeException e) { throw new Error(e); } } } |