📄 bmpimagewriter.java
字号:
stream.writeByte(01); int r = nextVal2 << 4 | 0; stream.writeByte(r); incCompImageSize(2); runCount = -1;/// Only EOF required now } } } else{ // Check for existing run if (runCount > 2){ pixel = ( runVal1 << 4) | runVal2; stream.writeByte(runCount); stream.writeByte(pixel); incCompImageSize(2); } else if (absVal < 0){ // first time absBuf[++absVal] = runVal1; absBuf[++absVal] = runVal2; absBuf[++absVal] = nextVal1; absBuf[++absVal] = nextVal2; } else if (absVal < 253){ // only 255 elements absBuf[++absVal] = nextVal1; absBuf[++absVal] = nextVal2; } else { stream.writeByte(0); stream.writeByte(absVal+1); incCompImageSize(2); for(int a=0; a<absVal;a+=2){ pixel = (absBuf[a] << 4) | absBuf[a+1]; stream.writeByte((byte)pixel); incCompImageSize(1); } // Padding for word align // since it will fit into 127 bytes stream.writeByte(0); incCompImageSize(1); absVal = -1; } runVal1 = nextVal1; runVal2 = nextVal2; runCount = 2; } // Handle the End of scanline for the last 2 4bits if (j >= scanlineBytes-2 ) { if (absVal == -1 && runCount >= 2){ if (j == scanlineBytes-2){ if(bipixels[++j] == runVal1){ runCount++; pixel = ( runVal1 << 4) | runVal2; stream.writeByte(runCount); stream.writeByte(pixel); incCompImageSize(2); } else { pixel = ( runVal1 << 4) | runVal2; stream.writeByte(runCount); stream.writeByte(pixel); stream.writeByte(01); pixel = bipixels[j]<<4 |0; stream.writeByte(pixel); int n = bipixels[j]<<4|0; incCompImageSize(4); } } else { stream.writeByte(runCount); pixel =( runVal1 << 4) | runVal2 ; stream.writeByte(pixel); incCompImageSize(2); } } else if(absVal > -1){ if (j == scanlineBytes-2){ absBuf[++absVal] = bipixels[++j]; } if (absVal >=2){ stream.writeByte(0); stream.writeByte(absVal+1); incCompImageSize(2); for(int a=0; a<absVal;a+=2){ pixel = (absBuf[a] << 4) | absBuf[a+1]; stream.writeByte((byte)pixel); incCompImageSize(1); } if(!(isEven(absVal+1))){ q = absBuf[absVal] << 4|0; stream.writeByte(q); incCompImageSize(1); } // Padding if ( !isEven((int)Math.ceil((absVal+1)/2)) ) { stream.writeByte(0); incCompImageSize(1); } } else { switch (absVal){ case 0: stream.writeByte(1); int n = absBuf[0]<<4 | 0; stream.writeByte(n); incCompImageSize(2); break; case 1: stream.writeByte(2); pixel = (absBuf[0] << 4) | absBuf[1]; stream.writeByte(pixel); incCompImageSize(2); break; } } } stream.writeByte(0); stream.writeByte(0); incCompImageSize(2); } } } private synchronized void incCompImageSize(int value){ compImageSize = compImageSize + value; } private boolean isEven(int number) { return (number%2 == 0 ? true : false); } private void writeFileHeader(int fileSize, int offset) throws IOException { // magic value stream.writeByte('B'); stream.writeByte('M'); // File size stream.writeInt(fileSize); // reserved1 and reserved2 stream.writeInt(0); // offset to image data stream.writeInt(offset); } private void writeInfoHeader(int headerSize, int bitsPerPixel) throws IOException { // size of header stream.writeInt(headerSize); // width stream.writeInt(w); // height stream.writeInt(h); // number of planes stream.writeShort(1); // Bits Per Pixel stream.writeShort(bitsPerPixel); } private void writeSize(int dword, int offset) throws IOException { stream.skipBytes(offset); stream.writeInt(dword); } public void reset() { super.reset(); stream = null; } private int getCompressionType(String typeString) { for (int i = 0; i < BMPConstants.compressionTypeNames.length; i++) if (BMPConstants.compressionTypeNames[i].equals(typeString)) return i; return 0; } private void writeEmbedded(IIOImage image, ImageWriteParam bmpParam) throws IOException { String format = compressionType == BMPConstants.BI_JPEG ? "jpeg" : "png"; Iterator iterator = ImageIO.getImageWritersByFormatName(format); ImageWriter writer = null; if (iterator.hasNext()) writer = (ImageWriter)iterator.next(); if (writer != null) { if (embedded_stream == null) { throw new RuntimeException("No stream for writing embedded image!"); } writer.addIIOWriteProgressListener(new IIOWriteProgressAdapter() { public void imageProgress(ImageWriter source, float percentageDone) { processImageProgress(percentageDone); } }); writer.addIIOWriteWarningListener(new IIOWriteWarningListener() { public void warningOccurred(ImageWriter source, int imageIndex, String warning) { processWarningOccurred(imageIndex, warning); } }); writer.setOutput(ImageIO.createImageOutputStream(embedded_stream)); ImageWriteParam param = writer.getDefaultWriteParam(); //param.setDestinationBands(bmpParam.getDestinationBands()); param.setDestinationOffset(bmpParam.getDestinationOffset()); param.setSourceBands(bmpParam.getSourceBands()); param.setSourceRegion(bmpParam.getSourceRegion()); param.setSourceSubsampling(bmpParam.getSourceXSubsampling(), bmpParam.getSourceYSubsampling(), bmpParam.getSubsamplingXOffset(), bmpParam.getSubsamplingYOffset()); writer.write(null, image, param); } else throw new RuntimeException(I18N.getString("BMPImageWrite5") + " " + format); } private int firstLowBit(int num) { int count = 0; while ((num & 1) == 0) { count++; num >>>= 1; } return count; } private class IIOWriteProgressAdapter implements IIOWriteProgressListener { public void imageComplete(ImageWriter source) { } public void imageProgress(ImageWriter source, float percentageDone) { } public void imageStarted(ImageWriter source, int imageIndex) { } public void thumbnailComplete(ImageWriter source) { } public void thumbnailProgress(ImageWriter source, float percentageDone) { } public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) { } public void writeAborted(ImageWriter source) { } } /* * Returns preferred compression type for given image. * The default compression type is BI_RGB, but some image types can't be * encodeed with using default compression without cahnge color resolution. * For example, TYPE_USHORT_565_RGB may be encodeed only by using BI_BITFIELDS * compression type. * * NB: we probably need to extend this method if we encounter other image * types which can not be encoded with BI_RGB compression type. */ protected int getPreferredCompressionType(ColorModel cm, SampleModel sm) { ImageTypeSpecifier imageType = new ImageTypeSpecifier(cm, sm); return getPreferredCompressionType(imageType); } protected int getPreferredCompressionType(ImageTypeSpecifier imageType) { if (imageType.getBufferedImageType() == BufferedImage.TYPE_USHORT_565_RGB) { return BI_BITFIELDS; } return BI_RGB; } /* * Check whether we can encode image of given type using compression method in question. * * For example, TYPE_USHORT_565_RGB can be encodeed with BI_BITFIELDS compression only. * * NB: method should be extended if other cases when we can not encode * with given compression will be discovered. */ protected boolean canEncodeImage(int compression, ColorModel cm, SampleModel sm) { ImageTypeSpecifier imgType = new ImageTypeSpecifier(cm, sm); return canEncodeImage(compression, imgType); } protected boolean canEncodeImage(int compression, ImageTypeSpecifier imgType) { ImageWriterSpi spi = this.getOriginatingProvider(); if (!spi.canEncodeImage(imgType)) { return false; } int biType = imgType.getBufferedImageType(); int bpp = imgType.getColorModel().getPixelSize(); if (compressionType == BI_RLE4 && bpp != 4) { // only 4bpp images can be encoded as BI_RLE4 return false; } if (compressionType == BI_RLE8 && bpp != 8) { // only 8bpp images can be encoded as BI_RLE8 return false; } if (bpp == 16) { /* * Technically we expect that we may be able to * encode only some of SinglePixelPackedSampleModel * images here. * * In addition we should take into account following: * * 1. BI_RGB case, according to the MSDN description: * * The bitmap has a maximum of 2^16 colors. If the * biCompression member of the BITMAPINFOHEADER is BI_RGB, * the bmiColors member of BITMAPINFO is NULL. Each WORD * in the bitmap array represents a single pixel. The * relative intensities of red, green, and blue are * represented with five bits for each color component. * * 2. BI_BITFIELDS case, according ot the MSDN description: * * Windows 95/98/Me: When the biCompression member is * BI_BITFIELDS, the system supports only the following * 16bpp color masks: A 5-5-5 16-bit image, where the blue * mask is 0x001F, the green mask is 0x03E0, and the red mask * is 0x7C00; and a 5-6-5 16-bit image, where the blue mask * is 0x001F, the green mask is 0x07E0, and the red mask is * 0xF800. */ boolean canUseRGB = false; boolean canUseBITFIELDS = false; SampleModel sm = imgType.getSampleModel(); if (sm instanceof SinglePixelPackedSampleModel) { int[] sizes = ((SinglePixelPackedSampleModel)sm).getSampleSize(); canUseRGB = true; canUseBITFIELDS = true; for (int i = 0; i < sizes.length; i++) { canUseRGB &= (sizes[i] == 5); canUseBITFIELDS &= ((sizes[i] == 5) || (i == 1 && sizes[i] == 6)); } } return (((compressionType == BI_RGB) && canUseRGB) || ((compressionType == BI_BITFIELDS) && canUseBITFIELDS)); } return true; } protected void writeMaskToPalette(int mask, int i, byte[] r, byte[]g, byte[] b, byte[]a) { b[i] = (byte)(0xff & (mask >> 24)); g[i] = (byte)(0xff & (mask >> 16)); r[i] = (byte)(0xff & (mask >> 8)); a[i] = (byte)(0xff & mask); } private int roundBpp(int x) { if (x <= 8) { return 8; } else if (x <= 16) { return 16; } if (x <= 24) { return 24; } else { return 32; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -