编程语言
首页 > 编程语言> > 需要帮助开始通过Java将原始G3传真文件转换为TIFF格式

需要帮助开始通过Java将原始G3传真文件转换为TIFF格式

作者:互联网

我有一个原始传真文件(G3 / T.4格式),需要通过Java以编程方式将其转换为多页TIFF.到目前为止JAI还没有成功,即使我认为它应该有效.来自sFaxTools的工具已成功将我的原始传真文件转换为TIFF(Batch Fax2Tif或Faxsee),但我需要通过Java以编程方式执行此操作.我认为应该有使用java高级成像的可能性,请查看下面的代码片段:

 private void writeTiff(byte[] buffer, OutputStream outStream) {
    try {
         //reading image from given buffer
         RenderedImage rendImage = null;
         TIFFDecodeParam decodeParams = new TIFFDecodeParam();
         ByteArrayInputStream stream = new ByteArrayInputStream(buffer);
         ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", stream, decodeParams);
         TIFFEncodeParam encodeParams = new TIFFEncodeParam();
         int numPages = decoder.getNumPages();
         for (int i = 0; i < numPages; i++) {
            rendImage = decoder.decodeAsRenderedImage(i);
            ImageEncoder encoder = ImageCodec.createImageEncoder("TIFF", outStream, encodeParams);
            encoder.encode(rendImage);
         }
    } catch (Exception e) {
        e.printStackTrace();
    } catch (Error err) {
        err.printStackTrace();
    }
}

问题是,特别是阅读部分
  ImageDecoder decoder = ImageCodec.createImageDecoder(“tiff”,stream,decodeParams);
应该被一些ImageDecoder实现取代,该实现在内部使用FaxDecoder来解码g3原始传真文件.在jai包中有一个受保护的类TIFFFaxDecoder,是否有可能以及如何将此用于我的目的?任何的想法?
谢谢

解决方法:

我认为JAI不支持直接读取G3 / T.4原始传真数据.但是,这里的示例代码可以修改和扩展以满足您的需求,实现评论中概述的想法(最初发布为Gist).

它不以任何方式解码G3 / T.4数据,它只是将原始传真数据包装在最小的TIFF容器中.这允许稍后将数据读取为正常TIFF.它使用(我自己的)TwelveMonkeys ImageIO库来实现.

如果您不知道传真文件的宽度/高度,您可以通过使用CCITTFaxDecoderStream,尝试标准中定义的不同宽度(列)来实现算法来查找它们,并查看有多少整行你可以阅读.如果你有正确的数字,你应该完全消耗流.

import com.twelvemonkeys.imageio.metadata.AbstractEntry;
import com.twelvemonkeys.imageio.metadata.Entry;
import com.twelvemonkeys.imageio.metadata.exif.EXIFWriter;
import com.twelvemonkeys.imageio.metadata.exif.Rational;
import com.twelvemonkeys.imageio.metadata.exif.TIFF;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.io.*;
import java.util.ArrayList;

public class G3Test {
    public static void main(String[] args) throws IOException {
        File input = new File(args[0]);
        File output = new File(args.length > 1 ? args[1] : input.getName().replace(".g3", ".tif"));

        // ImageWidth = 1728, 2048, 2482. SHORT or LONG. These are the fixed page widths in pixels defined in CCITT Group 3.
        int columns = 1728; // The default
        int rows = 100;     // Trial and error for sample file found at http://www.filesuffix.com/en/extension/fax

        ArrayList<Entry> entries = new ArrayList<>();

        // http://cool.conservation-us.org/bytopic/imaging/std/tiff-f.html
        // Required Class F tags
        entries.add(new TIFFEntry(TIFF.TAG_COMPRESSION, TIFF.TYPE_SHORT, 3)); // CCITT T.4
        entries.add(new TIFFEntry(TIFF.TAG_FILL_ORDER, TIFF.TYPE_SHORT, 1));  // Left to right
        entries.add(new TIFFEntry(TIFF.TAG_GROUP3OPTIONS, TIFF.TYPE_LONG, 0)); // No options set
        entries.add(new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, TIFF.TYPE_LONG, columns));
        entries.add(new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, TIFF.TYPE_LONG, rows));
        entries.add(new TIFFEntry(TIFF.TAG_SUBFILE_TYPE, TIFF.TYPE_LONG, 2)); // Page
        entries.add(new TIFFEntry(TIFF.TAG_RESOLUTION_UNIT, TIFF.TYPE_SHORT, 2)); // Inches
        entries.add(new TIFFEntry(TIFF.TAG_X_RESOLUTION, TIFF.TYPE_RATIONAL, new Rational(204))); // 204
        entries.add(new TIFFEntry(TIFF.TAG_Y_RESOLUTION, TIFF.TYPE_RATIONAL, new Rational(98))); // 98, 196
        // Required Bilevel (Class B) tags
        entries.add(new TIFFEntry(TIFF.TAG_BITS_PER_SAMPLE, TIFF.TYPE_SHORT, 1)); // 1 bit/sample
        entries.add(new TIFFEntry(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, TIFF.TYPE_SHORT, 0)); // White is zero
        entries.add(new TIFFEntry(TIFF.TAG_SOFTWARE, TIFF.TYPE_ASCII, "TwelveMonkeys FAX2TIFF 0.1 BETA ;-)"));
        entries.add(new TIFFEntry(TIFF.TAG_ROWS_PER_STRIP, TIFF.TYPE_LONG, rows));
        entries.add(new TIFFEntry(TIFF.TAG_SAMPLES_PER_PIXEL, TIFF.TYPE_SHORT, 1)); // 1 sample/pixel
        entries.add(new TIFFEntry(TIFF.TAG_STRIP_BYTE_COUNTS, TIFF.TYPE_LONG, input.length()));
        entries.add(new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, TIFF.TYPE_LONG, -1)); // placeholder for now

        // We now have all our entries, compute size of the entries, and make that the offset (we'll write the data right after).
        EXIFWriter writer = new EXIFWriter();
        long offset = 12 + writer.computeIFDSize(entries); // + 12 for TIFF magic (4), IFD0 pointer (4) and EOF (4)
        entries.remove(entries.size() - 1);
        entries.add(new TIFFEntry(TIFF.TAG_STRIP_OFFSETS, TIFF.TYPE_LONG, offset));


        try (InputStream in = new FileInputStream(input)) {
            try (ImageOutputStream out = ImageIO.createImageOutputStream(output)) {
                // Write the TIFF IFD for the image data
                writer.write(entries, out);

                // Copy the already G3 compressed bytes verbatim to the output
                byte[] buffer = new byte[1024];
                int read;
                while ((read = in.read(buffer)) >= 0) {
                    out.write(buffer, 0, read);
                }
            }
        }
    }

    // API stupidity, should be fixed in later verisons (ie. contain a predefined TIFFEntry class)
    static final class TIFFEntry extends AbstractEntry {
        private final short type;

        TIFFEntry(int identifier, short type, Object value) {
            super(identifier, value);
            this.type = type;
        }

        @Override
        public String getTypeName() {
            return TIFF.TYPE_NAMES[type];
        }
    }
}

标签:java,tiff,fax,jai
来源: https://codeday.me/bug/20190711/1432933.html