Stefan Schuermans commited on 2018-09-18 20:41:57
Showing 1 changed files, with 79 additions and 0 deletions.
| ... | ... |
@@ -1418,6 +1418,83 @@ public class BlinkenMovie |
| 1418 | 1418 |
return false; |
| 1419 | 1419 |
} |
| 1420 | 1420 |
|
| 1421 |
+ public boolean saveGif( String filename ) |
|
| 1422 |
+ {
|
|
| 1423 |
+ try {
|
|
| 1424 |
+ |
|
| 1425 |
+ //create GIF writer |
|
| 1426 |
+ ImageWriter gifWr = null; |
|
| 1427 |
+ {
|
|
| 1428 |
+ Iterator<ImageWriter> it = ImageIO.getImageWritersBySuffix( "gif" ); |
|
| 1429 |
+ if ( ! it.hasNext( ) ) {
|
|
| 1430 |
+ return false; |
|
| 1431 |
+ } |
|
| 1432 |
+ gifWr = it.next(); |
|
| 1433 |
+ } |
|
| 1434 |
+ |
|
| 1435 |
+ //begin writing image |
|
| 1436 |
+ ImageOutputStream out = new FileImageOutputStream( new File( filename ) ); |
|
| 1437 |
+ gifWr.setOutput( out ); |
|
| 1438 |
+ gifWr.prepareWriteSequence( null ); |
|
| 1439 |
+ |
|
| 1440 |
+ //create buffered image with correct dimensions |
|
| 1441 |
+ BufferedImage img = new BufferedImage( this.width, this.height, |
|
| 1442 |
+ BufferedImage.TYPE_INT_ARGB ); |
|
| 1443 |
+ |
|
| 1444 |
+ //process all frames |
|
| 1445 |
+ int cnt = this.getFrameCnt( ); |
|
| 1446 |
+ for( int i = 0; i < cnt; i++ ) |
|
| 1447 |
+ {
|
|
| 1448 |
+ |
|
| 1449 |
+ //frame data into buffered image |
|
| 1450 |
+ for( int y = 0; y < this.height; y++ ) |
|
| 1451 |
+ for( int x = 0; x < this.width; x++ ) |
|
| 1452 |
+ img.setRGB( x, y, this.frames[i].getColor( y, x ).getRGB( ) ); |
|
| 1453 |
+ |
|
| 1454 |
+ //get frame duration |
|
| 1455 |
+ int duration = this.frames[i].getDuration( ); |
|
| 1456 |
+ |
|
| 1457 |
+ //construct metadata |
|
| 1458 |
+ ImageWriteParam prm = gifWr.getDefaultWriteParam( ); |
|
| 1459 |
+ ImageTypeSpecifier typeSpec = ImageTypeSpecifier.createFromBufferedImageType( img.getType( ) ); |
|
| 1460 |
+ IIOMetadata meta = gifWr.getDefaultImageMetadata( typeSpec, prm ); |
|
| 1461 |
+ String metaFmt = meta.getNativeMetadataFormatName( ); |
|
| 1462 |
+ IIOMetadataNode metaRoot = (IIOMetadataNode)meta.getAsTree( metaFmt ); |
|
| 1463 |
+ String nameGCE = "GraphicControlExtension"; |
|
| 1464 |
+ IIOMetadataNode metaGCE = null; |
|
| 1465 |
+ for( int n = 0; n < metaRoot.getLength(); n++ ) {
|
|
| 1466 |
+ Node node = metaRoot.item(n); |
|
| 1467 |
+ if( node.getNodeName().compareToIgnoreCase(nameGCE) == 0 ) {
|
|
| 1468 |
+ metaGCE = (IIOMetadataNode)node; |
|
| 1469 |
+ } |
|
| 1470 |
+ } |
|
| 1471 |
+ if( metaGCE == null ) {
|
|
| 1472 |
+ metaGCE = new IIOMetadataNode( nameGCE ); |
|
| 1473 |
+ metaRoot.appendChild( metaGCE ); |
|
| 1474 |
+ } |
|
| 1475 |
+ metaGCE.setAttribute( "disposalMethod", "doNotDispose" ); |
|
| 1476 |
+ metaGCE.setAttribute( "transparentColorFlag", "FALSE" ); |
|
| 1477 |
+ metaGCE.setAttribute( "transparentColorIndex", "0" ); |
|
| 1478 |
+ metaGCE.setAttribute( "delayTime", Integer.toString( (duration + 5) / 10 ) ); |
|
| 1479 |
+ metaGCE.setAttribute( "userInputFlag", "FALSE" ); |
|
| 1480 |
+ meta.setFromTree( metaFmt, metaRoot ); |
|
| 1481 |
+ |
|
| 1482 |
+ //write image |
|
| 1483 |
+ gifWr.writeToSequence( new IIOImage( img, null, meta ), prm ); |
|
| 1484 |
+ |
|
| 1485 |
+ } |
|
| 1486 |
+ |
|
| 1487 |
+ //finalize image |
|
| 1488 |
+ gifWr.endWriteSequence( ); |
|
| 1489 |
+ out.close( ); |
|
| 1490 |
+ |
|
| 1491 |
+ return true; |
|
| 1492 |
+ } |
|
| 1493 |
+ catch( IOException e ) { }
|
|
| 1494 |
+ |
|
| 1495 |
+ return false; |
|
| 1496 |
+ } |
|
| 1497 |
+ |
|
| 1421 | 1498 |
public boolean save( String filename ) |
| 1422 | 1499 |
{
|
| 1423 | 1500 |
if( filename.endsWith( ".blm" ) ) |
| ... | ... |
@@ -1428,6 +1505,8 @@ public class BlinkenMovie |
| 1428 | 1505 |
return saveBml( filename ); |
| 1429 | 1506 |
if( filename.endsWith( ".bbm" ) ) |
| 1430 | 1507 |
return saveBbm( filename ); |
| 1508 |
+ if( filename.endsWith( ".gif" ) ) |
|
| 1509 |
+ return saveGif( filename ); |
|
| 1431 | 1510 |
return false; |
| 1432 | 1511 |
} |
| 1433 | 1512 |
|
| 1434 | 1513 |