411 IIOException
412 {
413 if (!metadata.PLTE_present) {
414 throw new IIOException("hIST chunk without prior PLTE chunk!");
415 }
416
417 /* According to PNG specification length of
418 * hIST chunk is specified in bytes and
419 * hIST chunk consists of 2 byte elements
420 * (so we expect length is even).
421 */
422 metadata.hIST_histogram = new char[chunkLength/2];
423 stream.readFully(metadata.hIST_histogram,
424 0, metadata.hIST_histogram.length);
425
426 metadata.hIST_present = true;
427 }
428
429 private void parse_iCCP_chunk(int chunkLength) throws IOException {
430 String keyword = readNullTerminatedString("ISO-8859-1", 80);
431 metadata.iCCP_profileName = keyword;
432
433 metadata.iCCP_compressionMethod = stream.readUnsignedByte();
434
435 byte[] compressedProfile =
436 new byte[chunkLength - keyword.length() - 2];
437 stream.readFully(compressedProfile);
438 metadata.iCCP_compressedProfile = compressedProfile;
439
440 metadata.iCCP_present = true;
441 }
442
443 private void parse_iTXt_chunk(int chunkLength) throws IOException {
444 long chunkStart = stream.getStreamPosition();
445
446 String keyword = readNullTerminatedString("ISO-8859-1", 80);
447 metadata.iTXt_keyword.add(keyword);
448
449 int compressionFlag = stream.readUnsignedByte();
450 metadata.iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag == 1));
451
452 int compressionMethod = stream.readUnsignedByte();
453 metadata.iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
454
455 String languageTag = readNullTerminatedString("UTF8", 80);
456 metadata.iTXt_languageTag.add(languageTag);
457
458 long pos = stream.getStreamPosition();
459 int maxLen = (int)(chunkStart + chunkLength - pos);
460 String translatedKeyword =
461 readNullTerminatedString("UTF8", maxLen);
462 metadata.iTXt_translatedKeyword.add(translatedKeyword);
463
464 String text;
465 pos = stream.getStreamPosition();
466 byte[] b = new byte[(int)(chunkStart + chunkLength - pos)];
467 stream.readFully(b);
468
469 if (compressionFlag == 1) { // Decompress the text
470 text = new String(inflate(b), "UTF8");
471 } else {
472 text = new String(b, "UTF8");
473 }
474 metadata.iTXt_text.add(text);
475
476 // Check if the text chunk contains image creation time
477 if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
478 // Update Standard/Document/ImageCreationTime from text chunk
479 int index = metadata.iTXt_text.size() - 1;
480 metadata.decodeImageCreationTimeFromTextChunk(
481 metadata.iTXt_text.listIterator(index));
482 }
483 }
484
485 private void parse_pHYs_chunk() throws IOException {
486 metadata.pHYs_pixelsPerUnitXAxis = stream.readInt();
541 metadata.sPLT_green[i] = stream.readUnsignedShort();
542 metadata.sPLT_blue[i] = stream.readUnsignedShort();
543 metadata.sPLT_alpha[i] = stream.readUnsignedShort();
544 metadata.sPLT_frequency[i] = stream.readUnsignedShort();
545 }
546 } else {
547 throw new IIOException("sPLT sample depth not 8 or 16!");
548 }
549
550 metadata.sPLT_present = true;
551 }
552
553 private void parse_sRGB_chunk() throws IOException {
554 metadata.sRGB_renderingIntent = stream.readUnsignedByte();
555
556 metadata.sRGB_present = true;
557 }
558
559 private void parse_tEXt_chunk(int chunkLength) throws IOException {
560 String keyword = readNullTerminatedString("ISO-8859-1", 80);
561 metadata.tEXt_keyword.add(keyword);
562
563 byte[] b = new byte[chunkLength - keyword.length() - 1];
564 stream.readFully(b);
565 metadata.tEXt_text.add(new String(b, "ISO-8859-1"));
566
567 // Check if the text chunk contains image creation time
568 if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
569 // Update Standard/Document/ImageCreationTime from text chunk
570 int index = metadata.tEXt_text.size() - 1;
571 metadata.decodeImageCreationTimeFromTextChunk(
572 metadata.tEXt_text.listIterator(index));
573 }
574 }
575
576 private void parse_tIME_chunk() throws IOException {
577 metadata.tIME_year = stream.readUnsignedShort();
578 metadata.tIME_month = stream.readUnsignedByte();
579 metadata.tIME_day = stream.readUnsignedByte();
580 metadata.tIME_hour = stream.readUnsignedByte();
581 metadata.tIME_minute = stream.readUnsignedByte();
582 metadata.tIME_second = stream.readUnsignedByte();
583
635 }
636
637 private static byte[] inflate(byte[] b) throws IOException {
638 InputStream bais = new ByteArrayInputStream(b);
639 InputStream iis = new InflaterInputStream(bais);
640 ByteArrayOutputStream baos = new ByteArrayOutputStream();
641
642 int c;
643 try {
644 while ((c = iis.read()) != -1) {
645 baos.write(c);
646 }
647 } finally {
648 iis.close();
649 }
650 return baos.toByteArray();
651 }
652
653 private void parse_zTXt_chunk(int chunkLength) throws IOException {
654 String keyword = readNullTerminatedString("ISO-8859-1", 80);
655 metadata.zTXt_keyword.add(keyword);
656
657 int method = stream.readUnsignedByte();
658 metadata.zTXt_compressionMethod.add(method);
659
660 byte[] b = new byte[chunkLength - keyword.length() - 2];
661 stream.readFully(b);
662 metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1"));
663
664 // Check if the text chunk contains image creation time
665 if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
666 // Update Standard/Document/ImageCreationTime from text chunk
667 int index = metadata.zTXt_text.size() - 1;
668 metadata.decodeImageCreationTimeFromTextChunk(
669 metadata.zTXt_text.listIterator(index));
670 }
671 }
672
673 private void readMetadata() throws IIOException {
674 if (gotMetadata) {
675 return;
676 }
677
678 readHeader();
679
680 /*
|
411 IIOException
412 {
413 if (!metadata.PLTE_present) {
414 throw new IIOException("hIST chunk without prior PLTE chunk!");
415 }
416
417 /* According to PNG specification length of
418 * hIST chunk is specified in bytes and
419 * hIST chunk consists of 2 byte elements
420 * (so we expect length is even).
421 */
422 metadata.hIST_histogram = new char[chunkLength/2];
423 stream.readFully(metadata.hIST_histogram,
424 0, metadata.hIST_histogram.length);
425
426 metadata.hIST_present = true;
427 }
428
429 private void parse_iCCP_chunk(int chunkLength) throws IOException {
430 String keyword = readNullTerminatedString("ISO-8859-1", 80);
431 int compressedProfileLength = chunkLength - keyword.length() - 2;
432 if (compressedProfileLength < 0) {
433 throw new IIOException("iCCP chunk length is not proper");
434 }
435 metadata.iCCP_profileName = keyword;
436
437 metadata.iCCP_compressionMethod = stream.readUnsignedByte();
438
439 byte[] compressedProfile =
440 new byte[compressedProfileLength];
441 stream.readFully(compressedProfile);
442 metadata.iCCP_compressedProfile = compressedProfile;
443
444 metadata.iCCP_present = true;
445 }
446
447 private void parse_iTXt_chunk(int chunkLength) throws IOException {
448 long chunkStart = stream.getStreamPosition();
449
450 String keyword = readNullTerminatedString("ISO-8859-1", 80);
451 metadata.iTXt_keyword.add(keyword);
452
453 int compressionFlag = stream.readUnsignedByte();
454 metadata.iTXt_compressionFlag.add(Boolean.valueOf(compressionFlag == 1));
455
456 int compressionMethod = stream.readUnsignedByte();
457 metadata.iTXt_compressionMethod.add(Integer.valueOf(compressionMethod));
458
459 String languageTag = readNullTerminatedString("UTF8", 80);
460 metadata.iTXt_languageTag.add(languageTag);
461
462 long pos = stream.getStreamPosition();
463 int maxLen = (int)(chunkStart + chunkLength - pos);
464 String translatedKeyword =
465 readNullTerminatedString("UTF8", maxLen);
466 metadata.iTXt_translatedKeyword.add(translatedKeyword);
467
468 String text;
469 pos = stream.getStreamPosition();
470 int textLength = (int)(chunkStart + chunkLength - pos);
471 if (textLength < 0) {
472 throw new IIOException("iTXt chunk length is not proper");
473 }
474 byte[] b = new byte[textLength];
475 stream.readFully(b);
476
477 if (compressionFlag == 1) { // Decompress the text
478 text = new String(inflate(b), "UTF8");
479 } else {
480 text = new String(b, "UTF8");
481 }
482 metadata.iTXt_text.add(text);
483
484 // Check if the text chunk contains image creation time
485 if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
486 // Update Standard/Document/ImageCreationTime from text chunk
487 int index = metadata.iTXt_text.size() - 1;
488 metadata.decodeImageCreationTimeFromTextChunk(
489 metadata.iTXt_text.listIterator(index));
490 }
491 }
492
493 private void parse_pHYs_chunk() throws IOException {
494 metadata.pHYs_pixelsPerUnitXAxis = stream.readInt();
549 metadata.sPLT_green[i] = stream.readUnsignedShort();
550 metadata.sPLT_blue[i] = stream.readUnsignedShort();
551 metadata.sPLT_alpha[i] = stream.readUnsignedShort();
552 metadata.sPLT_frequency[i] = stream.readUnsignedShort();
553 }
554 } else {
555 throw new IIOException("sPLT sample depth not 8 or 16!");
556 }
557
558 metadata.sPLT_present = true;
559 }
560
561 private void parse_sRGB_chunk() throws IOException {
562 metadata.sRGB_renderingIntent = stream.readUnsignedByte();
563
564 metadata.sRGB_present = true;
565 }
566
567 private void parse_tEXt_chunk(int chunkLength) throws IOException {
568 String keyword = readNullTerminatedString("ISO-8859-1", 80);
569 int textLength = chunkLength - keyword.length() - 1;
570 if (textLength < 0) {
571 throw new IIOException("tEXt chunk length is not proper");
572 }
573 metadata.tEXt_keyword.add(keyword);
574
575 byte[] b = new byte[textLength];
576 stream.readFully(b);
577 metadata.tEXt_text.add(new String(b, "ISO-8859-1"));
578
579 // Check if the text chunk contains image creation time
580 if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
581 // Update Standard/Document/ImageCreationTime from text chunk
582 int index = metadata.tEXt_text.size() - 1;
583 metadata.decodeImageCreationTimeFromTextChunk(
584 metadata.tEXt_text.listIterator(index));
585 }
586 }
587
588 private void parse_tIME_chunk() throws IOException {
589 metadata.tIME_year = stream.readUnsignedShort();
590 metadata.tIME_month = stream.readUnsignedByte();
591 metadata.tIME_day = stream.readUnsignedByte();
592 metadata.tIME_hour = stream.readUnsignedByte();
593 metadata.tIME_minute = stream.readUnsignedByte();
594 metadata.tIME_second = stream.readUnsignedByte();
595
647 }
648
649 private static byte[] inflate(byte[] b) throws IOException {
650 InputStream bais = new ByteArrayInputStream(b);
651 InputStream iis = new InflaterInputStream(bais);
652 ByteArrayOutputStream baos = new ByteArrayOutputStream();
653
654 int c;
655 try {
656 while ((c = iis.read()) != -1) {
657 baos.write(c);
658 }
659 } finally {
660 iis.close();
661 }
662 return baos.toByteArray();
663 }
664
665 private void parse_zTXt_chunk(int chunkLength) throws IOException {
666 String keyword = readNullTerminatedString("ISO-8859-1", 80);
667 int textLength = chunkLength - keyword.length() - 2;
668 if (textLength < 0) {
669 throw new IIOException("zTXt chunk length is not proper");
670 }
671 metadata.zTXt_keyword.add(keyword);
672
673 int method = stream.readUnsignedByte();
674 metadata.zTXt_compressionMethod.add(method);
675
676 byte[] b = new byte[textLength];
677 stream.readFully(b);
678 metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1"));
679
680 // Check if the text chunk contains image creation time
681 if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
682 // Update Standard/Document/ImageCreationTime from text chunk
683 int index = metadata.zTXt_text.size() - 1;
684 metadata.decodeImageCreationTimeFromTextChunk(
685 metadata.zTXt_text.listIterator(index));
686 }
687 }
688
689 private void readMetadata() throws IIOException {
690 if (gotMetadata) {
691 return;
692 }
693
694 readHeader();
695
696 /*
|