ソース・イメージ・データが測光型CIE L*a*b*またはYCbCrを有し、かつ宛先色空間型がRGBである場合、ソース・イメージ・データは、内部カラー変換器を使用して自動的にRGBに変換されます。
デフォルトのCMYK色空間に使用される正規化色座標変換は、次のように定義されます:
R = (1 - K)*(1 - C) G = (1 - K)*(1 - M) B = (1 - K)*(1 - Y)
K = min{1 - R, 1 - G, 1 - B} if(K != 1) { C = (1 - R - K)/(1 - K) M = (1 - G - K)/(1 - K) Y = (1 - B - K)/(1 - K) } else { C = M = Y = 0 }
他の色空間が推測されない場合に使用される一般的な色空間は、単にデータが読み込まれるようにするために提供されます。 あらゆる種類の正確な変換を提供するためのものではありません。
データが前述のものによって正しく処理されない色空間にあることが分かっている場合は、ImageTypeSpecifier
をリーダーに供給し、問題のデータに適した色空間から導出する必要があります。
何らかの理由で、埋め込まれたICCプロファイルが自動的に使用されない場合は、この手順に従って手動で使用することができます:
ImageReader.getImageMetadata
からイメージ・メタデータを取得ICC_Profile.getInstance(byte[])
を使用してICCプロファイル・フィールド・データから作成したICC_ProfileからICC_ColorSpaceを作成します。ICC_ColorSpace
を受け入れるファクトリ・メソッドの1つを使用して、新しい色空間からImageTypeSpecifier
を作成します。
ImageReadParam.setDestinationType
を使用してImageTypeSpecifier
を設定します。read
メソッドに渡します。「ICCプロファイル」フィールドに基づかない推定色空間がICCプロファイル・ベースの色空間と互換性がある場合、この推定色空間から派生した第2のImageTypeSpecifier
がImageReader.getImageTypes
によって返されるIteratorに含まれます。 イテレータに複数の型が含まれている場合、最初の型はICCプロファイルに基づいており、2番目の型は推定色空間に基づいています。
ImageReader.setInput(Object,boolean,boolean)
のignoreMetadata
パラメータを介して、通常どおりすべてのメタデータを無視するように通知されます。 TIFFImageReadParam.addAllowedTagSet(TIFFTagSet)
とTIFFImageReadParam.removeAllowedTagSet(TIFFTagSet)
を介して、どのTIFFTagが認識するかどうかを通知します。 ignoreMetadata
がtrue
の場合、イメージの読み取りに不可欠なメタデータのみがネイティブ・イメージ・メタデータ・オブジェクトにロードされます。 ignoreMetadata
がfalse
の場合、リーダーは、デフォルトでイメージを読み取るために不可欠なフィールドまたは許可されたTIFFTagSet
の1つに含まれるTIFFTag
を持つフィールドだけをネイティブ・イメージ・メタデータ・オブジェクトにロードします。 TIFFImageReadParam.setReadUnknownTags(boolean)
がパラメータtrue
で呼び出されたTIFFImageReadParam
を渡すことによって、許可されたTIFFTagSet
にないタグを持つフィールドの読み取りを強制することができます。
TIFFDirectoryオブジェクトを使用すると、メタデータ値へのアクセスが簡単になります。 TIFFDirectory
のインスタンスは、TIFFDirectory.createFromMetadata
メソッドを使用してTIFFリーダーによって返されたIIOMetadata
オブジェクトから作成されます。
標準メタデータ要素 | TIFFフィールドからの派生 |
---|---|
/Chroma/ColorSpaceType@name | PhotometricInterpretation: WhiteIsZero、BlackIsZero、TransparencyMask = "GRAY"; RGB、PaletteColor => "RGB"; CMYK => "CMYK"; YCbCr => "YCbCr"; CIELab、ICCLab => "Lab"。 |
/Chroma/NumChannels@value | SamplesPerPixel |
/Chroma/BlackIsZero@value | "TRUE" <=> PhotometricInterpretation => WhiteIsZero |
/Chroma/Palette | ColorMap |
/Compression/CompressionTypeName@value | 圧縮: 非圧縮=> "none"; CCITT 1D => "CCITT RLE";グループ3ファックス=> "CCITT T.4";グループ4ファックス=> "CCITT T.6"; LZW => "LZW"; JPEG => "Old JPEG";新しいJPEG => "JPEG"; Zlib =>> "ZLib"; PackBits => "PackBits"; Deflate => "Deflate"; Exif JPEG => "JPEG"。 |
/Compression/Lossless@value | 圧縮: JPEGまたは新しいJPEG => "FALSE";そうでなければ"TRUE"。 |
/Data/PlanarConfiguration@value | Chunky => "PixelInterleaved"; Planar => "PlaneInterleaved"。 |
/Data/SampleFormat@value | PhotometricInterpretation PaletteColor => "Index"; SampleFormat符号なし整数データ=> "UnsignedIntegral"; SampleFormat 2つの補数符号付き整数データ=> "SignedIntegral"; SampleFormat IEEE浮動小数点データ=> "Real";それ以外の要素は放出されません。 |
/Data/BitsPerSample@value | BitsPerSampleは空白で区切られたリストです。 |
/Data/SampleMSB@value | FillOrder: 左から右=> BitsPerSample-1のスペースで区切られたリスト。右から左=>スペースで区切られた0のリスト。 |
/Dimension/PixelAspectRatio@value | (1/XResolution)/(1/YResolution) |
/Dimension/ImageOrientation@value | Orientation |
/Dimension/HorizontalPixelSize@value | ResolutionUnitがNoneでない場合、1/XResolution(ミリ・メートル)。 |
/Dimension/VerticalPixelSize@value | ResolutionUnitがNoneでない場合、1/YResolution(ミリ・メートル)。 |
/Dimension/HorizontalPosition@value | ResolutionUnitがNoneでない場合のミリ秒単位の単位。 |
/Dimension/VerticalPosition@value | ResolutionUnitがNoneでない場合はYミリ・メートル単位で表します。 |
/Document/FormatVersion@value | 6.0 |
/Document/SubimageInterpretation@value | NewSubFileType: 透明度=> "TransparencyMask";縮小解像度=> "ReducedResolution";シングル・ページ=> "SinglePage"。 |
/Document/ImageCreationTime@value | DateTime |
/Text/TextEntry | DocumentName, ImageDescription, Make, Model, PageName, Software, Artist, HostComputer, InkNames, Copyright: /Text/TextEntry@keyword =フィールド名、/Text/TextEntry@value =フィールド値。 例: TIFF Software field => /Text/TextEntry@keyword = "ソフトウェア"、/Text/TextEntry@value =イメージの作成に使用されたソフトウェア・パッケージの名前とバージョン番号。 |
/Transparency/Alpha@value | ExtraSamples: 関連するアルファ=> "premultiplied";関連しないアルファ=> "nonpremultiplied"。 |
APP1
マーカー・セグメントの内容を読み取ることができます。
ImageReader
メソッドを使用して、イメージ・データとメタデータを読み取ることができます:
ImageInputStream input;
ImageReader tiffReader;
ImageReadParam tiffReadParam;
tiffReader.setInput(input);
// Read primary image and IFD.
BufferedImage image = tiffReader.read(0, tiffReadParam);
IIOMetadata primaryIFD = tiffReader.getImageMetadata(0);
// Read thumbnail if present.
BufferedImage thumbnail = null;
if (tiffReader.getNumImages(true) > 1) {
thumbnail = tiffReader.read(1, tiffReadParam);
}
Exifサムネイルはサムネイルとしてではなく、TIFFストリーム内の別のページとして扱われます。つまり、tiffReader.hasThumbnails(0)
はfalse
を返します。
APP1
マーカー・セグメントが挿入された3バンドISO/IEC 10918-1のベースラインDCT JPEGストリームです。 長さの後のマーカー・セグメントのパラメータは、完全なTIFFストリームに続く6バイトのシーケンス{'E', 'x', 'i', 'f', 0x00, 0x00}
です。 埋め込まれたTIFFストリームは、オプションでサムネイルIFDおよび圧縮または非圧縮のサムネイル・イメージ・データが続くJPEGイメージを記述するプライマリIFDを含む。 埋め込みTIFFストリームは、プライマリIFDに関連するイメージ・データも、JPEGストリーム自体に見られる情報を複製する記述フィールドも含まないことに留意されたい。
APP1
マーカー・セグメントのパラメータ内容は、JPEGリーダーによって返されたイメージ・メタデータ・オブジェクトから抽出されたjavax_imageio_jpeg_image_1.0
ネイティブ・イメージ・メタデータ・ツリー内の関連するNode
のユーザー・オブジェクトから取得することができます。 このAPP1 Exifノードは、"markerSequence"という名前のノードの子になり、名前unknown
と、0xE1
(String
の値"225"
)を持つMarkerTag
という名前の属性を持ちます。 このノードのユーザー・オブジェクトは、6バイトの{'E', 'x', 'i', 'f', '0', '0'}
で始まるバイト配列になります。 プライマリIFDおよびサムネイルIFDおよびイメージは、通常のImageReader
メソッドによってユーザー・オブジェクトから読み取ることができる:
ImageReader jpegReader;
ImageReader tiffReader;
// Obtain the APP1 Exif marker data from the JPEG image metadata.
IIOMetadata jpegImageMetadata = jpegReader.getImageMetadata(0);
String nativeFormat = jpegImageMetadata.getNativeMetadataFormatName();
Node jpegImageMetadataTree = jpegImageMetadata.getAsTree(nativeFormat);
// getExifMarkerData() returns the byte array which is the user object
// of the APP1 Exif marker node.
byte[] app1Params = getExifMarkerData(jpegImageMetadataTree);
if (app1Params == null) {
throw new IIOException("APP1 Exif marker not found.");
}
// Set up input, skipping Exif ID 6-byte sequence.
MemoryCacheImageInputStream app1ExifInput
= new MemoryCacheImageInputStream
(new ByteArrayInputStream(app1Params, 6, app1Params.length - 6));
tiffReader.setInput(app1ExifInput);
// Read primary IFD.
IIOMetadata primaryIFD = tiffReader.getImageMetadata(0);
// Read thumbnail if present.
BufferedImage thumbnail = null;
if (tiffReader.getNumImages(true) > 1) {
thumbnail = tiffReader.read(1, tiffReadParam);
}
// Read the primary image.
BufferedImage image = jpegReader.read(0);
tiffReader.getNumImages(true)
は、空のイメージに対応するものを含む組み込みTIFFストリーム内のIFDの数を返します。 埋め込まれたTIFFストリームのプライマリ・イメージは常に空であるため、tiffReader.read(0, readParam)
を呼び出すと例外がスローされます。主画像はJPEGリーダー自体を使用して取得する必要があります。
ImageWriter
のgetDefaultWriteParam()
メソッドによって返されたImageWriteParam
に対して、canWriteTiles()
およびcanWriteCompressed()
メソッドはtrue
を返します。canOffsetTiles()
とcanWriteProgressive()
メソッドはfalse
を返します。 TIFFライターは、タイル・イメージの書き込み、イメージの挿入、空のイメージの書き込みまたは挿入、イメージ・データの置換など、多くのオプション機能をサポートしています。 ピクセルは、空のイメージまたは空でないイメージのいずれかで、データが圧縮されていない場合にのみ置き換えられます。
タイルが書き込まれている場合、各ディメンションはTIFF仕様に従って16の最も近い倍数に丸められます。 JPEG-in-TIFF圧縮が使用されており、タイルが書き込まれている場合、各タイルのディメンションは、そのディメンションのJPEG最小単位(MCU)の最も近い倍数に丸められます。 JPEG-in-TIFF圧縮が使用されていてストリップが書き込まれている場合、ストリップあたりの行数は、両方のディメンションで最大MCUの8倍の倍数に丸められます。
MODE_EXPLICIT
に設定した後、ImageWriteParam
のsetCompressionType()
メソッドによって設定することができます。 本来サポートされている圧縮形式のセットを次の表に示します:
圧縮タイプ | 説明 | 参照 |
---|---|---|
CCITT RLE | 修正ハフマン圧縮 | TIFF 6.0仕様、セクション10 |
CCITT T.4 | CCITT T.4二値符号化/グループ3ファクシミリ圧縮 | TIFF 6.0仕様、セクション11 |
CCITT T.6 | CCITT T.6二値符号化/グループ4ファクシミリ圧縮 | TIFF 6.0仕様、セクション11 |
LZW | LZW圧縮 | TIFF 6.0仕様、セクション13 |
JPEG | "新しい" JPEG-in-TIFF圧縮 | TIFFテクニカル・ノート#2 |
ZLib | "Deflate/Inflate" compression (この表の後の注記を参照) | |
PackBits | バイト指向、ランレングス圧縮 | TIFF 6.0仕様、セクション9 |
Deflate | "Zip-in-TIFF" compression (この表の後の注記を参照) | 「ZLIB圧縮データ・フォーマット仕様」, 「DEFLATE圧縮データ・フォーマット仕様」 |
Exif JPEG | Exif固有のJPEG圧縮(この表の後の注記を参照) | 「Exif 2.2仕様」 (PDF)、セクション4.5.5、"サムネイル・データの基本構造" |
TIFF 6.0仕様のセクション22で説明されている古いスタイルのJPEG圧縮はサポートされていません。
CCITT圧縮型は、二値の(1-bit)イメージにのみ適用されます。 JPEG圧縮型は、バイト・グレイ・スケールの(1-band)およびRGB (3-band)イメージにのみ適用されます。
ZLibとDeflate圧縮は、TIFF Compressionフィールドの値を除いて同一です: ZLibの圧縮フィールドの値は8ですが、Deflateの場合は値32946 (0x80b2)です。 どちらの場合も、各イメージ・セグメント(ストリップまたはタイル)は、単一の完全なzlibデータ・ストリームとして書き込まれます。
"Exif JPEG"は、JPEGネイティブ・イメージ・メタデータ・ツリーに含めるために、APP1 Exifマーカー・セグメントの内容を書き込むときに使用される圧縮型です。 この圧縮型が使用されたときに出力に付加される内容は、空のイメージまたは空でないイメージが書き込まれるかどうかの関数です。 イメージが空の場合、圧縮されたExifプライマリIFDの仕様に準拠したTIFF IFDが追加されます。 イメージが空でなければ、圧縮されたExifサムネイルIFDおよびイメージの仕様に従った完全なIFDおよびイメージが付加されます。 空のイメージのデータは、後にTIFFライターのピクセル置換機能を使用して追加できないことに注意してください。
ZLib/DeflateまたはJPEG圧縮を使用すると、圧縮品質が設定されます。 ZLib/Deflateの場合、指定された浮動小数点の品質値は[1, 9]
の範囲に再スケーリングされ、Deflate圧縮レベルを得るために整数に切り捨てられます。 JPEGの場合、浮動小数点品質値は通常の方法で解釈するJPEGライター・プラグ・インに直接渡されます。
ソース・イメージ・データ色空間型がRGBであり、宛先測光型がCIE L*a*b*またはYCbCrである場合、ソース・イメージ・データは内部カラー変換器を使用してRGBから自動的に変換されます。
ICC Profile
フィールドが書き込まれます:
ImageTypeSpecifier
のColorSpaceは、ColorSpace
クラスのCS_*
定数によって定義された標準色空間の1つではないICC_ColorSpace
のインスタンスです。 宛先型はImageWriteParam.setDestinationType(ImageTypeSpecifier)
で設定され、デフォルトでは書き込まれるイメージのImageTypeSpecifier
に設定されます。
二値イメージの場合、FillOrder
、およびT4Options
フィールドは出力データに影響します。 FillOrder
の値が2 (BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT
)の場合、データは右から左に入力され、それ以外の場合は左から右に入力されます。 T4Options
の値は、データを1Dまたは2Dエンコードする必要があるかどうか、およびEOLパッディングを使用するかどうかを指定します。
すべてのイメージについて、RowsPerStrip
フィールドの値は、イメージがタイル化されていない場合、ストリップごとの行数を設定するために使用されます。 ストリップあたりの行のデフォルト数は、8または8キロバイトを超えないいずれか大きい方の行数です。
すべてのイメージについて、タイ・リング・モードがImageWriteParam.MODE_COPY_FROM_METADATA
の場合、TileWidth
およびTileLength
フィールド値を使用してタイル・ディメンションを設定できます。 このモードが設定されていてもフィールドが設定されていない場合、それぞれのデフォルト値はイメージの幅と高さです。
JPEG-in-TIFF圧縮を使用する場合、ライターに提供されたメタデータ・オブジェクトにJPEGTables
フィールドが含まれている場合にのみ、JPEGTables
フィールドがIFDに書き込まれ、JPEGストリームが各ストリップまたはタイルに短縮されます。 JPEGTables
フィールドの内容が有効なテーブルのみのJPEGストリームである場合は、それが使用されます。そうしないと、フィールドの内容はデフォルトの視覚的に無損失の表に置き換えられます。 そのようなJPEGTables
フィールドがメタデータに存在しない場合、JPEGTables
フィールドは出力に書き込まれず、各ストリップまたはタイルは独立した独立したJPEGストリームとして書き込まれます。
Deflate/ZLibまたはLZW圧縮を使用する場合、イメージが8ビット/サンプルの場合、Predictor
フィールドの値が2 (BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING
)の場合、水平差分予測子が使用されます。 予測がリクエストされても、イメージが8ビット/サンプルを持たない場合、フィールドは1 (BaselineTIFFTagSet.PREDICTOR_NONE
)の値にリセットされます。
いくつかのフィールドが追加または変更されることがあります:
PhotometricInterpretation
が存在しない場合。Planar
で存在する場合、PlanarConfiguration
はChunky
にリセットされます。Compression
always.BitsPerSample
。SamplesPerPixel
always.ExtraSamples
(アルファ・チャネルが存在する場合)。SampleFormat
が存在しない場合、そのデータは16ビットまたは32ビットの整数または浮動小数点です。PhotometricInterpretation
がRGBPalette
の場合はColorMap
。ImageWidth
とImageLength
です。TileWidth
、TileLength
、TileOffsets
、およびTileByteCounts
が含まれています。RowsPerStrip
、StripOffsets
、およびStripByteCounts
が含まれています。XResolution
、YResolution
、およびResolutionUnit
が存在しない場合。YCbCrSubsampling
とYCbCrPositioning
のように、測光の解釈がYCbCrで、圧縮のタイプがJPEGでない場合は(JPEG以外のYCbCr出力に対しては、[1, 1]サブ・サンプリングとサイズ測位のみがサポートされています)です。YCbCrSubsampling
、YCbCrPositioning
、およびReferenceBlackWhite
: 圧縮型がJPEGで色空間がRGBの場合、これらは、ヘッドルーム/フットルーム(0:255,128:255,128:255)を持たない[2, 2]中心のサブ・サンプリングにリセットされます。いくつかのフィールドが削除されることがあります:
BitsPerSample
。ExtraSamples
。RGBPalette
でない場合はColorMap
。TileWidth
、TileLength
、TileOffsets
、およびTileByteCounts
を使用しない場合は、。RowsPerStrip
、StripOffsets
、およびStripByteCounts
を使用しています。YCbCrSubsampling
、YCbCrPositioning
、およびReferenceBlackWhite
を指定します。圧縮タイプがJPEGで、色空間がグレースケールの場合。JPEGProc
、JPEGInterchangeFormat
、JPEGInterchangeFormatLength
、JPEGRestartInterval
、JPEGLosslessPredictors
、JPEGPointTransforms
、JPEGQTables
、JPEGDCTables
、およびJPEGACTables
です。提供されたメタデータに存在する他のフィールドは解釈されず、提供されたものとして書き込まれます。
Exifイメージが書き込まれている場合、存在するフィールドのセットとその値は、結果がExif 2.2仕様と一致するように変更されます。
TIFFストリームに書き込むためのイメージ・メタデータの設定は、TIFF IFDを表すTIFFDirectory
クラスを使用することで簡略化できます。 TIFF IFD内のフィールドは、TIFFFieldのインスタンスで表されます。 書き込まれる各フィールドに対して、TIFFField
をTIFFDirectory
に追加し、後者をTIFFDirectory.getAsMetadata
を呼び出してIIOMetadata
オブジェクトに変換することができます。 こうして得られたIIOMetadata
オブジェクトは、TIFFライターに渡されます。
TIFFフィールド | 標準メタデータ要素からの派生 |
---|---|
PhotometricInterpretation | /Chroma/ColorSpaceType@name: "GRAY"と/Chroma/BlackIsZero@value = "FALSE" => WhiteIsZero; "GRAY"および/Document/SubimageInterpretation@value = "TransparencyMask" => TransparencyMask; "RGB"と/Chroma/Palette present => PaletteColor; "GRAY" => BlackIsZero; "RGB" => RGB; "YCbCr" => YCbCr; "CMYK" => CMYK; "Lab" => CIELab。 |
SamplesPerPixel | /Chroma/NumChannels@value |
ColorMap | /Chroma/Palette |
Compression | /Compression/CompressionTypeName@value: "none" =>非圧縮; "CCITT RLE" => CCITT 1D; "CCITT T.4" =>グループ3ファックス; "CCITT T.6" =>グループ4ファックス; "LZW" => LZW; "Old JPEG" => JPEG; "JPEG" =>新JPEG; "ZLib" => ZLib; "PackBits" => PackBits; "Deflate" =>デフレート。 |
PlanarConfiguration | /Data/PlanarConfiguration@value: "PixelInterleaved" => Chunky; "PlaneInterleaved" => Planar。 |
SampleFormat | /Data/SampleFormat@value: "SignedIntegral" => 2つの補数符号付き整数データ。"UnsignedIntegral" =>符号なし整数データ。"Real" => IEEE浮動小数点データ。"Index" =>符号なし整数データ。 |
BitsPerSample | /Data/BitsPerSample@value: char配列に解析されたスペース区切りのリスト。 |
FillOrder | /Data/SampleMSB@value: スペースで区切られたリストのすべての値が0s =>右から左;そうでなければ=>左から右。 |
XResolution | (10 / /Dimension/HorizontalPixelSize@value)または(10 / (/Dimension/VerticalPixelSize@value * /Dimension/PixelAspectRatio@value)) |
YResolution | (10 / /Dimension/VerticalPixelSize@value)または(10 / (/Dimension/HorizontalPixelSize@value / /Dimension/PixelAspectRatio@value)) |
ResolutionUnit | XResolutionまたはYResolutionが設定されている場合はセンチメートル。それ以外はNone。 |
Orientation | /Dimension/ImageOrientation@value |
XPosition | /Dimension/HorizontalPosition@value / 10 |
YPosition | /Dimension/VerticalPosition@value / 10 |
NewSubFileType | /Document/SubimageInterpretation@value: "TransparencyMask" =>透過マスク。"ReducedResolution" =>解像度の低下。"SinglePage" =>シングル・ページ。 |
DateTime | /Document/ImageCreationTime@value |
DocumentName, ImageDescription, Make, Model, PageName, Software, Artist, HostComputer, InkNames, Copyright | /Text/TextEntry: /Text/TextEntry@keywordは、TIFFフィールドのいずれかの名前です(例:"ソフトウェア")。このフィールドは、content /Text/TextEntry@valueとcount 1で追加されます。 |
ExtraSamples | /Transparency/Alpha@value: "premultiplied" =>関連付けられたアルファ、カウント1; "nonpremultiplied" =>関連付けられていないアルファ、カウント1。 |
APP1
マーカー・セグメントの内容を書き込むことができます。
ImageWriter tiffWriter;
ImageWriteParam tiffWriteParam;
IIOMetadata tiffStreamMetadata;
IIOMetadata primaryIFD;
BufferedImage image;
BufferedImage thumbnail;
// Specify uncompressed output.
tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
if (thumbnail != null) {
// Write the TIFF header.
tiffWriter.prepareWriteSequence(tiffStreamMetadata);
// Append the primary IFD.
tiffWriter.prepareInsertEmpty(-1, // append
new ImageTypeSpecifier(image),
image.getWidth(),
image.getHeight(),
primaryIFD,
null, // thumbnails
tiffWriteParam);
tiffWriter.endInsertEmpty();
// Append the thumbnail image data.
tiffWriter.writeToSequence(new IIOImage(thumbnail, null, null),
tiffWriteParam);
// Insert the primary image data.
tiffWriter.prepareReplacePixels(0, new Rectangle(image.getWidth(),
image.getHeight()));
tiffWriter.replacePixels(image, tiffWriteParam);
tiffWriter.endReplacePixels();
// End writing.
tiffWriter.endWriteSequence();
} else {
// Write only the primary IFD and image data.
tiffWriter.write(tiffStreamMetadata,
new IIOImage(image, null, primaryIFD),
tiffWriteParam);
}
APP1
セグメント内の埋め込みTIFFストリームの構造は、1次イメージ・データが存在しないことを除いて、「非圧縮Exifイメージ構造」と同じです。つまり、1次IFDはイメージ・データを参照しません。
ImageWriter tiffWriter;
ImageWriteParam tiffWriteParam;
IIOMetadata tiffStreamMetadata;
BufferedImage image;
BufferedImage thumbnail;
IIOMetadata primaryIFD;
ImageOutputStream output;
// Set up an output to contain the APP1 Exif TIFF stream.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
MemoryCacheImageOutputStream app1ExifOutput =
new MemoryCacheImageOutputStream(baos);
tiffWriter.setOutput(app1ExifOutput);
// Set compression for the thumbnail.
tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
tiffWriteParam.setCompressionType("Exif JPEG");
// Write the APP1 Exif TIFF stream.
if (thumbnail != null) {
// Write the TIFF header.
tiffWriter.prepareWriteSequence(tiffStreamMetadata);
// Append the primary IFD.
tiffWriter.prepareInsertEmpty(-1, // append
new ImageTypeSpecifier(image),
image.getWidth(),
image.getHeight(),
primaryIFD,
null, // thumbnails
tiffWriteParam);
tiffWriter.endInsertEmpty();
// Append the thumbnail IFD and image data.
tiffWriter.writeToSequence(new IIOImage(thumbnail, null,
null), tiffWriteParam);
// End writing.
tiffWriter.endWriteSequence();
} else {
// Write only the primary IFD.
tiffWriter.prepareWriteEmpty(tiffStreamMetadata,
new ImageTypeSpecifier(image),
image.getWidth(),
image.getHeight(),
primaryIFD,
null, // thumbnails
tiffWriteParam);
tiffWriter.endWriteEmpty();
}
// Flush data into byte stream.
app1ExifOutput.flush();
// Create APP1 parameter array.
byte[] app1Parameters = new byte[6 + baos.size()];
// Add APP1 Exif ID bytes.
app1Parameters[0] = (byte) 'E';
app1Parameters[1] = (byte) 'x';
app1Parameters[2] = (byte) 'i';
app1Parameters[3] = (byte) 'f';
app1Parameters[4] = app1Parameters[5] = (byte) 0;
// Append TIFF stream to APP1 parameters.
System.arraycopy(baos.toByteArray(), 0, app1Parameters, 6, baos.size());
// Create the APP1 Exif node to be added to native JPEG image metadata.
IIOMetadataNode app1Node = new IIOMetadataNode("unknown");
app1Node.setAttribute("MarkerTag", String.valueOf(0xE1));
app1Node.setUserObject(app1Parameters);
// Append the APP1 Exif marker to the "markerSequence" node.
IIOMetadata jpegImageMetadata =
jpegWriter.getDefaultImageMetadata(new ImageTypeSpecifier(image),
jpegWriteParam);
String nativeFormat = jpegImageMetadata.getNativeMetadataFormatName();
Node tree = jpegImageMetadata.getAsTree(nativeFormat);
NodeList children = tree.getChildNodes();
int numChildren = children.getLength();
for (int i = 0; i < numChildren; i++) {
Node child = children.item(i);
if (child.getNodeName().equals("markerSequence")) {
child.appendChild(app1Node);
break;
}
}
jpegImageMetadata.setFromTree(nativeFormat, tree);
// Write the JPEG image data including the APP1 Exif marker.
jpegWriter.setOutput(output);
jpegWriter.write(new IIOImage(image, null, jpegImageMetadata));
上記で作成された"unknown"
ノードは、ネイティブJPEGイメージ・メタデータの"markerSequence"
ノードに追加され、プライマリ・イメージがJPEGライターを使用して書き込まれるときにJPEGストリームに書き込まれます。
<!DOCTYPE "javax_imageio_tiff_stream_1.0" [ <!ELEMENT "javax_imageio_tiff_stream_1.0" (ByteOrder)> <!ELEMENT "ByteOrder" EMPTY> <!-- The stream byte order --> <!ATTLIST "ByteOrder" "value" #CDATA #REQUIRED> <!-- One of "BIG_ENDIAN" or "LITTLE_ENDIAN" --> <!-- Data type: String --> ]>
<!DOCTYPE "javax_imageio_tiff_image_1.0" [ <!ELEMENT "javax_imageio_tiff_image_1.0" (TIFFIFD)*> <!ELEMENT "TIFFIFD" (TIFFField | TIFFIFD)*> <!-- An IFD (directory) containing fields --> <!ATTLIST "TIFFIFD" "tagSets" #CDATA #REQUIRED> <!-- Data type: String --> <!ATTLIST "TIFFIFD" "parentTagNumber" #CDATA #IMPLIED> <!-- The tag number of the field pointing to this IFD --> <!-- Data type: Integer --> <!ATTLIST "TIFFIFD" "parentTagName" #CDATA #IMPLIED> <!-- A mnemonic name for the field pointing to this IFD, if known --> <!-- Data type: String --> <!ELEMENT "TIFFField" (TIFFBytes | TIFFAsciis | TIFFShorts | TIFFSShorts | TIFFLongs | TIFFSLongs | TIFFRationals | TIFFSRationals | TIFFFloats | TIFFDoubles | TIFFUndefined)> <!-- A field containing data --> <!ATTLIST "TIFFField" "number" #CDATA #REQUIRED> <!-- The tag number asociated with the field --> <!-- Data type: String --> <!ATTLIST "TIFFField" "name" #CDATA #IMPLIED> <!-- A mnemonic name associated with the field, if known --> <!-- Data type: String --> <!ELEMENT "TIFFBytes" (TIFFByte)*> <!-- A sequence of TIFFByte nodes --> <!ELEMENT "TIFFByte" EMPTY> <!-- An integral value between 0 and 255 --> <!ATTLIST "TIFFByte" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFByte" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFAsciis" (TIFFAscii)*> <!-- A sequence of TIFFAscii nodes --> <!ELEMENT "TIFFAscii" EMPTY> <!-- A String value --> <!ATTLIST "TIFFAscii" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ELEMENT "TIFFShorts" (TIFFShort)*> <!-- A sequence of TIFFShort nodes --> <!ELEMENT "TIFFShort" EMPTY> <!-- An integral value between 0 and 65535 --> <!ATTLIST "TIFFShort" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFShort" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFSShorts" (TIFFSShort)*> <!-- A sequence of TIFFSShort nodes --> <!ELEMENT "TIFFSShort" EMPTY> <!-- An integral value between -32768 and 32767 --> <!ATTLIST "TIFFSShort" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFSShort" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFLongs" (TIFFLong)*> <!-- A sequence of TIFFLong nodes --> <!ELEMENT "TIFFLong" EMPTY> <!-- An integral value between 0 and 4294967295 --> <!ATTLIST "TIFFLong" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFLong" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFSLongs" (TIFFSLong)*> <!-- A sequence of TIFFSLong nodes --> <!ELEMENT "TIFFSLong" EMPTY> <!-- An integral value between -2147483648 and 2147482647 --> <!ATTLIST "TIFFSLong" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ATTLIST "TIFFSLong" "description" #CDATA #IMPLIED> <!-- A description, if available --> <!-- Data type: String --> <!ELEMENT "TIFFRationals" (TIFFRational)*> <!-- A sequence of TIFFRational nodes --> <!ELEMENT "TIFFRational" EMPTY> <!-- A rational value consisting of an unsigned numerator and denominator --> <!ATTLIST "TIFFRational" "value" #CDATA #IMPLIED> <!-- The numerator and denominator, separated by a slash --> <!-- Data type: String --> <!ELEMENT "TIFFSRationals" (TIFFSRational)*> <!-- A sequence of TIFFSRational nodes --> <!ELEMENT "TIFFSRational" EMPTY> <!-- A rational value consisting of a signed numerator and denominator --> <!ATTLIST "TIFFSRational" "value" #CDATA #IMPLIED> <!-- The numerator and denominator, separated by a slash --> <!-- Data type: String --> <!ELEMENT "TIFFFloats" (TIFFFloat)*> <!-- A sequence of TIFFFloat nodes --> <!ELEMENT "TIFFFloat" EMPTY> <!-- A single-precision floating-point value --> <!ATTLIST "TIFFFloat" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ELEMENT "TIFFDoubles" (TIFFDouble)*> <!-- A sequence of TIFFDouble nodes --> <!ELEMENT "TIFFDouble" EMPTY> <!-- A double-precision floating-point value --> <!ATTLIST "TIFFDouble" "value" #CDATA #IMPLIED> <!-- The value --> <!-- Data type: String --> <!ELEMENT "TIFFUndefined" EMPTY> <!-- Uninterpreted byte data --> <!ATTLIST "TIFFUndefined" "value" #CDATA #IMPLIED> <!-- A list of comma-separated byte values --> <!-- Data type: String --> ]>
バグを報告する、または機能強化を提案する
さらにAPIリファレンスと開発者ドキュメントについては、概念的な概要、用語の定義、回避策、および作業コードの例など、より詳細な開発者向けの説明が含まれている「Java SEドキュメンテーション」を参照してください。
Javaは、米国およびその他の国におけるOracleおよび/またはその関連会社の商標または登録商標です。
Copyright © 1993, 2018, Oracle and/or its affiliates, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
All rights reserved. 使用は「ライセンス条項」と「ドキュメンテーション再配布ポリシー」に従います。