📄 gifimagewriter.java
字号:
} if (streamMetadata.colorResolution == GIFMetadata.UNDEFINED_INTEGER_VALUE) { streamMetadata.colorResolution = colorModel != null ? colorModel.getComponentSize()[0] : sampleModel.getSampleSize()[0]; } // Set the Global Color Table if not set, i.e., if not // provided in the stream metadata. if (streamMetadata.globalColorTable == null) { if (isWritingSequence && imageMetadata != null && imageMetadata.localColorTable != null) { // Writing a sequence and a local color table was // provided in the metadata of the first image: use it. streamMetadata.globalColorTable = imageMetadata.localColorTable; } else if (imageMetadata == null || imageMetadata.localColorTable == null) { // Create a color table. streamMetadata.globalColorTable = createColorTable(colorModel, sampleModel); } } // Set the Global Color Table. At this point it should be // A) the global color table provided in stream metadata, if any; // B) the local color table of the image metadata, if any, if // writing a sequence; // C) a table created on the basis of the first image ColorModel // and SampleModel if no local color table is available; or // D) null if none of the foregoing conditions obtain (which // should only be if a sequence is not being written and // a local color table is provided in image metadata). globalColorTable = streamMetadata.globalColorTable; // Write the header. int bitsPerPixel; if (globalColorTable != null) { bitsPerPixel = getNumBits(globalColorTable.length/3); } else if (imageMetadata != null && imageMetadata.localColorTable != null) { bitsPerPixel = getNumBits(imageMetadata.localColorTable.length/3); } else { bitsPerPixel = sampleModel.getSampleSize(0); } writeHeader(streamMetadata, bitsPerPixel); } else if (isWritingSequence) { globalColorTable = theStreamMetadata.globalColorTable; } else { throw new IllegalArgumentException("Must write header for single image!"); } // Write extension blocks, Image Descriptor, and image data. writeImage(iioimage.getRenderedImage(), imageMetadata, p, globalColorTable, sourceBounds, destSize); // Write the trailer. if (writeTrailer) { writeTrailer(); } } /** * Writes any extension blocks, the Image Descriptor, and the image data * * @param iioimage The image and image metadata. * @param param The write parameters. * @param globalColorTable The Global Color Table. * @param sourceBounds The source region. * @param destSize The destination dimensions. */ private void writeImage(RenderedImage image, GIFWritableImageMetadata imageMetadata, ImageWriteParam param, byte[] globalColorTable, Rectangle sourceBounds, Dimension destSize) throws IOException { ColorModel colorModel = image.getColorModel(); SampleModel sampleModel = image.getSampleModel(); boolean writeGraphicsControlExtension; if (imageMetadata == null) { // Create default metadata. imageMetadata = (GIFWritableImageMetadata)getDefaultImageMetadata( new ImageTypeSpecifier(image), param); // Set GraphicControlExtension flag only if there is // transparency. writeGraphicsControlExtension = imageMetadata.transparentColorFlag; } else { // Check for GraphicControlExtension element. NodeList list = null; try { IIOMetadataNode root = (IIOMetadataNode) imageMetadata.getAsTree(IMAGE_METADATA_NAME); list = root.getElementsByTagName("GraphicControlExtension"); } catch(IllegalArgumentException iae) { // Should never happen. } // Set GraphicControlExtension flag if element present. writeGraphicsControlExtension = list != null && list.getLength() > 0; // If progressive mode is not MODE_COPY_FROM_METADATA, ensure // the interlacing is set per the ImageWriteParam mode setting. if (param != null && param.canWriteProgressive()) { if (param.getProgressiveMode() == ImageWriteParam.MODE_DISABLED) { imageMetadata.interlaceFlag = false; } else if (param.getProgressiveMode() == ImageWriteParam.MODE_DEFAULT) { imageMetadata.interlaceFlag = true; } } } // Unset local color table if equal to global color table. if (Arrays.equals(globalColorTable, imageMetadata.localColorTable)) { imageMetadata.localColorTable = null; } // Override dimensions imageMetadata.imageWidth = destSize.width; imageMetadata.imageHeight = destSize.height; // Write Graphics Control Extension. if (writeGraphicsControlExtension) { writeGraphicControlExtension(imageMetadata); } // Write extension blocks. writePlainTextExtension(imageMetadata); writeApplicationExtension(imageMetadata); writeCommentExtension(imageMetadata); // Write Image Descriptor int bitsPerPixel = getNumBits(imageMetadata.localColorTable == null ? (globalColorTable == null ? sampleModel.getSampleSize(0) : globalColorTable.length/3) : imageMetadata.localColorTable.length/3); writeImageDescriptor(imageMetadata, bitsPerPixel); // Write image data writeRasterData(image, sourceBounds, destSize, param, imageMetadata.interlaceFlag); } private void writeRows(RenderedImage image, LZWCompressor compressor, int sx, int sdx, int sy, int sdy, int sw, int dy, int ddy, int dw, int dh, int numRowsWritten, int progressReportRowPeriod) throws IOException { if (DEBUG) System.out.println("Writing unoptimized"); int[] sbuf = new int[sw]; byte[] dbuf = new byte[dw]; Raster raster = image.getNumXTiles() == 1 && image.getNumYTiles() == 1 ? image.getTile(0, 0) : image.getData(); for (int y = dy; y < dh; y += ddy) { if (numRowsWritten % progressReportRowPeriod == 0) { if (abortRequested()) { processWriteAborted(); return; } processImageProgress((numRowsWritten*100.0F)/dh); } raster.getSamples(sx, sy, sw, 1, 0, sbuf); for (int i = 0, j = 0; i < dw; i++, j += sdx) { dbuf[i] = (byte)sbuf[j]; } compressor.compress(dbuf, 0, dw); numRowsWritten++; sy += sdy; } } private void writeRowsOpt(byte[] data, int offset, int lineStride, LZWCompressor compressor, int dy, int ddy, int dw, int dh, int numRowsWritten, int progressReportRowPeriod) throws IOException { if (DEBUG) System.out.println("Writing optimized"); offset += dy*lineStride; lineStride *= ddy; for (int y = dy; y < dh; y += ddy) { if (numRowsWritten % progressReportRowPeriod == 0) { if (abortRequested()) { processWriteAborted(); return; } processImageProgress((numRowsWritten*100.0F)/dh); } compressor.compress(data, offset, dw); numRowsWritten++; offset += lineStride; } } private void writeRasterData(RenderedImage image, Rectangle sourceBounds, Dimension destSize, ImageWriteParam param, boolean interlaceFlag) throws IOException { int sourceXOffset = sourceBounds.x; int sourceYOffset = sourceBounds.y; int sourceWidth = sourceBounds.width; int sourceHeight = sourceBounds.height; int destWidth = destSize.width; int destHeight = destSize.height; int periodX; int periodY; if (param == null) { periodX = 1; periodY = 1; } else { periodX = param.getSourceXSubsampling(); periodY = param.getSourceYSubsampling(); } SampleModel sampleModel = image.getSampleModel(); int bitsPerPixel = sampleModel.getSampleSize()[0]; int initCodeSize = bitsPerPixel; if (initCodeSize == 1) { initCodeSize++; } stream.write(initCodeSize); LZWCompressor compressor = new LZWCompressor(stream, initCodeSize, false); boolean isOptimizedCase = periodX == 1 && periodY == 1 && sampleModel instanceof ComponentSampleModel && image.getNumXTiles() == 1 && image.getNumYTiles() == 1 && image.getTile(0, 0).getDataBuffer() instanceof DataBufferByte; int numRowsWritten = 0; int progressReportRowPeriod = Math.max(destHeight/20, 1); processImageStarted(imageIndex); if (interlaceFlag) { if (DEBUG) System.out.println("Writing interlaced"); if (isOptimizedCase) { Raster tile = image.getTile(0, 0); byte[] data = ((DataBufferByte)tile.getDataBuffer()).getData(); ComponentSampleModel csm = (ComponentSampleModel)tile.getSampleModel(); int offset = csm.getOffset(sourceXOffset, sourceYOffset, 0); int lineStride = csm.getScanlineStride(); writeRowsOpt(data, offset, lineStride, compressor, 0, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += destHeight/8; writeRowsOpt(data, offset, lineStride, compressor, 4, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 4)/8; writeRowsOpt(data, offset, lineStride, compressor, 2, 4, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += (destHeight - 2)/4; writeRowsOpt(data, offset, lineStride, compressor, 1, 2, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); } else { writeRows(image, compressor, sourceXOffset, periodX, sourceYOffset, 8*periodY, sourceWidth, 0, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) { return; } numRowsWritten += destHeight/8; writeRows(image, compressor, sourceXOffset, periodX, sourceYOffset + 4*periodY, 8*periodY, sourceWidth, 4, 8, destWidth, destHeight, numRowsWritten, progressReportRowPeriod); if (abortRequested()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -