使用 Commons Imaging 的多条到单条 tiff
Multistrip to single strip tiff using Commons Imaging
我正在尝试将多条带 Tiff 图像转换为单条带 tiff。我能够使用来自 Java 的 JAI API 来做到这一点。但这些都不是独立于平台的。
我现在正在与 Commons Imaging 合作来执行此任务。在这里我无法找到如何准确地写回单条图像数据。
这是我到目前为止编写的代码片段。 (请注意这只是一个粗略的例子,我会在获得单条之前修改代码)
//get the metadata out a tiff file
final IImageMetadata metadata = Imaging.getMetadata(file);
iffImageMetadata tiffMetadata = null;
if(metadata instanceof TiffImageMetadata){
tiffMetadata = (TiffImageMetadata) metadata;
TiffImageMetadata.Directory dir = (TiffImageMetadata.Directory)tiffMetadata.getDirectories().get(0);
TiffImageData imgData = dir.getTiffImageData();
long offset = 0;
//check number of strips(can be done by getting TIFF TAG 273
DataElement[] imgDataElements = imgData.getImageData();
int noOfSTrips = imgDataElements.length;
if(noOfSTrips == 1){
return; //already a single strip
}
//merge all single strips to a single byte array
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
for(int i = 0; i< noOfSTrips; i++){
ByteSourceData data = (ByteSourceData) imgDataElements[i];
outputStream.write(data.getData());
}
List<TiffField> tiffFields = tiffMetadata.getAllFields();
TiffOutputField outputField = null;
for(TiffField tiffField : tiffFields){
String type = tiffField.getFieldTypeName();
switch(tiffField.getTag()) {
case 273:
if (type == FieldType.LONG.getName())
{
if (tiffField.getCount() > 1){
//this will be writen back to the output set
outputField = new TiffOutputField(tiffField.getTagInfo(), tiffField.getFieldType(), 1, outputStream.toByteArray());
offset = tiffField.getByteArrayValue()[0];
}
}
break;
}
}
TiffOutputSet outputSet = tiffMetadata.getOutputSet();
List<TiffOutputDirectory> outputDirectories = outputSet.getDirectories();
TiffOutputDirectory outputDir = outputDirectories.get(0);
outputDir.removeField(273);
outputDir.add(outputField);
//NOW WHAT TO DO??
//I HAVE SEEN ExifRewritter CLASS THAT CAN UPDATE TIFF WITH EXIF, BUT HOW I CAN UPDATE THIS BACK
}
任何指点都会有所帮助。
所以我终于能够将多条 tif 图像转换为单条。
基本上我从 Commons Imaging 的 TiffImageWriterBase
class 复制了一些代码,这是因为 rowsPerStrip
的计算方式使得结果图像始终是多条带。 .我已修改此代码以设置 rowsPerStrip = image.height
。
这是我写的代码:
//source is any multistrip image
File file = new File("D:\Tiff\image.tif");
BufferedImage src = Imaging.getBufferedImage(file);
OutputStream os = new FileOutputStream(new File("D:\Tiff\modified_image.tif"));
os = new BufferedOutputStream(os);
final int width = src.getWidth();
final int height = src.getHeight();
//These are set as per CCITT 4 compression, you can modify these as per requirement
int samplesPerPixel = 1;
int bitsPerSample = 1;
int photometricInterpretation =0;
//setting rowsPerStrip equal to heigh of the image, this did the trick for me
int rowsPerStrip = height;//This code was present originally -> stripSizeInBits / (1 * bitsPerSample * samplesPerPixel);
rowsPerStrip = Math.max(1, rowsPerStrip); // must have at least one.
//you can copy getStrips method from TiffImageWriterBase class or work upon yours own
final byte[][] strips = getStrips(src, samplesPerPixel, bitsPerSample, rowsPerStrip);
for (int i = 0; i < strips.length; i++) {
strips[i] = T4AndT6Compression.compressT6(strips[i], width,
strips[i].length / ((width + 7) / 8));
}
final TiffElement.DataElement[] imageData = new TiffElement.DataElement[strips.length];
for (int i = 0; i < strips.length; i++) {
imageData[i] = new TiffImageData.Data(0, strips[i].length, strips[i]);
}
final TiffOutputSet outputSet = new TiffOutputSet(ByteOrder.LITTLE_ENDIAN);
final TiffOutputDirectory directory = outputSet.addRootDirectory();
directory.add(TiffTagConstants.TIFF_TAG_IMAGE_WIDTH, width);
directory.add(TiffTagConstants.TIFF_TAG_IMAGE_LENGTH, height);
directory.add(TiffTagConstants.TIFF_TAG_PHOTOMETRIC_INTERPRETATION,
(short) photometricInterpretation);
directory.add(TiffTagConstants.TIFF_TAG_COMPRESSION,
(short) TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_4);
directory.add(TiffTagConstants.TIFF_TAG_SAMPLES_PER_PIXEL,
(short) samplesPerPixel);
directory.add(TiffTagConstants.TIFF_TAG_BITS_PER_SAMPLE,
(short) bitsPerSample);
directory.add(TiffTagConstants.TIFF_TAG_ROWS_PER_STRIP,
rowsPerStrip);
directory.add(TiffTagConstants.TIFF_TAG_RESOLUTION_UNIT,
(short) 2);
PixelDensity pixelDensity = PixelDensity.createFromPixelsPerInch(72, 72);
directory.add(TiffTagConstants.TIFF_TAG_XRESOLUTION,
RationalNumber.valueOf(pixelDensity.horizontalDensityInches()));
directory.add(TiffTagConstants.TIFF_TAG_YRESOLUTION,
RationalNumber.valueOf(pixelDensity.verticalDensityInches()));
final TiffImageData tiffImageData = new TiffImageData.Strips(imageData,
rowsPerStrip);
directory.setTiffImageData(tiffImageData);
//single strip image will be written to output stream
new TiffImageWriterLossy().write(os, outputSet);
我正在尝试将多条带 Tiff 图像转换为单条带 tiff。我能够使用来自 Java 的 JAI API 来做到这一点。但这些都不是独立于平台的。 我现在正在与 Commons Imaging 合作来执行此任务。在这里我无法找到如何准确地写回单条图像数据。
这是我到目前为止编写的代码片段。 (请注意这只是一个粗略的例子,我会在获得单条之前修改代码)
//get the metadata out a tiff file
final IImageMetadata metadata = Imaging.getMetadata(file);
iffImageMetadata tiffMetadata = null;
if(metadata instanceof TiffImageMetadata){
tiffMetadata = (TiffImageMetadata) metadata;
TiffImageMetadata.Directory dir = (TiffImageMetadata.Directory)tiffMetadata.getDirectories().get(0);
TiffImageData imgData = dir.getTiffImageData();
long offset = 0;
//check number of strips(can be done by getting TIFF TAG 273
DataElement[] imgDataElements = imgData.getImageData();
int noOfSTrips = imgDataElements.length;
if(noOfSTrips == 1){
return; //already a single strip
}
//merge all single strips to a single byte array
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
for(int i = 0; i< noOfSTrips; i++){
ByteSourceData data = (ByteSourceData) imgDataElements[i];
outputStream.write(data.getData());
}
List<TiffField> tiffFields = tiffMetadata.getAllFields();
TiffOutputField outputField = null;
for(TiffField tiffField : tiffFields){
String type = tiffField.getFieldTypeName();
switch(tiffField.getTag()) {
case 273:
if (type == FieldType.LONG.getName())
{
if (tiffField.getCount() > 1){
//this will be writen back to the output set
outputField = new TiffOutputField(tiffField.getTagInfo(), tiffField.getFieldType(), 1, outputStream.toByteArray());
offset = tiffField.getByteArrayValue()[0];
}
}
break;
}
}
TiffOutputSet outputSet = tiffMetadata.getOutputSet();
List<TiffOutputDirectory> outputDirectories = outputSet.getDirectories();
TiffOutputDirectory outputDir = outputDirectories.get(0);
outputDir.removeField(273);
outputDir.add(outputField);
//NOW WHAT TO DO??
//I HAVE SEEN ExifRewritter CLASS THAT CAN UPDATE TIFF WITH EXIF, BUT HOW I CAN UPDATE THIS BACK
}
任何指点都会有所帮助。
所以我终于能够将多条 tif 图像转换为单条。
基本上我从 Commons Imaging 的 TiffImageWriterBase
class 复制了一些代码,这是因为 rowsPerStrip
的计算方式使得结果图像始终是多条带。 .我已修改此代码以设置 rowsPerStrip = image.height
。
这是我写的代码:
//source is any multistrip image
File file = new File("D:\Tiff\image.tif");
BufferedImage src = Imaging.getBufferedImage(file);
OutputStream os = new FileOutputStream(new File("D:\Tiff\modified_image.tif"));
os = new BufferedOutputStream(os);
final int width = src.getWidth();
final int height = src.getHeight();
//These are set as per CCITT 4 compression, you can modify these as per requirement
int samplesPerPixel = 1;
int bitsPerSample = 1;
int photometricInterpretation =0;
//setting rowsPerStrip equal to heigh of the image, this did the trick for me
int rowsPerStrip = height;//This code was present originally -> stripSizeInBits / (1 * bitsPerSample * samplesPerPixel);
rowsPerStrip = Math.max(1, rowsPerStrip); // must have at least one.
//you can copy getStrips method from TiffImageWriterBase class or work upon yours own
final byte[][] strips = getStrips(src, samplesPerPixel, bitsPerSample, rowsPerStrip);
for (int i = 0; i < strips.length; i++) {
strips[i] = T4AndT6Compression.compressT6(strips[i], width,
strips[i].length / ((width + 7) / 8));
}
final TiffElement.DataElement[] imageData = new TiffElement.DataElement[strips.length];
for (int i = 0; i < strips.length; i++) {
imageData[i] = new TiffImageData.Data(0, strips[i].length, strips[i]);
}
final TiffOutputSet outputSet = new TiffOutputSet(ByteOrder.LITTLE_ENDIAN);
final TiffOutputDirectory directory = outputSet.addRootDirectory();
directory.add(TiffTagConstants.TIFF_TAG_IMAGE_WIDTH, width);
directory.add(TiffTagConstants.TIFF_TAG_IMAGE_LENGTH, height);
directory.add(TiffTagConstants.TIFF_TAG_PHOTOMETRIC_INTERPRETATION,
(short) photometricInterpretation);
directory.add(TiffTagConstants.TIFF_TAG_COMPRESSION,
(short) TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_4);
directory.add(TiffTagConstants.TIFF_TAG_SAMPLES_PER_PIXEL,
(short) samplesPerPixel);
directory.add(TiffTagConstants.TIFF_TAG_BITS_PER_SAMPLE,
(short) bitsPerSample);
directory.add(TiffTagConstants.TIFF_TAG_ROWS_PER_STRIP,
rowsPerStrip);
directory.add(TiffTagConstants.TIFF_TAG_RESOLUTION_UNIT,
(short) 2);
PixelDensity pixelDensity = PixelDensity.createFromPixelsPerInch(72, 72);
directory.add(TiffTagConstants.TIFF_TAG_XRESOLUTION,
RationalNumber.valueOf(pixelDensity.horizontalDensityInches()));
directory.add(TiffTagConstants.TIFF_TAG_YRESOLUTION,
RationalNumber.valueOf(pixelDensity.verticalDensityInches()));
final TiffImageData tiffImageData = new TiffImageData.Strips(imageData,
rowsPerStrip);
directory.setTiffImageData(tiffImageData);
//single strip image will be written to output stream
new TiffImageWriterLossy().write(os, outputSet);