By Date: <-- -->
By Thread: <-- -->

iText ~ Multipage TIFF ~ OldJPEG / JPEG



Title: iText ~ Multipage TIFF ~ OldJPEG / JPEG

Hello,

yesterday i send a question about following problem with iText using multipage tiff:

- multipage tiff with no compression:        works well
- multipage tiff with lzw compression:       works well
- multipage tiff with packbits compression:  works well
- multipage tiff with zip compression:       works well
- multipage tiff with jpeg compression:      dont works (skipped by the getTiffImage() method)
- multipage tiff with old jpeg:              dont works

JPEG:      have no idea how to fix it, because there are no usable tag values. do you have some advice for me? thanks in advance!

OldJPEG:   i clould fix the problem by changing in TiffImage.getTiffImageColor() as follows:

    protected static Image getTiffImageColor(TIFFDirectory dir, RandomAccessFileOrArray s) {
        try {
            int compression = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_COMPRESSION);
            int predictor = 1;
            TIFFLZWDecoder lzwDecoder = null;
            switch (compression) {
                case TIFFConstants.COMPRESSION_NONE:
                case TIFFConstants.COMPRESSION_LZW:
                case TIFFConstants.COMPRESSION_PACKBITS:
                case TIFFConstants.COMPRESSION_DEFLATE:
                case TIFFConstants.COMPRESSION_OJPEG:
                    break;
                default:
                    throw new IllegalArgumentException("The compression " + compression + " is not supported.");
            }
            int photometric = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_PHOTOMETRIC);
            switch (photometric) {
                case TIFFConstants.PHOTOMETRIC_MINISWHITE:
                case TIFFConstants.PHOTOMETRIC_MINISBLACK:
                case TIFFConstants.PHOTOMETRIC_RGB:
                case TIFFConstants.PHOTOMETRIC_SEPARATED:
                case TIFFConstants.PHOTOMETRIC_PALETTE:
                    break;
                default:
                    throw new IllegalArgumentException("The photometric " + photometric + " is not supported.");
            }
            float rotation = 0;
            if (dir.isTagPresent(TIFFConstants.TIFFTAG_ORIENTATION)) {
                int rot = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_ORIENTATION);
                if (rot == TIFFConstants.ORIENTATION_BOTRIGHT || rot == TIFFConstants.ORIENTATION_BOTLEFT)
                    rotation = (float)Math.PI;
                else if (rot == TIFFConstants.ORIENTATION_LEFTTOP || rot == TIFFConstants.ORIENTATION_LEFTBOT)
                    rotation = (float)(Math.PI / 2.0);
                else if (rot == TIFFConstants.ORIENTATION_RIGHTTOP || rot == TIFFConstants.ORIENTATION_RIGHTBOT)
                    rotation = -(float)(Math.PI / 2.0);
            }
            if (dir.isTagPresent(TIFFConstants.TIFFTAG_PLANARCONFIG)
                && dir.getFieldAsLong(TIFFConstants.TIFFTAG_PLANARCONFIG) == TIFFConstants.PLANARCONFIG_SEPARATE)
                throw new IllegalArgumentException("Planar images are not supported.");
            if (dir.isTagPresent(TIFFConstants.TIFFTAG_EXTRASAMPLES))
                throw new IllegalArgumentException("Extra samples are not supported.");
            int samplePerPixel = 1;
            if (dir.isTagPresent(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL)) // 1,3,4
                samplePerPixel = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL);
            int bitsPerSample = 1;
            if (dir.isTagPresent(TIFFConstants.TIFFTAG_BITSPERSAMPLE))
                bitsPerSample = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_BITSPERSAMPLE);
            switch (bitsPerSample) {
                case 1:
                case 2:
                case 4:
                case 8:
                    break;
                default:
                    throw new IllegalArgumentException("Bits per sample " + bitsPerSample + " is not supported.");
            }
            Image img = null;

            int h = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGELENGTH);
            int w = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGEWIDTH);
            int dpiX = 0;
            int dpiY = 0;
            int resolutionUnit = TIFFConstants.RESUNIT_INCH;
            if (dir.isTagPresent(TIFFConstants.TIFFTAG_RESOLUTIONUNIT))
                resolutionUnit = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_RESOLUTIONUNIT);
            dpiX = getDpi(dir.getField(TIFFConstants.TIFFTAG_XRESOLUTION), resolutionUnit);
            dpiY = getDpi(dir.getField(TIFFConstants.TIFFTAG_YRESOLUTION), resolutionUnit);
            int rowsStrip = h;
            if (dir.isTagPresent(TIFFConstants.TIFFTAG_ROWSPERSTRIP)) //another hack for broken tiffs
                rowsStrip = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_ROWSPERSTRIP);
            long offset[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPOFFSETS);
            long size[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPBYTECOUNTS);
            if (size == null && h == rowsStrip) { // some TIFF producers are really lousy, so...
                size = new long[]{s.length() - (int)offset[0]};
            }
            if (compression == TIFFConstants.COMPRESSION_LZW) {
                TIFFField predictorField = dir.getField(TIFFConstants.TIFFTAG_PREDICTOR);
                if (predictorField != null) {
                    predictor = predictorField.getAsInt(0);
                    if (predictor != 1 && predictor != 2) {
                        throw new RuntimeException("Illegal value for Predictor in TIFF file.");
                    }
                    if (predictor == 2 && bitsPerSample != 8) {
                        throw new RuntimeException(bitsPerSample + "-bit samples are not supported for Horizontal differencing Predictor.");

                    }
                }
                lzwDecoder = new TIFFLZWDecoder(w, predictor,
                                                samplePerPixel);
            }
            int rowsLeft = h;
            ByteArrayOutputStream stream = null;
            DeflaterOutputStream zip = null;
            CCITTG4Encoder g4 = null;
            if (bitsPerSample == 1 && samplePerPixel == 1) {
                g4 = new CCITTG4Encoder(w);
            }
            else {
                stream = new ByteArrayOutputStream();
                if (compression != TIFFConstants.COMPRESSION_OJPEG)
                    zip = new DeflaterOutputStream(stream);
            }
            for (int k = 0; k < offset.length; ++k) {
                byte im[] = new byte[(int)size[k]];
                s.seek(offset[k]);
                s.readFully(im);
                int height = Math.min(rowsStrip, rowsLeft);
                byte outBuf[] = null;
                if (compression != TIFFConstants.COMPRESSION_NONE)
                    outBuf = new byte[(w * bitsPerSample * samplePerPixel + 7) / 8 * height];
                switch (compression) {
                    case TIFFConstants.COMPRESSION_DEFLATE:
                        inflate(im, outBuf);
                        break;
                    case TIFFConstants.COMPRESSION_NONE:
                        outBuf = im;
                        break;
                    case TIFFConstants.COMPRESSION_PACKBITS:
                        decodePackbits(im,  outBuf);
                        break;
                    case TIFFConstants.COMPRESSION_LZW:
                        lzwDecoder.decode(im, outBuf, height);
                        break;
                    case TIFFConstants.COMPRESSION_OJPEG:
                                                // ********************************************
                                                // *** Deactivated - BEGIN (Eduard-Klaus Weber)
                                                //stream.write(im);
                                                // *** Deactivated - END **********************
                                                // ********************************************
                        break;
                }
                if (bitsPerSample == 1 && samplePerPixel == 1) {
                    g4.fax4Encode(outBuf, height);
                }
                else if (compression != TIFFConstants.COMPRESSION_OJPEG) {
                    zip.write(outBuf);
                }
                rowsLeft -= rowsStrip;
            }
            if (bitsPerSample == 1 && samplePerPixel == 1) {
                img = Image.getInstance(w, h, false, Image.CCITTG4,
                    photometric == TIFFConstants.PHOTOMETRIC_MINISBLACK ? Image.CCITT_BLACKIS1 : 0, g4.close());
            }
            else {
                if (compression == TIFFConstants.COMPRESSION_OJPEG) {
                                        // ********************************************************************************

                                        // Inserted - BEGIN (Eduard-Klaus Weber) ******************************************

                                        if (   (!dir.isTagPresent(TIFFConstants.TIFFTAG_JPEGIFOFFSET))
                                                || (!dir.isTagPresent(TIFFConstants.TIFFTAG_JPEGIFBYTECOUNT))
                                                || (!dir.isTagPresent(TIFFConstants.TIFFTAG_JPEGIFBYTECOUNT))) {
                                                        throw new RuntimeException("Missing tag(s) for OJPEG compression.");

                                        }
                                        int jpegOffset = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_JPEGIFOFFSET);
                                        int jpegLength = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_JPEGIFBYTECOUNT)
                                                                        +(int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_STRIPBYTECOUNTS);

                                        byte jpeg[] = new byte[jpegLength];
                                       
                                        int posFilePointer = s.getFilePointer();
                                        s.seek(jpegOffset);
                                        s.readFully(jpeg, 0, jpegLength);
                                        img = new Jpeg(jpeg);
                                        s.seek(posFilePointer);
                                        // *** Inserted - END *************************************************************

                                        // ********************************************************************************

                                        // ********************************************************************************

                                        // *** Deactivated - BEGIN (Eduard-Klaus Weber)
                                        //img = new Jpeg(stream.toByteArray());                 
                                        // *** Deactivated - END **********************************************************

                                        // ********************************************************************************

                }
                else {
                    zip.close();
                    img = Image.getInstance(w, h, samplePerPixel, bitsPerSample, stream.toByteArray());
                    img.setDeflated(true);
                }
            }
            img.setDpi(dpiX, dpiY);
            if (compression != TIFFConstants.COMPRESSION_OJPEG) {
                if (dir.isTagPresent(TIFFConstants.TIFFTAG_ICCPROFILE)) {
                    try {
                        TIFFField fd = dir.getField(TIFFConstants.TIFFTAG_ICCPROFILE);
                        ICC_Profile icc_prof = ICC_Profile.getInstance(fd.getAsBytes());
                        if (samplePerPixel == icc_prof.getNumComponents())
                            img.tagICC(icc_prof);
                    }
                    catch (Exception e) {
                        //empty
                    }
                }
                if (dir.isTagPresent(TIFFConstants.TIFFTAG_COLORMAP)) {
                    TIFFField fd = dir.getField(TIFFConstants.TIFFTAG_COLORMAP);
                    char rgb[] = fd.getAsChars();
                    byte palette[] = new byte[rgb.length];
                    int gColor = rgb.length / 3;
                    int bColor = gColor * 2;
                    for (int k = 0; k < gColor; ++k) {
                        palette[k * 3] = (byte)(rgb[k] >>> 8);
                        palette[k * 3 + 1] = (byte)(rgb[k + gColor] >>> 8);
                        palette[k * 3 + 2] = (byte)(rgb[k + bColor] >>> 8);
                    }
                    PdfArray indexed = new PdfArray();
                    indexed.add(PdfName.INDEXED);
                    indexed.add(PdfName.DEVICERGB);
                    indexed.add(new PdfNumber(gColor - 1));
                    indexed.add(new PdfString(palette));
                    PdfDictionary additional = new PdfDictionary();
                    additional.put(PdfName.COLORSPACE, indexed);
                    img.setAdditional(additional);
                }
                img.setOriginalType(Image.ORIGINAL_TIFF);
            }
            if (photometric == TIFFConstants.PHOTOMETRIC_MINISWHITE)
                img.setInverted(true);
            if (rotation != 0)
                img.setInitialRotation(rotation);
            return img;
        }
        catch (Exception e) {
            throw new ExceptionConverter(e);
        }
    }

