78 private ImageOutputStream stream = null;
79 private ByteArrayOutputStream embedded_stream = null;
80 private int version;
81 private int compressionType;
82 private boolean isTopDown;
83 private int w, h;
84 private int compImageSize = 0;
85 private int[] bitMasks;
86 private int[] bitPos;
87 private byte[] bpixels;
88 private short[] spixels;
89 private int[] ipixels;
90
91 /** Constructs {@code BMPImageWriter} based on the provided
92 * {@code ImageWriterSpi}.
93 */
94 public BMPImageWriter(ImageWriterSpi originator) {
95 super(originator);
96 }
97
98 public void setOutput(Object output) {
99 super.setOutput(output); // validates output
100 if (output != null) {
101 if (!(output instanceof ImageOutputStream))
102 throw new IllegalArgumentException(I18N.getString("BMPImageWriter0"));
103 this.stream = (ImageOutputStream)output;
104 stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
105 } else
106 this.stream = null;
107 }
108
109 public ImageWriteParam getDefaultWriteParam() {
110 return new BMPImageWriteParam();
111 }
112
113 public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
114 return null;
115 }
116
117 public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
118 ImageWriteParam param) {
119 BMPMetadata meta = new BMPMetadata();
120 meta.bmpVersion = VERSION_3;
121 meta.compression = getPreferredCompressionType(imageType);
122 if (param != null
123 && param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) {
124 meta.compression = BMPCompressionTypes.getType(param.getCompressionType());
125 }
126 meta.bitsPerPixel = (short)imageType.getColorModel().getPixelSize();
127 return meta;
128 }
129
130 public IIOMetadata convertStreamMetadata(IIOMetadata inData,
131 ImageWriteParam param) {
132 return null;
133 }
134
135 public IIOMetadata convertImageMetadata(IIOMetadata metadata,
136 ImageTypeSpecifier type,
137 ImageWriteParam param) {
138 return null;
139 }
140
141 public boolean canWriteRasters() {
142 return true;
143 }
144
145 public void write(IIOMetadata streamMetadata,
146 IIOImage image,
147 ImageWriteParam param) throws IOException {
148
149 if (stream == null) {
150 throw new IllegalStateException(I18N.getString("BMPImageWriter7"));
151 }
152
153 if (image == null) {
154 throw new IllegalArgumentException(I18N.getString("BMPImageWriter8"));
155 }
156
157 clearAbortRequest();
158 processImageStarted(0);
159 if (abortRequested()) {
160 processWriteAborted();
161 return;
162 }
163 if (param == null)
164 param = getDefaultWriteParam();
1299 stream.writeInt(headerSize);
1300
1301 // width
1302 stream.writeInt(w);
1303
1304 // height
1305 stream.writeInt(isTopDown ? -h : h);
1306
1307 // number of planes
1308 stream.writeShort(1);
1309
1310 // Bits Per Pixel
1311 stream.writeShort(bitsPerPixel);
1312 }
1313
1314 private void writeSize(int dword, int offset) throws IOException {
1315 stream.skipBytes(offset);
1316 stream.writeInt(dword);
1317 }
1318
1319 public void reset() {
1320 super.reset();
1321 stream = null;
1322 }
1323
1324 private void writeEmbedded(IIOImage image,
1325 ImageWriteParam bmpParam) throws IOException {
1326 String format =
1327 compressionType == BI_JPEG ? "jpeg" : "png";
1328 Iterator<ImageWriter> iterator =
1329 ImageIO.getImageWritersByFormatName(format);
1330 ImageWriter writer = null;
1331 if (iterator.hasNext())
1332 writer = iterator.next();
1333 if (writer != null) {
1334 if (embedded_stream == null) {
1335 throw new RuntimeException("No stream for writing embedded image!");
1336 }
1337
1338 writer.addIIOWriteProgressListener(new IIOWriteProgressAdapter() {
1357 bmpParam.getSourceYSubsampling(),
1358 bmpParam.getSubsamplingXOffset(),
1359 bmpParam.getSubsamplingYOffset());
1360 writer.write(null, image, param);
1361 } else
1362 throw new RuntimeException(I18N.getString("BMPImageWrite5") + " " + format);
1363
1364 }
1365
1366 private int firstLowBit(int num) {
1367 int count = 0;
1368 while ((num & 1) == 0) {
1369 count++;
1370 num >>>= 1;
1371 }
1372 return count;
1373 }
1374
1375 private class IIOWriteProgressAdapter implements IIOWriteProgressListener {
1376
1377 public void imageComplete(ImageWriter source) {
1378 }
1379
1380 public void imageProgress(ImageWriter source, float percentageDone) {
1381 }
1382
1383 public void imageStarted(ImageWriter source, int imageIndex) {
1384 }
1385
1386 public void thumbnailComplete(ImageWriter source) {
1387 }
1388
1389 public void thumbnailProgress(ImageWriter source, float percentageDone) {
1390 }
1391
1392 public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) {
1393 }
1394
1395 public void writeAborted(ImageWriter source) {
1396 }
1397 }
1398
1399 /*
1400 * Returns preferred compression type for given image.
1401 * The default compression type is BI_RGB, but some image types can't be
1402 * encodeed with using default compression without cahnge color resolution.
1403 * For example, TYPE_USHORT_565_RGB may be encodeed only by using BI_BITFIELDS
1404 * compression type.
1405 *
1406 * NB: we probably need to extend this method if we encounter other image
1407 * types which can not be encoded with BI_RGB compression type.
1408 */
1409 protected int getPreferredCompressionType(ColorModel cm, SampleModel sm) {
1410 ImageTypeSpecifier imageType = new ImageTypeSpecifier(cm, sm);
1411 return getPreferredCompressionType(imageType);
1412 }
1413
1414 protected int getPreferredCompressionType(ImageTypeSpecifier imageType) {
|
78 private ImageOutputStream stream = null;
79 private ByteArrayOutputStream embedded_stream = null;
80 private int version;
81 private int compressionType;
82 private boolean isTopDown;
83 private int w, h;
84 private int compImageSize = 0;
85 private int[] bitMasks;
86 private int[] bitPos;
87 private byte[] bpixels;
88 private short[] spixels;
89 private int[] ipixels;
90
91 /** Constructs {@code BMPImageWriter} based on the provided
92 * {@code ImageWriterSpi}.
93 */
94 public BMPImageWriter(ImageWriterSpi originator) {
95 super(originator);
96 }
97
98 @Override
99 public void setOutput(Object output) {
100 super.setOutput(output); // validates output
101 if (output != null) {
102 if (!(output instanceof ImageOutputStream))
103 throw new IllegalArgumentException(I18N.getString("BMPImageWriter0"));
104 this.stream = (ImageOutputStream)output;
105 stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
106 } else
107 this.stream = null;
108 }
109
110 @Override
111 public ImageWriteParam getDefaultWriteParam() {
112 return new BMPImageWriteParam();
113 }
114
115 @Override
116 public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
117 return null;
118 }
119
120 @Override
121 public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
122 ImageWriteParam param) {
123 BMPMetadata meta = new BMPMetadata();
124 meta.bmpVersion = VERSION_3;
125 meta.compression = getPreferredCompressionType(imageType);
126 if (param != null
127 && param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) {
128 meta.compression = BMPCompressionTypes.getType(param.getCompressionType());
129 }
130 meta.bitsPerPixel = (short)imageType.getColorModel().getPixelSize();
131 return meta;
132 }
133
134 @Override
135 public IIOMetadata convertStreamMetadata(IIOMetadata inData,
136 ImageWriteParam param) {
137 return null;
138 }
139
140 @Override
141 public IIOMetadata convertImageMetadata(IIOMetadata metadata,
142 ImageTypeSpecifier type,
143 ImageWriteParam param) {
144 return null;
145 }
146
147 @Override
148 public boolean canWriteRasters() {
149 return true;
150 }
151
152 @Override
153 public void write(IIOMetadata streamMetadata,
154 IIOImage image,
155 ImageWriteParam param) throws IOException {
156
157 if (stream == null) {
158 throw new IllegalStateException(I18N.getString("BMPImageWriter7"));
159 }
160
161 if (image == null) {
162 throw new IllegalArgumentException(I18N.getString("BMPImageWriter8"));
163 }
164
165 clearAbortRequest();
166 processImageStarted(0);
167 if (abortRequested()) {
168 processWriteAborted();
169 return;
170 }
171 if (param == null)
172 param = getDefaultWriteParam();
1307 stream.writeInt(headerSize);
1308
1309 // width
1310 stream.writeInt(w);
1311
1312 // height
1313 stream.writeInt(isTopDown ? -h : h);
1314
1315 // number of planes
1316 stream.writeShort(1);
1317
1318 // Bits Per Pixel
1319 stream.writeShort(bitsPerPixel);
1320 }
1321
1322 private void writeSize(int dword, int offset) throws IOException {
1323 stream.skipBytes(offset);
1324 stream.writeInt(dword);
1325 }
1326
1327 @Override
1328 public void reset() {
1329 super.reset();
1330 stream = null;
1331 }
1332
1333 private void writeEmbedded(IIOImage image,
1334 ImageWriteParam bmpParam) throws IOException {
1335 String format =
1336 compressionType == BI_JPEG ? "jpeg" : "png";
1337 Iterator<ImageWriter> iterator =
1338 ImageIO.getImageWritersByFormatName(format);
1339 ImageWriter writer = null;
1340 if (iterator.hasNext())
1341 writer = iterator.next();
1342 if (writer != null) {
1343 if (embedded_stream == null) {
1344 throw new RuntimeException("No stream for writing embedded image!");
1345 }
1346
1347 writer.addIIOWriteProgressListener(new IIOWriteProgressAdapter() {
1366 bmpParam.getSourceYSubsampling(),
1367 bmpParam.getSubsamplingXOffset(),
1368 bmpParam.getSubsamplingYOffset());
1369 writer.write(null, image, param);
1370 } else
1371 throw new RuntimeException(I18N.getString("BMPImageWrite5") + " " + format);
1372
1373 }
1374
1375 private int firstLowBit(int num) {
1376 int count = 0;
1377 while ((num & 1) == 0) {
1378 count++;
1379 num >>>= 1;
1380 }
1381 return count;
1382 }
1383
1384 private class IIOWriteProgressAdapter implements IIOWriteProgressListener {
1385
1386 @Override
1387 public void imageComplete(ImageWriter source) {
1388 }
1389
1390 @Override
1391 public void imageProgress(ImageWriter source, float percentageDone) {
1392 }
1393
1394 @Override
1395 public void imageStarted(ImageWriter source, int imageIndex) {
1396 }
1397
1398 @Override
1399 public void thumbnailComplete(ImageWriter source) {
1400 }
1401
1402 @Override
1403 public void thumbnailProgress(ImageWriter source, float percentageDone) {
1404 }
1405
1406 @Override
1407 public void thumbnailStarted(ImageWriter source, int imageIndex, int thumbnailIndex) {
1408 }
1409
1410 @Override
1411 public void writeAborted(ImageWriter source) {
1412 }
1413 }
1414
1415 /*
1416 * Returns preferred compression type for given image.
1417 * The default compression type is BI_RGB, but some image types can't be
1418 * encodeed with using default compression without cahnge color resolution.
1419 * For example, TYPE_USHORT_565_RGB may be encodeed only by using BI_BITFIELDS
1420 * compression type.
1421 *
1422 * NB: we probably need to extend this method if we encounter other image
1423 * types which can not be encoded with BI_RGB compression type.
1424 */
1425 protected int getPreferredCompressionType(ColorModel cm, SampleModel sm) {
1426 ImageTypeSpecifier imageType = new ImageTypeSpecifier(cm, sm);
1427 return getPreferredCompressionType(imageType);
1428 }
1429
1430 protected int getPreferredCompressionType(ImageTypeSpecifier imageType) {
|