Path: blob/master/test/jdk/javax/imageio/plugins/tiff/MultiPageImageTIFFFieldTest.java
41153 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 8152183 814845426* @author a.stepanov27* @summary check that TIFFields are derived properly for multi-page tiff28* @run main MultiPageImageTIFFFieldTest29*/3031import java.awt.*;32import java.awt.color.*;33import java.awt.image.BufferedImage;34import java.io.*;35import javax.imageio.*;36import javax.imageio.metadata.*;37import javax.imageio.stream.*;38import javax.imageio.plugins.tiff.*;394041public class MultiPageImageTIFFFieldTest {4243private final static String FILENAME = "test.tiff";44private final static int W1 = 20, H1 = 40, W2 = 100, H2 = 15;45private final static Color C1 = Color.BLACK, C2 = Color.RED;4647private final static int N_WIDTH = BaselineTIFFTagSet.TAG_IMAGE_WIDTH;48private final static int N_HEIGHT = BaselineTIFFTagSet.TAG_IMAGE_LENGTH;4950private static final String DESCRIPTION_1[] = {"Description-1", "abc ABC"};51private static final String DESCRIPTION_2[] = {"Description-2", "1-2-3"};52private final static int N_DESCRIPTION =53BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION;5455private final static String EXIF_DATA_1[] = {"2001:01:01 00:00:01"};56private final static String EXIF_DATA_2[] = {"2002:02:02 00:00:02"};57private final static int N_EXIF = ExifTIFFTagSet.TAG_DATE_TIME_ORIGINAL;5859private final static String GPS_DATA[] = {60ExifGPSTagSet.STATUS_MEASUREMENT_IN_PROGRESS};61private final static int N_GPS = ExifGPSTagSet.TAG_GPS_STATUS;6263private final static short FAX_DATA =64FaxTIFFTagSet.CLEAN_FAX_DATA_ERRORS_UNCORRECTED;65private final static int N_FAX = FaxTIFFTagSet.TAG_CLEAN_FAX_DATA;6667private static final byte[] ICC_PROFILE_2 =68ICC_ProfileRGB.getInstance(ColorSpace.CS_sRGB).getData();69private static final int N_ICC = BaselineTIFFTagSet.TAG_ICC_PROFILE;7071private static final int N_BPS = BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE;7273private static final int74COMPRESSION_1 = BaselineTIFFTagSet.COMPRESSION_DEFLATE,75COMPRESSION_2 = BaselineTIFFTagSet.COMPRESSION_LZW;76private static final int N_COMPRESSION = BaselineTIFFTagSet.TAG_COMPRESSION;7778private static final int79GRAY_1 = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO,80GRAY_2 = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO,81RGB = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB;8283private static final int N_PHOTO =84BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION;8586private ImageWriter getTIFFWriter() {8788java.util.Iterator<ImageWriter> writers =89ImageIO.getImageWritersByFormatName("TIFF");90if (!writers.hasNext()) {91throw new RuntimeException("No writers available for TIFF format");92}93return writers.next();94}9596private ImageReader getTIFFReader() {9798java.util.Iterator<ImageReader> readers =99ImageIO.getImageReadersByFormatName("TIFF");100if (!readers.hasNext()) {101throw new RuntimeException("No readers available for TIFF format");102}103return readers.next();104}105106private void addASCIIField(TIFFDirectory d,107String name,108String data[],109int num) {110111d.addTIFFField(new TIFFField(112new TIFFTag(name, num, 1 << TIFFTag.TIFF_ASCII),113TIFFTag.TIFF_ASCII, data.length, data));114}115116private void checkASCIIField(TIFFDirectory d,117String what,118String data[],119int num) {120121String notFound = what + " field was not found";122check(d.containsTIFFField(num), notFound);123TIFFField f = d.getTIFFField(num);124check(f.getType() == TIFFTag.TIFF_ASCII, "field type != ASCII");125check(f.getCount() == data.length, "invalid " + what + " data count");126for (int i = 0; i < data.length; i++) {127check(f.getValueAsString(i).equals(data[i]),128"invalid " + what + " data");129}130}131132private void writeImage() throws Exception {133134OutputStream s = new BufferedOutputStream(new FileOutputStream(FILENAME));135try (ImageOutputStream ios = ImageIO.createImageOutputStream(s)) {136137ImageWriter writer = getTIFFWriter();138writer.setOutput(ios);139140BufferedImage img1 =141new BufferedImage(W1, H1, BufferedImage.TYPE_BYTE_GRAY);142Graphics g = img1.getGraphics();143g.setColor(C1);144g.fillRect(0, 0, W1, H1);145g.dispose();146147BufferedImage img2 =148new BufferedImage(W2, H2, BufferedImage.TYPE_INT_RGB);149g = img2.getGraphics();150g.setColor(C2);151g.fillRect(0, 0, W2, H2);152g.dispose();153154ImageWriteParam param1 = writer.getDefaultWriteParam();155param1.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);156param1.setCompressionType("Deflate");157param1.setCompressionQuality(0.5f);158159ImageWriteParam param2 = writer.getDefaultWriteParam();160param2.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);161param2.setCompressionType("LZW");162param2.setCompressionQuality(0.5f);163164IIOMetadata165md1 = writer.getDefaultImageMetadata(166new ImageTypeSpecifier(img1), param1),167md2 = writer.getDefaultImageMetadata(168new ImageTypeSpecifier(img2), param2);169170TIFFDirectory171dir1 = TIFFDirectory.createFromMetadata(md1),172dir2 = TIFFDirectory.createFromMetadata(md2);173174addASCIIField(dir1, "ImageDescription", DESCRIPTION_1, N_DESCRIPTION);175addASCIIField(dir2, "ImageDescription", DESCRIPTION_2, N_DESCRIPTION);176177addASCIIField(dir1, "GPSStatus", GPS_DATA, N_GPS);178addASCIIField(dir2, "GPSStatus", GPS_DATA, N_GPS);179180addASCIIField(dir1, "DateTimeOriginal", EXIF_DATA_1, N_EXIF);181addASCIIField(dir2, "DateTimeOriginal", EXIF_DATA_2, N_EXIF);182183TIFFTag faxTag = new TIFFTag(184"CleanFaxData", N_FAX, 1 << TIFFTag.TIFF_SHORT);185dir1.addTIFFField(new TIFFField(faxTag, FAX_DATA));186dir2.addTIFFField(new TIFFField(faxTag, FAX_DATA));187188dir2.addTIFFField(new TIFFField(189new TIFFTag("ICC Profile", N_ICC, 1 << TIFFTag.TIFF_UNDEFINED),190TIFFTag.TIFF_UNDEFINED, ICC_PROFILE_2.length, ICC_PROFILE_2));191192writer.prepareWriteSequence(null);193writer.writeToSequence(194new IIOImage(img1, null, dir1.getAsMetadata()), param1);195writer.writeToSequence(196new IIOImage(img2, null, dir2.getAsMetadata()), param2);197writer.endWriteSequence();198199ios.flush();200writer.dispose();201}202s.close();203}204205private void checkBufferedImages(BufferedImage im1, BufferedImage im2) {206207check(im1.getWidth() == W1, "invalid width for image 1");208check(im1.getHeight() == H1, "invalid height for image 1");209check(im2.getWidth() == W2, "invalid width for image 2");210check(im2.getHeight() == H2, "invalid height for image 2");211212Color213c1 = new Color(im1.getRGB(W1 / 2, H1 / 2)),214c2 = new Color(im2.getRGB(W2 / 2, H2 / 2));215216check(c1.equals(C1), "invalid image 1 color");217check(c2.equals(C2), "invalid image 2 color");218}219220private void readAndCheckImage() throws Exception {221222ImageReader reader = getTIFFReader();223224ImageInputStream s = ImageIO.createImageInputStream(new File(FILENAME));225reader.setInput(s, false, false);226227int ni = reader.getNumImages(true);228check(ni == 2, "invalid number of images");229230// check TIFFImageReadParam for multipage image231TIFFImageReadParam232param1 = new TIFFImageReadParam(), param2 = new TIFFImageReadParam();233234param1.addAllowedTagSet(ExifTIFFTagSet.getInstance());235param1.addAllowedTagSet(ExifGPSTagSet.getInstance());236237param2.addAllowedTagSet(ExifTIFFTagSet.getInstance());238param2.addAllowedTagSet(GeoTIFFTagSet.getInstance());239240// FaxTIFFTagSet is allowed by default241param2.removeAllowedTagSet(FaxTIFFTagSet.getInstance());242243244// read images and metadata245IIOImage i1 = reader.readAll(0, param1), i2 = reader.readAll(1, param2);246BufferedImage247bi1 = (BufferedImage) i1.getRenderedImage(),248bi2 = (BufferedImage) i2.getRenderedImage();249250// check rendered images, just in case251checkBufferedImages(bi1, bi2);252253TIFFDirectory254dir1 = TIFFDirectory.createFromMetadata(i1.getMetadata()),255dir2 = TIFFDirectory.createFromMetadata(i2.getMetadata());256257// check ASCII fields258checkASCIIField(259dir1, "image 1 description", DESCRIPTION_1, N_DESCRIPTION);260checkASCIIField(261dir2, "image 2 description", DESCRIPTION_2, N_DESCRIPTION);262263checkASCIIField(dir1, "image 1 datetime", EXIF_DATA_1, N_EXIF);264checkASCIIField(dir2, "image 2 datetime", EXIF_DATA_2, N_EXIF);265266// check sizes267TIFFField f = dir1.getTIFFField(N_WIDTH);268check((f.getCount() == 1) && (f.getAsInt(0) == W1),269"invalid width field for image 1");270f = dir2.getTIFFField(N_WIDTH);271check((f.getCount() == 1) && (f.getAsInt(0) == W2),272"invalid width field for image 2");273274f = dir1.getTIFFField(N_HEIGHT);275check((f.getCount() == 1) && (f.getAsInt(0) == H1),276"invalid height field for image 1");277f = dir2.getTIFFField(N_HEIGHT);278check((f.getCount() == 1) && (f.getAsInt(0) == H2),279"invalid height field for image 2");280281// check fax data282check(dir1.containsTIFFField(N_FAX), "image 2 TIFF directory " +283"must contain clean fax data");284f = dir1.getTIFFField(N_FAX);285check(286(f.getCount() == 1) && f.isIntegral() && (f.getAsInt(0) == FAX_DATA),287"invalid clean fax data");288289check(!dir2.containsTIFFField(N_FAX), "image 2 TIFF directory " +290"must not contain fax fields");291292// check GPS data293checkASCIIField(dir1, "GPS status", GPS_DATA, N_GPS);294295check(!dir2.containsTIFFField(N_GPS), "image 2 TIFF directory " +296"must not contain GPS fields");297298// check ICC profile data299check(!dir1.containsTIFFField(N_ICC), "image 1 TIFF directory "300+ "must not contain ICC Profile field");301check(dir2.containsTIFFField(N_ICC), "image 2 TIFF directory "302+ "must contain ICC Profile field");303304f = dir2.getTIFFField(N_ICC);305check(f.getType() == TIFFTag.TIFF_UNDEFINED,306"invalid ICC profile field type");307int cnt = f.getCount();308byte icc[] = f.getAsBytes();309check((cnt == ICC_PROFILE_2.length) && (cnt == icc.length),310"invalid ICC profile");311for (int i = 0; i < cnt; i++) {312check(icc[i] == ICC_PROFILE_2[i], "invalid ICC profile data");313}314315// check component sizes316check(dir1.getTIFFField(N_BPS).isIntegral() &&317dir2.getTIFFField(N_BPS).isIntegral(),318"invalid bits per sample type");319int sz1[] = bi1.getColorModel().getComponentSize(),320sz2[] = bi2.getColorModel().getComponentSize(),321bps1[] = dir1.getTIFFField(N_BPS).getAsInts(),322bps2[] = dir2.getTIFFField(N_BPS).getAsInts();323324check((bps1.length == sz1.length) && (bps2.length == sz2.length),325"invalid component size count");326327for (int i = 0; i < bps1.length; i++) {328check(bps1[i] == sz1[i], "image 1: invalid bits per sample data");329}330331for (int i = 0; i < bps2.length; i++) {332check(bps2[i] == sz2[i], "image 2: invalid bits per sample data");333}334335// check compression data336check(dir1.containsTIFFField(N_COMPRESSION) &&337dir2.containsTIFFField(N_COMPRESSION),338"compression info lost");339f = dir1.getTIFFField(N_COMPRESSION);340check(f.isIntegral() && (f.getCount() == 1) &&341(f.getAsInt(0) == COMPRESSION_1), "invalid image 1 compression data");342343f = dir2.getTIFFField(N_COMPRESSION);344check(f.isIntegral() && (f.getCount() == 1) &&345(f.getAsInt(0) == COMPRESSION_2), "invalid image 2 compression data");346347// check photometric interpretation348f = dir1.getTIFFField(N_PHOTO);349check(f.isIntegral() && (f.getCount() == 1) &&350((f.getAsInt(0) == GRAY_1) || (f.getAsInt(0) == GRAY_2)),351"invalid photometric interpretation for image 1");352353f = dir2.getTIFFField(N_PHOTO);354check(f.isIntegral() && (f.getCount() == 1) && (f.getAsInt(0) == RGB),355"invalid photometric interpretation for image 2");356}357358public void run() {359360try {361writeImage();362readAndCheckImage();363} catch (Exception e) {364throw new RuntimeException(e);365}366}367368private void check(boolean ok, String msg) {369370if (!ok) { throw new RuntimeException(msg); }371}372373public static void main(String[] args) {374(new MultiPageImageTIFFFieldTest()).run();375}376}377378379