Yours sincerely
Eduard-Klaus Weber



*******************************************************************************
Diese eMail enthaelt vertrauliche und/oder rechtlich geschuetzte Informationen.
Wenn Sie nicht der richtige Adressat sind oder diese eMail irrtuemlich erhalten
haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail.
Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail ist nicht
gestattet.

This email may contain confidential and/or privileged information.
If you are not the intended recipient (or have received this email
in error) please notify the sender immediately and destroy this e-mail.
Any unauthorized copying, disclosure or distribution of the material
in this email is strictly forbidden.
*******************************************************************************
BEGIN:VCARD
N;ENCODING=QUOTED-PRINTABLE:Weber;Eduard-Klaus;;Herr;
FN;ENCODING=QUOTED-PRINTABLE:Eduard-Klaus Weber
ORG;ENCODING=QUOTED-PRINTABLE:W&W Informatik GmbH;I1 Schaden- / Unfallversicherung Schaden, Leistung
TITLE;ENCODING=QUOTED-PRINTABLE:Mitarbeiter/in Informatik
TEL;WORK;VOICE:+49 (711) 662-1482

TEL;WORK;FAX:+49 (711) 662-681482
ADR;WORK:;RO74 217;Rotebühlstr. 74;Stuttgart (West);;70178;
ADR;POSTAL:;;70163 Stuttgart
URL;WORK:http://www.ww-informatik.de
EMAIL;PREF;INTERNET:eduard.weber@ww-informatik.de
END:VCARD
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
iText-questions mailing list
iText-questions (at) lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/itext-questions