使用 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);