250 return 2;
251 }
252 x = x - 1;
253 x = x | (x >> 1);
254 x = x | (x >> 2);
255 x = x | (x >> 4);
256 x = x | (x >> 8);
257 x = x | (x >> 16);
258 return x + 1;
259 }
260
261
262
263 public GIFImageWriter(GIFImageWriterSpi originatingProvider) {
264 super(originatingProvider);
265 if (DEBUG) {
266 System.err.println("GIF Writer is created");
267 }
268 }
269
270 public boolean canWriteSequence() {
271 return true;
272 }
273
274 /**
275 * Merges {@code inData} into {@code outData}. The supplied
276 * metadata format name is attempted first and failing that the standard
277 * metadata format name is attempted.
278 */
279 private void convertMetadata(String metadataFormatName,
280 IIOMetadata inData,
281 IIOMetadata outData) {
282 String formatName = null;
283
284 String nativeFormatName = inData.getNativeMetadataFormatName();
285 if (nativeFormatName != null &&
286 nativeFormatName.equals(metadataFormatName)) {
287 formatName = metadataFormatName;
288 } else {
289 String[] extraFormatNames = inData.getExtraMetadataFormatNames();
300
301 if (formatName == null &&
302 inData.isStandardMetadataFormatSupported()) {
303 formatName = STANDARD_METADATA_NAME;
304 }
305
306 if (formatName != null) {
307 try {
308 Node root = inData.getAsTree(formatName);
309 outData.mergeTree(formatName, root);
310 } catch(IIOInvalidTreeException e) {
311 // ignore
312 }
313 }
314 }
315
316 /**
317 * Creates a default stream metadata object and merges in the
318 * supplied metadata.
319 */
320 public IIOMetadata convertStreamMetadata(IIOMetadata inData,
321 ImageWriteParam param) {
322 if (inData == null) {
323 throw new IllegalArgumentException("inData == null!");
324 }
325
326 IIOMetadata sm = getDefaultStreamMetadata(param);
327
328 convertMetadata(STREAM_METADATA_NAME, inData, sm);
329
330 return sm;
331 }
332
333 /**
334 * Creates a default image metadata object and merges in the
335 * supplied metadata.
336 */
337 public IIOMetadata convertImageMetadata(IIOMetadata inData,
338 ImageTypeSpecifier imageType,
339 ImageWriteParam param) {
340 if (inData == null) {
341 throw new IllegalArgumentException("inData == null!");
342 }
343 if (imageType == null) {
344 throw new IllegalArgumentException("imageType == null!");
345 }
346
347 GIFWritableImageMetadata im =
348 (GIFWritableImageMetadata)getDefaultImageMetadata(imageType,
349 param);
350
351 // Save interlace flag state.
352
353 boolean isProgressive = im.interlaceFlag;
354
355 convertMetadata(IMAGE_METADATA_NAME, inData, im);
356
357 // Undo change to interlace flag if not MODE_COPY_FROM_METADATA.
358
359 if (param != null && param.canWriteProgressive() &&
360 param.getProgressiveMode() != ImageWriteParam.MODE_COPY_FROM_METADATA) {
361 im.interlaceFlag = isProgressive;
362 }
363
364 return im;
365 }
366
367 public void endWriteSequence() throws IOException {
368 if (stream == null) {
369 throw new IllegalStateException("output == null!");
370 }
371 if (!isWritingSequence) {
372 throw new IllegalStateException("prepareWriteSequence() was not invoked!");
373 }
374 writeTrailer();
375 resetLocal();
376 }
377
378 public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
379 ImageWriteParam param) {
380 GIFWritableImageMetadata imageMetadata =
381 new GIFWritableImageMetadata();
382
383 // Image dimensions
384
385 SampleModel sampleModel = imageType.getSampleModel();
386
387 Rectangle sourceBounds = new Rectangle(sampleModel.getWidth(),
388 sampleModel.getHeight());
389 Dimension destSize = new Dimension();
390 computeRegions(sourceBounds, destSize, param);
391
392 imageMetadata.imageWidth = destSize.width;
393 imageMetadata.imageHeight = destSize.height;
394
395 // Interlacing
396
397 if (param != null && param.canWriteProgressive() &&
405
406 ColorModel colorModel = imageType.getColorModel();
407
408 imageMetadata.localColorTable =
409 createColorTable(colorModel, sampleModel);
410
411 // Transparency
412
413 if (colorModel instanceof IndexColorModel) {
414 int transparentIndex =
415 ((IndexColorModel)colorModel).getTransparentPixel();
416 if (transparentIndex != -1) {
417 imageMetadata.transparentColorFlag = true;
418 imageMetadata.transparentColorIndex = transparentIndex;
419 }
420 }
421
422 return imageMetadata;
423 }
424
425 public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
426 GIFWritableStreamMetadata streamMetadata =
427 new GIFWritableStreamMetadata();
428 streamMetadata.version = "89a";
429 return streamMetadata;
430 }
431
432 public ImageWriteParam getDefaultWriteParam() {
433 return new GIFImageWriteParam(getLocale());
434 }
435
436 public void prepareWriteSequence(IIOMetadata streamMetadata)
437 throws IOException {
438
439 if (stream == null) {
440 throw new IllegalStateException("Output is not set.");
441 }
442
443 resetLocal();
444
445 // Save the possibly converted stream metadata as an instance variable.
446 if (streamMetadata == null) {
447 this.theStreamMetadata =
448 (GIFWritableStreamMetadata)getDefaultStreamMetadata(null);
449 } else {
450 this.theStreamMetadata = new GIFWritableStreamMetadata();
451 convertMetadata(STREAM_METADATA_NAME, streamMetadata,
452 theStreamMetadata);
453 }
454
455 this.isWritingSequence = true;
456 }
457
458 public void reset() {
459 super.reset();
460 resetLocal();
461 }
462
463 /**
464 * Resets locally defined instance variables.
465 */
466 private void resetLocal() {
467 this.isWritingSequence = false;
468 this.wroteSequenceHeader = false;
469 this.theStreamMetadata = null;
470 this.imageIndex = 0;
471 }
472
473 public void setOutput(Object output) {
474 super.setOutput(output);
475 if (output != null) {
476 if (!(output instanceof ImageOutputStream)) {
477 throw new
478 IllegalArgumentException("output is not an ImageOutputStream");
479 }
480 this.stream = (ImageOutputStream)output;
481 this.stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
482 } else {
483 this.stream = null;
484 }
485 }
486
487 public void write(IIOMetadata sm,
488 IIOImage iioimage,
489 ImageWriteParam p) throws IOException {
490 if (stream == null) {
491 throw new IllegalStateException("output == null!");
492 }
493 if (iioimage == null) {
494 throw new IllegalArgumentException("iioimage == null!");
495 }
496 if (iioimage.hasRaster()) {
497 throw new UnsupportedOperationException("canWriteRasters() == false!");
498 }
499
500 resetLocal();
501
502 GIFWritableStreamMetadata streamMetadata;
503 if (sm == null) {
504 streamMetadata =
505 (GIFWritableStreamMetadata)getDefaultStreamMetadata(p);
506 } else {
507 streamMetadata =
508 (GIFWritableStreamMetadata)convertStreamMetadata(sm, p);
509 }
510
511 write(true, true, streamMetadata, iioimage, p);
512 }
513
514 public void writeToSequence(IIOImage image, ImageWriteParam param)
515 throws IOException {
516 if (stream == null) {
517 throw new IllegalStateException("output == null!");
518 }
519 if (image == null) {
520 throw new IllegalArgumentException("image == null!");
521 }
522 if (image.hasRaster()) {
523 throw new UnsupportedOperationException("canWriteRasters() == false!");
524 }
525 if (!isWritingSequence) {
526 throw new IllegalStateException("prepareWriteSequence() was not invoked!");
527 }
528
529 write(!wroteSequenceHeader, false, theStreamMetadata,
530 image, param);
531
532 if (!wroteSequenceHeader) {
533 wroteSequenceHeader = true;
1302 imageMetadata.interlaceFlag,
1303 imageMetadata.sortFlag,
1304 bitsPerPixel,
1305 imageMetadata.localColorTable);
1306 }
1307
1308 private void writeTrailer() throws IOException {
1309 stream.write(0x3b);
1310 }
1311 }
1312
1313 class GIFImageWriteParam extends ImageWriteParam {
1314 GIFImageWriteParam(Locale locale) {
1315 super(locale);
1316 this.canWriteCompressed = true;
1317 this.canWriteProgressive = true;
1318 this.compressionTypes = new String[] {"LZW"};
1319 this.compressionType = compressionTypes[0];
1320 }
1321
1322 public void setCompressionMode(int mode) {
1323 if (mode == MODE_DISABLED) {
1324 throw new UnsupportedOperationException("MODE_DISABLED is not supported.");
1325 }
1326 super.setCompressionMode(mode);
1327 }
1328 }
|
250 return 2;
251 }
252 x = x - 1;
253 x = x | (x >> 1);
254 x = x | (x >> 2);
255 x = x | (x >> 4);
256 x = x | (x >> 8);
257 x = x | (x >> 16);
258 return x + 1;
259 }
260
261
262
263 public GIFImageWriter(GIFImageWriterSpi originatingProvider) {
264 super(originatingProvider);
265 if (DEBUG) {
266 System.err.println("GIF Writer is created");
267 }
268 }
269
270 @Override
271 public boolean canWriteSequence() {
272 return true;
273 }
274
275 /**
276 * Merges {@code inData} into {@code outData}. The supplied
277 * metadata format name is attempted first and failing that the standard
278 * metadata format name is attempted.
279 */
280 private void convertMetadata(String metadataFormatName,
281 IIOMetadata inData,
282 IIOMetadata outData) {
283 String formatName = null;
284
285 String nativeFormatName = inData.getNativeMetadataFormatName();
286 if (nativeFormatName != null &&
287 nativeFormatName.equals(metadataFormatName)) {
288 formatName = metadataFormatName;
289 } else {
290 String[] extraFormatNames = inData.getExtraMetadataFormatNames();
301
302 if (formatName == null &&
303 inData.isStandardMetadataFormatSupported()) {
304 formatName = STANDARD_METADATA_NAME;
305 }
306
307 if (formatName != null) {
308 try {
309 Node root = inData.getAsTree(formatName);
310 outData.mergeTree(formatName, root);
311 } catch(IIOInvalidTreeException e) {
312 // ignore
313 }
314 }
315 }
316
317 /**
318 * Creates a default stream metadata object and merges in the
319 * supplied metadata.
320 */
321 @Override
322 public IIOMetadata convertStreamMetadata(IIOMetadata inData,
323 ImageWriteParam param) {
324 if (inData == null) {
325 throw new IllegalArgumentException("inData == null!");
326 }
327
328 IIOMetadata sm = getDefaultStreamMetadata(param);
329
330 convertMetadata(STREAM_METADATA_NAME, inData, sm);
331
332 return sm;
333 }
334
335 /**
336 * Creates a default image metadata object and merges in the
337 * supplied metadata.
338 */
339 @Override
340 public IIOMetadata convertImageMetadata(IIOMetadata inData,
341 ImageTypeSpecifier imageType,
342 ImageWriteParam param) {
343 if (inData == null) {
344 throw new IllegalArgumentException("inData == null!");
345 }
346 if (imageType == null) {
347 throw new IllegalArgumentException("imageType == null!");
348 }
349
350 GIFWritableImageMetadata im =
351 (GIFWritableImageMetadata)getDefaultImageMetadata(imageType,
352 param);
353
354 // Save interlace flag state.
355
356 boolean isProgressive = im.interlaceFlag;
357
358 convertMetadata(IMAGE_METADATA_NAME, inData, im);
359
360 // Undo change to interlace flag if not MODE_COPY_FROM_METADATA.
361
362 if (param != null && param.canWriteProgressive() &&
363 param.getProgressiveMode() != ImageWriteParam.MODE_COPY_FROM_METADATA) {
364 im.interlaceFlag = isProgressive;
365 }
366
367 return im;
368 }
369
370 @Override
371 public void endWriteSequence() throws IOException {
372 if (stream == null) {
373 throw new IllegalStateException("output == null!");
374 }
375 if (!isWritingSequence) {
376 throw new IllegalStateException("prepareWriteSequence() was not invoked!");
377 }
378 writeTrailer();
379 resetLocal();
380 }
381
382 @Override
383 public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType,
384 ImageWriteParam param) {
385 GIFWritableImageMetadata imageMetadata =
386 new GIFWritableImageMetadata();
387
388 // Image dimensions
389
390 SampleModel sampleModel = imageType.getSampleModel();
391
392 Rectangle sourceBounds = new Rectangle(sampleModel.getWidth(),
393 sampleModel.getHeight());
394 Dimension destSize = new Dimension();
395 computeRegions(sourceBounds, destSize, param);
396
397 imageMetadata.imageWidth = destSize.width;
398 imageMetadata.imageHeight = destSize.height;
399
400 // Interlacing
401
402 if (param != null && param.canWriteProgressive() &&
410
411 ColorModel colorModel = imageType.getColorModel();
412
413 imageMetadata.localColorTable =
414 createColorTable(colorModel, sampleModel);
415
416 // Transparency
417
418 if (colorModel instanceof IndexColorModel) {
419 int transparentIndex =
420 ((IndexColorModel)colorModel).getTransparentPixel();
421 if (transparentIndex != -1) {
422 imageMetadata.transparentColorFlag = true;
423 imageMetadata.transparentColorIndex = transparentIndex;
424 }
425 }
426
427 return imageMetadata;
428 }
429
430 @Override
431 public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
432 GIFWritableStreamMetadata streamMetadata =
433 new GIFWritableStreamMetadata();
434 streamMetadata.version = "89a";
435 return streamMetadata;
436 }
437
438 @Override
439 public ImageWriteParam getDefaultWriteParam() {
440 return new GIFImageWriteParam(getLocale());
441 }
442
443 @Override
444 public void prepareWriteSequence(IIOMetadata streamMetadata)
445 throws IOException {
446
447 if (stream == null) {
448 throw new IllegalStateException("Output is not set.");
449 }
450
451 resetLocal();
452
453 // Save the possibly converted stream metadata as an instance variable.
454 if (streamMetadata == null) {
455 this.theStreamMetadata =
456 (GIFWritableStreamMetadata)getDefaultStreamMetadata(null);
457 } else {
458 this.theStreamMetadata = new GIFWritableStreamMetadata();
459 convertMetadata(STREAM_METADATA_NAME, streamMetadata,
460 theStreamMetadata);
461 }
462
463 this.isWritingSequence = true;
464 }
465
466 @Override
467 public void reset() {
468 super.reset();
469 resetLocal();
470 }
471
472 /**
473 * Resets locally defined instance variables.
474 */
475 private void resetLocal() {
476 this.isWritingSequence = false;
477 this.wroteSequenceHeader = false;
478 this.theStreamMetadata = null;
479 this.imageIndex = 0;
480 }
481
482 @Override
483 public void setOutput(Object output) {
484 super.setOutput(output);
485 if (output != null) {
486 if (!(output instanceof ImageOutputStream)) {
487 throw new
488 IllegalArgumentException("output is not an ImageOutputStream");
489 }
490 this.stream = (ImageOutputStream)output;
491 this.stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
492 } else {
493 this.stream = null;
494 }
495 }
496
497 @Override
498 public void write(IIOMetadata sm,
499 IIOImage iioimage,
500 ImageWriteParam p) throws IOException {
501 if (stream == null) {
502 throw new IllegalStateException("output == null!");
503 }
504 if (iioimage == null) {
505 throw new IllegalArgumentException("iioimage == null!");
506 }
507 if (iioimage.hasRaster()) {
508 throw new UnsupportedOperationException("canWriteRasters() == false!");
509 }
510
511 resetLocal();
512
513 GIFWritableStreamMetadata streamMetadata;
514 if (sm == null) {
515 streamMetadata =
516 (GIFWritableStreamMetadata)getDefaultStreamMetadata(p);
517 } else {
518 streamMetadata =
519 (GIFWritableStreamMetadata)convertStreamMetadata(sm, p);
520 }
521
522 write(true, true, streamMetadata, iioimage, p);
523 }
524
525 @Override
526 public void writeToSequence(IIOImage image, ImageWriteParam param)
527 throws IOException {
528 if (stream == null) {
529 throw new IllegalStateException("output == null!");
530 }
531 if (image == null) {
532 throw new IllegalArgumentException("image == null!");
533 }
534 if (image.hasRaster()) {
535 throw new UnsupportedOperationException("canWriteRasters() == false!");
536 }
537 if (!isWritingSequence) {
538 throw new IllegalStateException("prepareWriteSequence() was not invoked!");
539 }
540
541 write(!wroteSequenceHeader, false, theStreamMetadata,
542 image, param);
543
544 if (!wroteSequenceHeader) {
545 wroteSequenceHeader = true;
1314 imageMetadata.interlaceFlag,
1315 imageMetadata.sortFlag,
1316 bitsPerPixel,
1317 imageMetadata.localColorTable);
1318 }
1319
1320 private void writeTrailer() throws IOException {
1321 stream.write(0x3b);
1322 }
1323 }
1324
1325 class GIFImageWriteParam extends ImageWriteParam {
1326 GIFImageWriteParam(Locale locale) {
1327 super(locale);
1328 this.canWriteCompressed = true;
1329 this.canWriteProgressive = true;
1330 this.compressionTypes = new String[] {"LZW"};
1331 this.compressionType = compressionTypes[0];
1332 }
1333
1334 @Override
1335 public void setCompressionMode(int mode) {
1336 if (mode == MODE_DISABLED) {
1337 throw new UnsupportedOperationException("MODE_DISABLED is not supported.");
1338 }
1339 super.setCompressionMode(mode);
1340 }
1341 }
|