~hjd/ubuntu/wily/xmlgraphics-commons/debian-merged

« back to all changes in this revision

Viewing changes to src/java/org/apache/xmlgraphics/image/codec/tiff/TIFFImageEncoder.java

  • Committer: Hans Joachim Desserud
  • Date: 2015-11-11 18:22:53 UTC
  • mfrom: (9.1.5 sid)
  • Revision ID: hans_joachim_desserud-20151111182253-zwi0frfm97j0wddn
  * Merge from Debian unstable.  Remaining changes:
    - d/control: Drop dependencies required for unit testing as they
      include libmockito-java which would pull maven into main, disable unit
      test execution.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 * limitations under the License.
16
16
 */
17
17
 
18
 
/* $Id: TIFFImageEncoder.java 1345683 2012-06-03 14:50:33Z gadams $ */
 
18
/* $Id: TIFFImageEncoder.java 1681698 2015-05-26 07:49:35Z ssteiner $ */
19
19
 
20
20
package org.apache.xmlgraphics.image.codec.tiff;
21
21
 
22
22
import java.awt.Rectangle;
23
 
import java.awt.color.ColorSpace;
24
23
import java.awt.image.ColorModel;
25
24
import java.awt.image.ComponentSampleModel;
26
25
import java.awt.image.DataBuffer;
36
35
import java.io.IOException;
37
36
import java.io.OutputStream;
38
37
import java.io.RandomAccessFile;
 
38
import java.io.UnsupportedEncodingException;
39
39
import java.util.ArrayList;
40
40
import java.util.Iterator;
41
41
import java.util.List;
61
61
 */
62
62
public class TIFFImageEncoder extends ImageEncoderImpl {
63
63
 
64
 
    // Image Types
65
 
    private static final int TIFF_UNSUPPORTED           = -1;
66
 
    private static final int TIFF_BILEVEL_WHITE_IS_ZERO = 0;
67
 
    private static final int TIFF_BILEVEL_BLACK_IS_ZERO = 1;
68
 
    private static final int TIFF_GRAY                  = 2;
69
 
    private static final int TIFF_PALETTE               = 3;
70
 
    private static final int TIFF_RGB                   = 4;
71
 
    private static final int TIFF_CMYK                  = 5;
72
 
    private static final int TIFF_YCBCR                 = 6;
73
 
    private static final int TIFF_CIELAB                = 7;
74
 
    private static final int TIFF_GENERIC               = 8;
75
 
 
76
 
    // Compression types
77
 
    private static final int COMP_NONE      = 1;
78
 
    private static final int COMP_JPEG_TTN2 = 7;
79
 
    private static final int COMP_PACKBITS  = 32773;
80
 
    private static final int COMP_DEFLATE   = 32946;
81
 
 
82
64
    // Incidental tags
83
65
    private static final int TIFF_JPEG_TABLES       = 347;
84
66
    private static final int TIFF_YCBCR_SUBSAMPLING = 530;
85
67
    private static final int TIFF_YCBCR_POSITIONING = 531;
86
68
    private static final int TIFF_REF_BLACK_WHITE   = 532;
87
69
 
88
 
    // ExtraSamples types
89
 
    private static final int EXTRA_SAMPLE_UNSPECIFIED        = 0;
90
 
    private static final int EXTRA_SAMPLE_ASSOCIATED_ALPHA   = 1;
91
 
    private static final int EXTRA_SAMPLE_UNASSOCIATED_ALPHA = 2;
92
70
 
93
 
    // Default values
94
 
    private static final int DEFAULT_ROWS_PER_STRIP = 8;
95
71
 
96
72
    public TIFFImageEncoder(OutputStream output, ImageEncodeParam param) {
97
73
        super(output, param);
187
163
        c.ifdOffset = encode(c.nextImage, encodeParam, c.ifdOffset, true);
188
164
    }
189
165
 
190
 
    private class Context {
 
166
    private static class Context {
191
167
        //TODO This approach causes always two images to be present at the same time.
192
168
        //The encoder has to be changed a little to avoid that.
193
169
        private RenderedImage nextImage;
197
173
    private int encode(RenderedImage im, TIFFEncodeParam encodeParam,
198
174
                       int ifdOffset, boolean isLast) throws IOException {
199
175
        // Currently all images are stored uncompressed.
200
 
        int compression = encodeParam.getCompression();
 
176
        CompressionValue compression = encodeParam.getCompression();
201
177
 
202
 
        if (compression == COMP_JPEG_TTN2) {
 
178
        if (compression == CompressionValue.JPEG_TTN2) {
203
179
            throw new IllegalArgumentException(PropertyUtil.getString("TIFFImageEncoder12"));
204
180
        }
205
181
 
214
190
 
215
191
        // Get SampleModel.
216
192
        SampleModel sampleModel = im.getSampleModel();
217
 
 
218
 
        // Retrieve and verify sample size.
 
193
        ColorModel colorModel = im.getColorModel();
219
194
        int[] sampleSize = sampleModel.getSampleSize();
220
 
        for (int i = 1; i < sampleSize.length; i++) {
221
 
            if (sampleSize[i] != sampleSize[0]) {
222
 
                throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder0"));
223
 
            }
224
 
        }
225
 
 
226
 
        // Check low bit limits.
 
195
        int dataTypeSize = sampleSize[0];
227
196
        int numBands = sampleModel.getNumBands();
228
 
        if ((sampleSize[0] == 1 || sampleSize[0] == 4) && numBands != 1) {
229
 
            throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder1"));
230
 
        }
231
 
 
232
 
        // Retrieve and verify data type.
233
197
        int dataType = sampleModel.getDataType();
234
 
        switch(dataType) {
235
 
        case DataBuffer.TYPE_BYTE:
236
 
            if (sampleSize[0] != 1 && sampleSize[0] == 4 &&    // todo does this make sense??
237
 
               sampleSize[0] != 8) {                          // we get error only for 4
238
 
                throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder2"));
239
 
            }
240
 
            break;
241
 
        case DataBuffer.TYPE_SHORT:
242
 
        case DataBuffer.TYPE_USHORT:
243
 
            if (sampleSize[0] != 16) {
244
 
                throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder3"));
245
 
            }
246
 
            break;
247
 
        case DataBuffer.TYPE_INT:
248
 
        case DataBuffer.TYPE_FLOAT:
249
 
            if (sampleSize[0] != 32) {
250
 
                throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder4"));
251
 
            }
252
 
            break;
253
 
        default:
254
 
            throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder5"));
255
 
        }
256
 
 
257
 
        boolean dataTypeIsShort =
258
 
            dataType == DataBuffer.TYPE_SHORT ||
259
 
            dataType == DataBuffer.TYPE_USHORT;
260
 
 
261
 
        ColorModel colorModel = im.getColorModel();
262
 
        if (colorModel != null &&
263
 
            colorModel instanceof IndexColorModel &&
264
 
            dataType != DataBuffer.TYPE_BYTE) {
265
 
            // Don't support (unsigned) short palette-color images.
266
 
            throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder6"));
267
 
        }
268
 
        IndexColorModel icm = null;
269
 
        int sizeOfColormap = 0;
270
 
        char[] colormap = null;
 
198
        validateImage(dataTypeSize, sampleSize, numBands, dataType, colorModel);
 
199
 
 
200
        boolean dataTypeIsShort = dataType == DataBuffer.TYPE_SHORT
 
201
                || dataType == DataBuffer.TYPE_USHORT;
271
202
 
272
203
        // Set image type.
273
 
        int imageType = TIFF_UNSUPPORTED;
274
 
        int numExtraSamples = 0;
275
 
        int extraSampleType = EXTRA_SAMPLE_UNSPECIFIED;
276
 
        if (colorModel instanceof IndexColorModel) { // Bilevel or palette
277
 
            icm = (IndexColorModel)colorModel;
278
 
            int mapSize = icm.getMapSize();
279
 
 
280
 
            if (sampleSize[0] == 1 && numBands == 1) { // Bilevel image
281
 
 
282
 
                if (mapSize != 2) {
283
 
                    throw new IllegalArgumentException(PropertyUtil.getString("TIFFImageEncoder7"));
284
 
                }
285
 
 
286
 
                byte[] r = new byte[mapSize];
287
 
                icm.getReds(r);
288
 
                byte[] g = new byte[mapSize];
289
 
                icm.getGreens(g);
290
 
                byte[] b = new byte[mapSize];
291
 
                icm.getBlues(b);
292
 
 
293
 
                if ((r[0] & 0xff) == 0 &&
294
 
                    (r[1] & 0xff) == 255 &&
295
 
                    (g[0] & 0xff) == 0 &&
296
 
                    (g[1] & 0xff) == 255 &&
297
 
                    (b[0] & 0xff) == 0 &&
298
 
                    (b[1] & 0xff) == 255) {
299
 
 
300
 
                    imageType = TIFF_BILEVEL_BLACK_IS_ZERO;
301
 
 
302
 
                } else if ((r[0] & 0xff) == 255 &&
303
 
                           (r[1] & 0xff) == 0 &&
304
 
                           (g[0] & 0xff) == 255 &&
305
 
                           (g[1] & 0xff) == 0 &&
306
 
                           (b[0] & 0xff) == 255 &&
307
 
                           (b[1] & 0xff) == 0) {
308
 
 
309
 
                    imageType = TIFF_BILEVEL_WHITE_IS_ZERO;
310
 
 
311
 
                } else {
312
 
                    imageType = TIFF_PALETTE;
313
 
                }
314
 
 
315
 
            } else if (numBands == 1) { // Non-bilevel image.
316
 
                // Palette color image.
317
 
                imageType = TIFF_PALETTE;
318
 
            }
319
 
        } else if (colorModel == null) {
320
 
 
321
 
            if (sampleSize[0] == 1 && numBands == 1) { // bilevel
322
 
                imageType = TIFF_BILEVEL_BLACK_IS_ZERO;
323
 
            } else { // generic image
324
 
                imageType = TIFF_GENERIC;
325
 
                if (numBands > 1) {
326
 
                    numExtraSamples = numBands - 1;
327
 
                }
328
 
            }
329
 
 
330
 
        } else { // colorModel is non-null but not an IndexColorModel
331
 
            ColorSpace colorSpace = colorModel.getColorSpace();
332
 
 
333
 
            switch(colorSpace.getType()) {
334
 
            case ColorSpace.TYPE_CMYK:
335
 
                imageType = TIFF_CMYK;
336
 
                break;
337
 
            case ColorSpace.TYPE_GRAY:
338
 
                imageType = TIFF_GRAY;
339
 
                break;
340
 
            case ColorSpace.TYPE_Lab:
341
 
                imageType = TIFF_CIELAB;
342
 
                break;
343
 
            case ColorSpace.TYPE_RGB:
344
 
                if (compression == COMP_JPEG_TTN2
345
 
                        && encodeParam.getJPEGCompressRGBToYCbCr()) {
346
 
                    imageType = TIFF_YCBCR;
347
 
                } else {
348
 
                    imageType = TIFF_RGB;
349
 
                }
350
 
                break;
351
 
            case ColorSpace.TYPE_YCbCr:
352
 
                imageType = TIFF_YCBCR;
353
 
                break;
354
 
            default:
355
 
                imageType = TIFF_GENERIC; // generic
356
 
                break;
357
 
            }
358
 
 
359
 
            if (imageType == TIFF_GENERIC) {
360
 
                numExtraSamples = numBands - 1;
361
 
            } else if (numBands > 1) {
362
 
                numExtraSamples = numBands - colorSpace.getNumComponents();
363
 
            }
364
 
 
365
 
            if (numExtraSamples == 1 && colorModel.hasAlpha()) {
366
 
                extraSampleType = colorModel.isAlphaPremultiplied() ?
367
 
                    EXTRA_SAMPLE_ASSOCIATED_ALPHA :
368
 
                    EXTRA_SAMPLE_UNASSOCIATED_ALPHA;
369
 
            }
370
 
        }
371
 
 
372
 
        if (imageType == TIFF_UNSUPPORTED) {
373
 
            throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder8"));
374
 
        }
375
 
 
376
 
        int photometricInterpretation = -1;
377
 
        switch (imageType) {
378
 
 
379
 
        case TIFF_BILEVEL_WHITE_IS_ZERO:
380
 
            photometricInterpretation = 0;
381
 
            break;
382
 
 
383
 
        case TIFF_BILEVEL_BLACK_IS_ZERO:
384
 
            photometricInterpretation = 1;
385
 
            break;
386
 
 
387
 
        case TIFF_GRAY:
388
 
        case TIFF_GENERIC:
389
 
            // Since the CS_GRAY colorspace is always of type black_is_zero
390
 
            photometricInterpretation = 1;
391
 
            break;
392
 
 
393
 
        case TIFF_PALETTE:
394
 
            photometricInterpretation = 3;
395
 
 
396
 
            icm = (IndexColorModel)colorModel;
397
 
            sizeOfColormap = icm.getMapSize();
398
 
 
399
 
            byte[] r = new byte[sizeOfColormap];
400
 
            icm.getReds(r);
401
 
            byte[] g = new byte[sizeOfColormap];
402
 
            icm.getGreens(g);
403
 
            byte[] b = new byte[sizeOfColormap];
404
 
            icm.getBlues(b);
405
 
 
406
 
            int redIndex = 0, greenIndex = sizeOfColormap;
407
 
            int blueIndex = 2 * sizeOfColormap;
408
 
            colormap = new char[sizeOfColormap * 3];
409
 
            for (int i = 0; i < sizeOfColormap; i++) {
410
 
                int tmp = 0xff & r[i];   // beware of sign extended bytes
411
 
                colormap[redIndex++]   = (char)((tmp << 8) | tmp);
412
 
                tmp = 0xff & g[i];
413
 
                colormap[greenIndex++] = (char)((tmp << 8) | tmp);
414
 
                tmp = 0xff & b[i];
415
 
                colormap[blueIndex++]  = (char)((tmp << 8) | tmp);
416
 
            }
417
 
 
418
 
            sizeOfColormap *= 3;
419
 
 
420
 
            break;
421
 
 
422
 
        case TIFF_RGB:
423
 
            photometricInterpretation = 2;
424
 
            break;
425
 
 
426
 
        case TIFF_CMYK:
427
 
            photometricInterpretation = 5;
428
 
            break;
429
 
 
430
 
        case TIFF_YCBCR:
431
 
            photometricInterpretation = 6;
432
 
            break;
433
 
 
434
 
        case TIFF_CIELAB:
435
 
            photometricInterpretation = 8;
436
 
            break;
437
 
 
438
 
        default:
439
 
            throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder8"));
440
 
        }
441
 
 
442
 
        // Initialize tile dimensions.
443
 
        int tileWidth;
444
 
        int tileHeight;
445
 
        if (isTiled) {
446
 
            tileWidth = encodeParam.getTileWidth() > 0 ?
447
 
                encodeParam.getTileWidth() : im.getTileWidth();
448
 
            tileHeight = encodeParam.getTileHeight() > 0 ?
449
 
                encodeParam.getTileHeight() : im.getTileHeight();
450
 
        } else {
451
 
            tileWidth = width;
452
 
 
453
 
            tileHeight = encodeParam.getTileHeight() > 0 ?
454
 
                encodeParam.getTileHeight() : DEFAULT_ROWS_PER_STRIP;
455
 
        }
456
 
 
457
 
        int numTiles;
458
 
        if (isTiled) {
459
 
            // NB: Parentheses are used in this statement for correct rounding.
460
 
            numTiles =
461
 
                ((width + tileWidth - 1) / tileWidth) *
462
 
                ((height + tileHeight - 1) / tileHeight);
463
 
        } else {
464
 
            numTiles = (int)Math.ceil((double)height / (double)tileHeight);
465
 
        }
 
204
        ImageInfo imageInfo = ImageInfo.newInstance(im, dataTypeSize, numBands, colorModel,
 
205
                encodeParam);
 
206
 
 
207
        if (imageInfo.getType() == ImageType.UNSUPPORTED) {
 
208
            throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder8"));
 
209
        }
 
210
 
 
211
        final int numTiles = imageInfo.getNumTiles();
 
212
        final long bytesPerTile = imageInfo.getBytesPerTile();
 
213
        final long bytesPerRow = imageInfo.getBytesPerRow();
 
214
        final int tileHeight = imageInfo.getTileHeight();
 
215
        final int tileWidth = imageInfo.getTileWidth();
466
216
 
467
217
        long[] tileByteCounts = new long[numTiles];
468
 
 
469
 
        long bytesPerRow =
470
 
            (long)Math.ceil((sampleSize[0] / 8.0) * tileWidth * numBands);
471
 
 
472
 
        long bytesPerTile = bytesPerRow * tileHeight;
473
 
 
474
218
        for (int i = 0; i < numTiles; i++) {
475
219
            tileByteCounts[i] = bytesPerTile;
476
220
        }
480
224
            long lastStripRows = height - (tileHeight * (numTiles - 1));
481
225
            tileByteCounts[numTiles - 1] = lastStripRows * bytesPerRow;
482
226
        }
483
 
 
484
 
        long totalBytesOfData = bytesPerTile * (numTiles - 1) +
485
 
            tileByteCounts[numTiles - 1];
486
 
 
487
 
        // The data will be written after the IFD: create the array here
488
 
        // but fill it in later.
 
227
        long totalBytesOfData = bytesPerTile * (numTiles - 1) + tileByteCounts[numTiles - 1];
489
228
        long[] tileOffsets = new long[numTiles];
490
229
 
491
230
        // Basic fields - have to be in increasing numerical order.
502
241
        // ResolutionUnit                 296
503
242
 
504
243
        // Create Directory
505
 
        SortedSet fields = new TreeSet();
 
244
        SortedSet<TIFFField> fields = new TreeSet<TIFFField>();
506
245
 
507
246
        // Image Width
508
247
        fields.add(new TIFFField(TIFFImageDecoder.TIFF_IMAGE_WIDTH,
516
255
 
517
256
        char [] shortSampleSize = new char[numBands];
518
257
        for (int i = 0; i < numBands; i++) {
519
 
            shortSampleSize[i] = (char)sampleSize[i];
 
258
            shortSampleSize[i] = (char) dataTypeSize;
520
259
        }
521
260
        fields.add(new TIFFField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE,
522
261
                                 TIFFField.TIFF_SHORT, numBands,
524
263
 
525
264
        fields.add(new TIFFField(TIFFImageDecoder.TIFF_COMPRESSION,
526
265
                                 TIFFField.TIFF_SHORT, 1,
527
 
                                 new char[] {(char)compression}));
 
266
                                 new char[] {(char)compression.getValue()}));
528
267
 
529
268
        fields.add(
530
269
            new TIFFField(TIFFImageDecoder.TIFF_PHOTOMETRIC_INTERPRETATION,
531
270
                          TIFFField.TIFF_SHORT, 1,
532
 
                                 new char[] {(char)photometricInterpretation}));
 
271
                      new char[] {(char) imageInfo.getType().getPhotometricInterpretation()}));
533
272
 
534
273
        if (!isTiled) {
535
274
            fields.add(new TIFFField(TIFFImageDecoder.TIFF_STRIP_OFFSETS,
551
290
                                     tileByteCounts));
552
291
        }
553
292
 
554
 
        if (colormap != null) {
 
293
        if (imageInfo.getColormap() != null) {
555
294
            fields.add(new TIFFField(TIFFImageDecoder.TIFF_COLORMAP,
556
 
                                     TIFFField.TIFF_SHORT, sizeOfColormap,
557
 
                                     colormap));
 
295
                    TIFFField.TIFF_SHORT, imageInfo.getColormapSize(),
 
296
                    imageInfo.getColormap()));
558
297
        }
559
298
 
560
299
        if (isTiled) {
575
314
                                     tileByteCounts));
576
315
        }
577
316
 
578
 
        if (numExtraSamples > 0) {
579
 
            char[] extraSamples = new char[numExtraSamples];
580
 
            for (int i = 0; i < numExtraSamples; i++) {
581
 
                extraSamples[i] = (char)extraSampleType;
 
317
        if (imageInfo.getNumberOfExtraSamples() > 0) {
 
318
            char[] extraSamples = new char[imageInfo.getNumberOfExtraSamples()];
 
319
            for (int i = 0; i < imageInfo.getNumberOfExtraSamples(); i++) {
 
320
                extraSamples[i] = (char) imageInfo.getExtraSamplesType().getValue();
582
321
            }
583
322
            fields.add(new TIFFField(TIFFImageDecoder.TIFF_EXTRA_SAMPLES,
584
 
                                     TIFFField.TIFF_SHORT, numExtraSamples,
 
323
                    TIFFField.TIFF_SHORT, imageInfo.getNumberOfExtraSamples(),
585
324
                                     extraSamples));
586
325
        }
587
326
 
610
349
            // use it if available.
611
350
        }
612
351
 
613
 
        if (imageType == TIFF_YCBCR) {
 
352
        if (imageInfo.getType() == ImageType.YCBCR) {
614
353
            // YCbCrSubSampling: 2 is the default so we must write 1 as
615
354
            // we do not (yet) do any subsampling.
616
355
            char subsampleH = 1;
625
364
            fields.add(new TIFFField(TIFF_YCBCR_POSITIONING,
626
365
                                     TIFFField.TIFF_SHORT, 1,
627
366
                                     new char[]
628
 
                {(char)((compression == COMP_JPEG_TTN2) ? 1 : 2)}));
 
367
                    {(char) ((compression == CompressionValue.JPEG_TTN2) ? 1 : 2)}));
629
368
 
630
369
            // Reference black/white.
631
370
            long[][] refbw;
642
381
 
643
382
        // Add extra fields specified via the encoding parameters.
644
383
        TIFFField[] extraFields = encodeParam.getExtraFields();
645
 
        if (extraFields != null) {
646
 
            List extantTags = new ArrayList(fields.size());
647
 
            Iterator fieldIter = fields.iterator();
648
 
            while (fieldIter.hasNext()) {
649
 
                TIFFField fld = (TIFFField)fieldIter.next();
650
 
                extantTags.add(new Integer(fld.getTag()));
651
 
            }
 
384
        List extantTags = new ArrayList(fields.size());
 
385
        Iterator fieldIter = fields.iterator();
 
386
        while (fieldIter.hasNext()) {
 
387
            TIFFField fld = (TIFFField)fieldIter.next();
 
388
            extantTags.add(fld.getTag());
 
389
        }
652
390
 
653
 
            int numExtraFields = extraFields.length;
654
 
            for (int i = 0; i < numExtraFields; i++) {
655
 
                TIFFField fld = extraFields[i];
656
 
                Integer tagValue = new Integer(fld.getTag());
657
 
                if (!extantTags.contains(tagValue)) {
658
 
                    fields.add(fld);
659
 
                    extantTags.add(tagValue);
660
 
                }
 
391
        int numExtraFields = extraFields.length;
 
392
        for (int i = 0; i < numExtraFields; i++) {
 
393
            TIFFField fld = extraFields[i];
 
394
            Integer tagValue = fld.getTag();
 
395
            if (!extantTags.contains(tagValue)) {
 
396
                fields.add(fld);
 
397
                extantTags.add(tagValue);
661
398
            }
662
399
        }
663
400
 
691
428
        Deflater deflater = null;
692
429
        boolean jpegRGBToYCbCr = false;
693
430
 
694
 
        if (compression == COMP_NONE) {
 
431
        if (compression == CompressionValue.NONE) {
695
432
            // Determine the number of bytes of padding necessary between
696
433
            // the end of the IFD and the first data segment such that the
697
434
            // alignment of the data conforms to the specification (required
698
435
            // for uncompressed data only).
699
436
            int numBytesPadding = 0;
700
 
            if (sampleSize[0] == 16 && tileOffsets[0] % 2 != 0) {
 
437
            if (dataTypeSize == 16 && tileOffsets[0] % 2 != 0) {
701
438
                numBytesPadding = 1;
702
439
                tileOffsets[0]++;
703
 
            } else if (sampleSize[0] == 32 && tileOffsets[0] % 4 != 0) {
 
440
            } else if (dataTypeSize == 32 && tileOffsets[0] % 4 != 0) {
704
441
                numBytesPadding = (int)(4 - tileOffsets[0] % 4);
705
442
                tileOffsets[0] += numBytesPadding;
706
443
            }
750
487
                    output = new SeekableOutputStream(raFile);
751
488
 
752
489
                    // this method is exited!
753
 
                } catch (Exception e) {
 
490
                } catch (IOException e) {
754
491
                    // Allocate memory for the entire image data (!).
755
492
                    output = new ByteArrayOutputStream((int)totalBytesOfData);
756
493
                }
758
495
 
759
496
            int bufSize = 0;
760
497
            switch(compression) {
761
 
            case COMP_PACKBITS:
762
 
                bufSize = (int)(bytesPerTile + ((bytesPerRow + 127) / 128) * tileHeight);
 
498
            case PACKBITS:
 
499
                bufSize = (int) (bytesPerTile + ((bytesPerRow + 127) / 128) * tileHeight);
763
500
                break;
764
 
            case COMP_DEFLATE:
765
 
                bufSize = (int)bytesPerTile;
 
501
            case DEFLATE:
 
502
                bufSize = (int) bytesPerTile;
766
503
                deflater = new Deflater(encodeParam.getDeflateLevel());
767
504
                break;
768
505
            default:
781
518
 
782
519
        // Whether to test for contiguous data.
783
520
        boolean checkContiguous =
784
 
            ((sampleSize[0] == 1 &&
785
 
              sampleModel instanceof MultiPixelPackedSampleModel &&
786
 
              dataType == DataBuffer.TYPE_BYTE) ||
787
 
             (sampleSize[0] == 8 &&
788
 
              sampleModel instanceof ComponentSampleModel));
 
521
            ((dataTypeSize == 1
 
522
              && sampleModel instanceof MultiPixelPackedSampleModel
 
523
              && dataType == DataBuffer.TYPE_BYTE)
 
524
             || (dataTypeSize == 8
 
525
              && sampleModel instanceof ComponentSampleModel));
789
526
 
790
527
        // Also create a buffer to hold tileHeight lines of the
791
528
        // data to be written to the file, so we can use array writes.
792
529
        byte[] bpixels = null;
793
 
        if (compression != COMP_JPEG_TTN2) {
 
530
        if (compression != CompressionValue.JPEG_TTN2) {
794
531
            if (dataType == DataBuffer.TYPE_BYTE) {
795
532
                bpixels = new byte[tileHeight * tileWidth * numBands];
796
533
            } else if (dataTypeIsShort) {
797
534
                bpixels = new byte[2 * tileHeight * tileWidth * numBands];
798
 
            } else if (dataType == DataBuffer.TYPE_INT ||
799
 
                      dataType == DataBuffer.TYPE_FLOAT) {
 
535
            } else if (dataType == DataBuffer.TYPE_INT
 
536
                      || dataType == DataBuffer.TYPE_FLOAT) {
800
537
                bpixels = new byte[4 * tileHeight * tileWidth * numBands];
801
538
            }
802
539
        }
806
543
        int lastCol = minX + width;
807
544
        int tileNum = 0;
808
545
        for (int row = minY; row < lastRow; row += tileHeight) {
809
 
            int rows = isTiled ?
810
 
                tileHeight : Math.min(tileHeight, lastRow - row);
 
546
            int rows = isTiled
 
547
                ? tileHeight : Math.min(tileHeight, lastRow - row);
811
548
            int size = rows * tileWidth * numBands;
812
549
 
813
550
            for (int col = minX; col < lastCol; col += tileWidth) {
816
553
                    im.getData(new Rectangle(col, row, tileWidth, rows));
817
554
 
818
555
                boolean useDataBuffer = false;
819
 
                if (compression != COMP_JPEG_TTN2) { // JPEG access Raster
 
556
                if (compression != CompressionValue.JPEG_TTN2) { // JPEG access Raster
820
557
                    if (checkContiguous) {
821
 
                        if (sampleSize[0] == 8) { // 8-bit
 
558
                        if (dataTypeSize == 8) { // 8-bit
822
559
                            ComponentSampleModel csm =
823
560
                                (ComponentSampleModel)src.getSampleModel();
824
561
                            int[] bankIndices = csm.getBankIndices();
826
563
                            int pixelStride = csm.getPixelStride();
827
564
                            int lineStride = csm.getScanlineStride();
828
565
 
829
 
                            if (pixelStride != numBands ||
830
 
                               lineStride != bytesPerRow) {
 
566
                            if (pixelStride != numBands
 
567
                               || lineStride != bytesPerRow) {
831
568
                                useDataBuffer = false;
832
569
                            } else {
833
570
                                useDataBuffer = true;
834
571
                                for (int i = 0;
835
572
                                    useDataBuffer && i < numBands;
836
573
                                    i++) {
837
 
                                    if (bankIndices[i] != 0 ||
838
 
                                       bandOffsets[i] != i) {
 
574
                                    if (bankIndices[i] != 0
 
575
                                       || bandOffsets[i] != i) {
839
576
                                        useDataBuffer = false;
840
577
                                    }
841
578
                                }
843
580
                        } else { // 1-bit
844
581
                            MultiPixelPackedSampleModel mpp =
845
582
                                (MultiPixelPackedSampleModel)src.getSampleModel();
846
 
                            if (mpp.getNumBands() == 1 &&
847
 
                               mpp.getDataBitOffset() == 0 &&
848
 
                               mpp.getPixelBitStride() == 1) {
 
583
                            if (mpp.getNumBands() == 1
 
584
                               && mpp.getDataBitOffset() == 0
 
585
                               && mpp.getPixelBitStride() == 1) {
849
586
                                useDataBuffer = true;
850
587
                            }
851
588
                        }
866
603
 
867
604
                int pixel = 0;
868
605
                int k = 0;
869
 
                switch (sampleSize[0]) {
 
606
                switch (dataTypeSize) {
870
607
 
871
608
                case 1:
872
609
 
877
614
                            (MultiPixelPackedSampleModel)src.getSampleModel();
878
615
                        int lineStride = mpp.getScanlineStride();
879
616
                        int inOffset =
880
 
                            mpp.getOffset(col -
881
 
                                          src.getSampleModelTranslateX(),
882
 
                                          row -
883
 
                                          src.getSampleModelTranslateY());
884
 
                        if (lineStride == (int)bytesPerRow) {
 
617
                            mpp.getOffset(col
 
618
                                          - src.getSampleModelTranslateX(),
 
619
                                          row
 
620
                                          - src.getSampleModelTranslateY());
 
621
                        if (lineStride == bytesPerRow) {
885
622
                            System.arraycopy(btmp, inOffset,
886
623
                                             bpixels, 0,
887
 
                                             (int)bytesPerRow * rows);
 
624
                                             (int) bytesPerRow * rows);
888
625
                        } else {
889
626
                            int outOffset = 0;
890
627
                            for (int j = 0; j < rows; j++) {
891
628
                                System.arraycopy(btmp, inOffset,
892
629
                                                 bpixels, outOffset,
893
 
                                                 (int)bytesPerRow);
 
630
                                                 (int) bytesPerRow);
894
631
                                inOffset += lineStride;
895
 
                                outOffset += (int)bytesPerRow;
 
632
                                outOffset += bytesPerRow;
896
633
                            }
897
634
                        }
898
635
                    } else {
905
642
                            for (int j = 0; j < tileWidth / 8; j++) {
906
643
 
907
644
                                pixel =
908
 
                                    (pixels[index++] << 7) |
909
 
                                    (pixels[index++] << 6) |
910
 
                                    (pixels[index++] << 5) |
911
 
                                    (pixels[index++] << 4) |
912
 
                                    (pixels[index++] << 3) |
913
 
                                    (pixels[index++] << 2) |
914
 
                                    (pixels[index++] << 1) |
915
 
                                    pixels[index++];
 
645
                                    (pixels[index++] << 7)
 
646
                                    | (pixels[index++] << 6)
 
647
                                    | (pixels[index++] << 5)
 
648
                                    | (pixels[index++] << 4)
 
649
                                    | (pixels[index++] << 3)
 
650
                                    | (pixels[index++] << 2)
 
651
                                    | (pixels[index++] << 1)
 
652
                                    | pixels[index++];
916
653
                                bpixels[k++] = (byte)pixel;
917
654
                            }
918
655
 
927
664
                        }
928
665
                    }
929
666
 
930
 
                    if (compression == COMP_NONE) {
 
667
                    if (compression == CompressionValue.NONE) {
931
668
                        output.write(bpixels, 0, rows * ((tileWidth + 7) / 8));
932
 
                    } else if (compression == COMP_PACKBITS) {
 
669
                    } else if (compression == CompressionValue.PACKBITS) {
933
670
                        int numCompressedBytes =
934
671
                            compressPackBits(bpixels, rows,
935
 
                                             (int)bytesPerRow,
 
672
                                             bytesPerRow,
936
673
                                             compressBuf);
937
674
                        tileByteCounts[tileNum++] = numCompressedBytes;
938
675
                        output.write(compressBuf, 0, numCompressedBytes);
939
 
                    } else if (compression == COMP_DEFLATE) {
 
676
                    } else if (compression == CompressionValue.DEFLATE) {
940
677
                        int numCompressedBytes =
941
678
                            deflate(deflater, bpixels, compressBuf);
942
679
                        tileByteCounts[tileNum++] = numCompressedBytes;
966
703
                        }
967
704
                    }
968
705
 
969
 
                    if (compression == COMP_NONE) {
 
706
                    if (compression == CompressionValue.NONE) {
970
707
                        output.write(bpixels, 0, rows * ((tileWidth + 1) / 2));
971
 
                    } else if (compression == COMP_PACKBITS) {
 
708
                    } else if (compression == CompressionValue.PACKBITS) {
972
709
                        int numCompressedBytes =
973
710
                            compressPackBits(bpixels, rows,
974
 
                                             (int)bytesPerRow,
 
711
                                             bytesPerRow,
975
712
                                             compressBuf);
976
713
                        tileByteCounts[tileNum++] = numCompressedBytes;
977
714
                        output.write(compressBuf, 0, numCompressedBytes);
978
 
                    } else if (compression == COMP_DEFLATE) {
 
715
                    } else if (compression == CompressionValue.DEFLATE) {
979
716
                        int numCompressedBytes =
980
717
                            deflate(deflater, bpixels, compressBuf);
981
718
                        tileByteCounts[tileNum++] = numCompressedBytes;
985
722
 
986
723
                case 8:
987
724
 
988
 
                    if (compression != COMP_JPEG_TTN2) {
 
725
                    if (compression != CompressionValue.JPEG_TTN2) {
989
726
                        if (useDataBuffer) {
990
727
                            byte[] btmp =
991
728
                                ((DataBufferByte)src.getDataBuffer()).getData();
992
729
                            ComponentSampleModel csm =
993
730
                                (ComponentSampleModel)src.getSampleModel();
994
731
                            int inOffset =
995
 
                                csm.getOffset(col -
996
 
                                              src.getSampleModelTranslateX(),
997
 
                                              row -
998
 
                                              src.getSampleModelTranslateY());
 
732
                                csm.getOffset(col
 
733
                                              - src.getSampleModelTranslateX(),
 
734
                                              row
 
735
                                              - src.getSampleModelTranslateY());
999
736
                            int lineStride = csm.getScanlineStride();
1000
 
                            if (lineStride == (int)bytesPerRow) {
 
737
                            if (lineStride == bytesPerRow) {
1001
738
                                System.arraycopy(btmp,
1002
739
                                                 inOffset,
1003
740
                                                 bpixels, 0,
1004
 
                                                 (int)bytesPerRow * rows);
 
741
                                                 (int) bytesPerRow * rows);
1005
742
                            } else {
1006
743
                                int outOffset = 0;
1007
744
                                for (int j = 0; j < rows; j++) {
1008
745
                                    System.arraycopy(btmp, inOffset,
1009
746
                                                     bpixels, outOffset,
1010
 
                                                     (int)bytesPerRow);
 
747
                                                     (int) bytesPerRow);
1011
748
                                    inOffset += lineStride;
1012
 
                                    outOffset += (int)bytesPerRow;
 
749
                                    outOffset += bytesPerRow;
1013
750
                                }
1014
751
                            }
1015
752
                        } else {
1019
756
                        }
1020
757
                    }
1021
758
 
1022
 
                    if (compression == COMP_NONE) {
 
759
                    if (compression == CompressionValue.NONE) {
1023
760
                        output.write(bpixels, 0, size);
1024
 
                    } else if (compression == COMP_PACKBITS) {
 
761
                    } else if (compression == CompressionValue.PACKBITS) {
1025
762
                        int numCompressedBytes =
1026
763
                            compressPackBits(bpixels, rows,
1027
 
                                             (int)bytesPerRow,
 
764
                                             bytesPerRow,
1028
765
                                             compressBuf);
1029
766
                        tileByteCounts[tileNum++] = numCompressedBytes;
1030
767
                        output.write(compressBuf, 0, numCompressedBytes);
1031
 
                    } else if (compression == COMP_DEFLATE) {
 
768
                    } else if (compression == CompressionValue.DEFLATE) {
1032
769
                        int numCompressedBytes =
1033
770
                            deflate(deflater, bpixels, compressBuf);
1034
771
                        tileByteCounts[tileNum++] = numCompressedBytes;
1045
782
                        bpixels[ls++] = (byte) (value & 0x00ff);
1046
783
                    }
1047
784
 
1048
 
                    if (compression == COMP_NONE) {
1049
 
                        output.write(bpixels, 0, size*2);
1050
 
                    } else if (compression == COMP_PACKBITS) {
 
785
                    if (compression == CompressionValue.NONE) {
 
786
                        output.write(bpixels, 0, size * 2);
 
787
                    } else if (compression == CompressionValue.PACKBITS) {
1051
788
                        int numCompressedBytes =
1052
789
                            compressPackBits(bpixels, rows,
1053
 
                                             (int)bytesPerRow,
 
790
                                             bytesPerRow,
1054
791
                                             compressBuf);
1055
792
                        tileByteCounts[tileNum++] = numCompressedBytes;
1056
793
                        output.write(compressBuf, 0, numCompressedBytes);
1057
 
                    } else if (compression == COMP_DEFLATE) {
 
794
                    } else if (compression == CompressionValue.DEFLATE) {
1058
795
                        int numCompressedBytes =
1059
796
                            deflate(deflater, bpixels, compressBuf);
1060
797
                        tileByteCounts[tileNum++] = numCompressedBytes;
1070
807
                            bpixels[li++] = (byte)((value & 0xff000000) >>> 24);
1071
808
                            bpixels[li++] = (byte)((value & 0x00ff0000) >>> 16);
1072
809
                            bpixels[li++] = (byte)((value & 0x0000ff00) >>> 8);
1073
 
                            bpixels[li++] = (byte)( value & 0x000000ff);
 
810
                            bpixels[li++] = (byte)(value & 0x000000ff);
1074
811
                        }
1075
812
                    } else { // DataBuffer.TYPE_FLOAT
1076
813
                        int lf = 0;
1079
816
                            bpixels[lf++] = (byte)((value & 0xff000000) >>> 24);
1080
817
                            bpixels[lf++] = (byte)((value & 0x00ff0000) >>> 16);
1081
818
                            bpixels[lf++] = (byte)((value & 0x0000ff00) >>> 8);
1082
 
                            bpixels[lf++] = (byte)( value & 0x000000ff);
 
819
                            bpixels[lf++] = (byte)(value & 0x000000ff);
1083
820
                        }
1084
821
                    }
1085
 
                    if (compression == COMP_NONE) {
1086
 
                        output.write(bpixels, 0, size*4);
1087
 
                    } else if (compression == COMP_PACKBITS) {
 
822
                    if (compression == CompressionValue.NONE) {
 
823
                        output.write(bpixels, 0, size * 4);
 
824
                    } else if (compression == CompressionValue.PACKBITS) {
1088
825
                        int numCompressedBytes =
1089
826
                            compressPackBits(bpixels, rows,
1090
 
                                             (int)bytesPerRow,
 
827
                                             bytesPerRow,
1091
828
                                             compressBuf);
1092
829
                        tileByteCounts[tileNum++] = numCompressedBytes;
1093
830
                        output.write(compressBuf, 0, numCompressedBytes);
1094
 
                    } else if (compression == COMP_DEFLATE) {
 
831
                    } else if (compression == CompressionValue.DEFLATE) {
1095
832
                        int numCompressedBytes =
1096
833
                            deflate(deflater, bpixels, compressBuf);
1097
834
                        tileByteCounts[tileNum++] = numCompressedBytes;
1098
835
                        output.write(compressBuf, 0, numCompressedBytes);
1099
836
                    }
1100
837
                    break;
1101
 
 
 
838
                default:
 
839
                    break;
1102
840
                }
1103
841
            }
1104
842
        }
1105
843
 
1106
 
        if (compression == COMP_NONE) {
 
844
        if (compression == CompressionValue.NONE) {
1107
845
            // Write an extra byte for IFD word alignment if needed.
1108
846
            if (skipByte) {
1109
847
                output.write((byte)0);
1118
856
            }
1119
857
            totalBytes += (int)tileByteCounts[numTiles - 1];
1120
858
 
1121
 
            nextIFDOffset = isLast ?
1122
 
                0 : ifdOffset + dirSize + totalBytes;
 
859
            nextIFDOffset = isLast
 
860
                ? 0 : ifdOffset + dirSize + totalBytes;
1123
861
            if ((nextIFDOffset & 0x01) != 0) {   // make it even
1124
862
                nextIFDOffset++;
1125
863
                skipByte = true;
1150
888
 
1151
889
                // Open a FileInputStream from which to copy the data.
1152
890
                FileInputStream fileStream = new FileInputStream(tempFile);
1153
 
 
1154
 
                // Close the original SeekableOutputStream.
1155
 
                output.close();
1156
 
 
1157
 
                // Reset variable to the original OutputStream.
1158
 
                output = outCache;
1159
 
 
1160
 
                // Write the IFD.
1161
 
                writeDirectory(ifdOffset, fields, nextIFDOffset);
1162
 
 
1163
 
                // Write the image data.
1164
 
                byte[] copyBuffer = new byte[8192];
1165
 
                int bytesCopied = 0;
1166
 
                while (bytesCopied < totalBytes) {
1167
 
                    int bytesRead = fileStream.read(copyBuffer);
1168
 
                    if (bytesRead == -1) {
1169
 
                        break;
 
891
                try {
 
892
                    // Close the original SeekableOutputStream.
 
893
                    output.close();
 
894
 
 
895
                    // Reset variable to the original OutputStream.
 
896
                    output = outCache;
 
897
 
 
898
                    // Write the IFD.
 
899
                    writeDirectory(ifdOffset, fields, nextIFDOffset);
 
900
 
 
901
                    // Write the image data.
 
902
                    byte[] copyBuffer = new byte[8192];
 
903
                    int bytesCopied = 0;
 
904
                    while (bytesCopied < totalBytes) {
 
905
                        int bytesRead = fileStream.read(copyBuffer);
 
906
                        if (bytesRead == -1) {
 
907
                            break;
 
908
                        }
 
909
                        output.write(copyBuffer, 0, bytesRead);
 
910
                        bytesCopied += bytesRead;
1170
911
                    }
1171
 
                    output.write(copyBuffer, 0, bytesRead);
1172
 
                    bytesCopied += bytesRead;
 
912
                } finally {
 
913
                    // Delete the temporary file.
 
914
                    fileStream.close();
1173
915
                }
1174
 
 
1175
 
                // Delete the temporary file.
1176
 
                fileStream.close();
1177
 
                tempFile.delete();
 
916
                boolean isDeleted = tempFile.delete();
 
917
                assert isDeleted;
1178
918
 
1179
919
                // Write an extra byte for IFD word alignment if needed.
1180
920
                if (skipByte) {
1209
949
        return nextIFDOffset;
1210
950
    }
1211
951
 
 
952
    private void validateImage(int dataTypeSize, int[] sampleSize, int numBands, int dataType,
 
953
            ColorModel colorModel) {
 
954
        // Retrieve and verify sample size.
 
955
        for (int i = 1; i < sampleSize.length; i++) {
 
956
            if (sampleSize[i] != dataTypeSize) {
 
957
                throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder0"));
 
958
            }
 
959
        }
 
960
 
 
961
        // Check low bit limits.
 
962
        if ((dataTypeSize == 1 || dataTypeSize == 4) && numBands != 1) {
 
963
            throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder1"));
 
964
        }
 
965
 
 
966
        // Retrieve and verify data type.
 
967
        switch (dataType) {
 
968
        case DataBuffer.TYPE_BYTE:
 
969
            if (dataTypeSize != 1 && dataTypeSize == 4 && // todo does this make sense??
 
970
                    dataTypeSize != 8) { // we get error only for 4
 
971
                throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder2"));
 
972
            }
 
973
            break;
 
974
        case DataBuffer.TYPE_SHORT:
 
975
        case DataBuffer.TYPE_USHORT:
 
976
            if (dataTypeSize != 16) {
 
977
                throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder3"));
 
978
            }
 
979
            break;
 
980
        case DataBuffer.TYPE_INT:
 
981
        case DataBuffer.TYPE_FLOAT:
 
982
            if (dataTypeSize != 32) {
 
983
                throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder4"));
 
984
            }
 
985
            break;
 
986
        default:
 
987
            throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder5"));
 
988
        }
 
989
 
 
990
        if (colorModel instanceof IndexColorModel && dataType != DataBuffer.TYPE_BYTE) {
 
991
            // Don't support (unsigned) short palette-color images.
 
992
            throw new RuntimeException(PropertyUtil.getString("TIFFImageEncoder6"));
 
993
        }
 
994
    }
 
995
 
1212
996
    /**
1213
997
     * Calculates the size of the IFD.
1214
998
     */
1226
1010
            TIFFField field = (TIFFField)iter.next();
1227
1011
 
1228
1012
            // Determine the size of the field value.
1229
 
            int valueSize = field.getCount() * sizeOfType[field.getType()];
 
1013
            int valueSize = field.getCount() * SIZE_OF_TYPE[field.getType()];
1230
1014
 
1231
1015
            // Add any excess size.
1232
1016
            if (valueSize > 4) {
1311
1095
    /**
1312
1096
     * Determine the number of bytes in the value portion of the field.
1313
1097
     */
1314
 
    private static int getValueSize(TIFFField field) {
 
1098
    private static int getValueSize(TIFFField field) throws UnsupportedEncodingException {
1315
1099
        int type = field.getType();
1316
1100
        int count = field.getCount();
1317
1101
        int valueSize = 0;
1318
1102
        if (type == TIFFField.TIFF_ASCII) {
1319
1103
            for (int i = 0; i < count; i++) {
1320
 
                byte[] stringBytes = field.getAsString(i).getBytes();   // note: default encoding @work here!
 
1104
                byte[] stringBytes = field.getAsString(i).getBytes("UTF-8");   // note: default encoding @work here!
1321
1105
                valueSize += stringBytes.length;
1322
1106
                if (stringBytes[stringBytes.length - 1] != 0) {
1323
1107
                    valueSize++;
1324
1108
                }
1325
1109
            }
1326
1110
        } else {
1327
 
            valueSize = count * sizeOfType[type];
 
1111
            valueSize = count * SIZE_OF_TYPE[type];
1328
1112
        }
1329
1113
        return valueSize;
1330
1114
    }
1331
1115
 
1332
 
    private static final int[] sizeOfType = {
 
1116
    private static final int[] SIZE_OF_TYPE = {
1333
1117
        0, //  0 = n/a
1334
1118
        1, //  1 = byte
1335
1119
        1, //  2 = ascii
1462
1246
 
1463
1247
        case TIFFField.TIFF_ASCII:
1464
1248
            for (int i = 0; i < count; i++) {
1465
 
                byte[] stringBytes = field.getAsString(i).getBytes();
 
1249
                byte[] stringBytes = field.getAsString(i).getBytes("UTF-8");
1466
1250
                output.write(stringBytes);
1467
1251
                if (stringBytes[stringBytes.length - 1] != (byte)0) {
1468
1252
                    output.write((byte)0);
1481
1265
    // stored in 2 bytes.
1482
1266
    private void writeUnsignedShort(int s) throws IOException {
1483
1267
        output.write((s & 0xff00) >>> 8);
1484
 
        output.write( s & 0x00ff);
 
1268
        output.write(s & 0x00ff);
1485
1269
    }
1486
1270
 
1487
1271
    /**
1496
1280
        output.write((int) (l & 0x000000ff));
1497
1281
    }
1498
1282
 
1499
 
    /**
1500
 
     * Returns the current offset in the supplied OutputStream.
1501
 
     * This method should only be used if compressing data.
1502
 
     */
1503
 
    private long getOffset(OutputStream out) throws IOException {
1504
 
        if (out instanceof ByteArrayOutputStream) {
1505
 
            return ((ByteArrayOutputStream)out).size();
1506
 
        } else if (out instanceof SeekableOutputStream) {
1507
 
            return ((SeekableOutputStream)out).getFilePointer();
1508
 
        } else {
1509
 
            // Shouldn't happen.
1510
 
            throw new IllegalStateException(PropertyUtil.getString("TIFFImageEncoder13"));
1511
 
        }
1512
 
    }
 
1283
//    /**
 
1284
//     * Returns the current offset in the supplied OutputStream.
 
1285
//     * This method should only be used if compressing data.
 
1286
//     */
 
1287
//    private long getOffset(OutputStream out) throws IOException {
 
1288
//        if (out instanceof ByteArrayOutputStream) {
 
1289
//            return ((ByteArrayOutputStream)out).size();
 
1290
//        } else if (out instanceof SeekableOutputStream) {
 
1291
//            return ((SeekableOutputStream)out).getFilePointer();
 
1292
//        } else {
 
1293
//            // Shouldn't happen.
 
1294
//            throw new IllegalStateException(PropertyUtil.getString("TIFFImageEncoder13"));
 
1295
//        }
 
1296
//    }
1513
1297
 
1514
1298
    /**
1515
1299
     * Performs PackBits compression on a tile of data.
1516
1300
     */
1517
1301
    private static int compressPackBits(byte[] data, int numRows,
1518
 
                                        int bytesPerRow, byte[] compData) {
 
1302
                                        long bytesPerRow, byte[] compData) {
1519
1303
        int inOffset = 0;
1520
1304
        int outOffset = 0;
1521
1305
 
1522
1306
        for (int i = 0; i < numRows; i++) {
1523
 
            outOffset = packBits(data, inOffset, bytesPerRow,
 
1307
            outOffset = packBits(data, inOffset, (int) bytesPerRow,
1524
1308
                                 compData, outOffset);
1525
1309
            inOffset += bytesPerRow;
1526
1310
        }
1541
1325
        while (inOffset <= inMax) {
1542
1326
            int run = 1;
1543
1327
            byte replicate = input[inOffset];
1544
 
            while (run < 127 && inOffset < inMax &&
1545
 
                  input[inOffset] == input[inOffset + 1]) {
 
1328
            while (run < 127 && inOffset < inMax
 
1329
                  && input[inOffset] == input[inOffset + 1]) {
1546
1330
                run++;
1547
1331
                inOffset++;
1548
1332
            }
1554
1338
 
1555
1339
            run = 0;
1556
1340
            int saveOffset = outOffset;
1557
 
            while (run < 128 &&
1558
 
                  ((inOffset < inMax &&
1559
 
                    input[inOffset] != input[inOffset + 1]) ||
1560
 
                   (inOffset < inMaxMinus1 &&
1561
 
                    input[inOffset] != input[inOffset + 2]))) {
 
1341
            while (run < 128
 
1342
                  && ((inOffset < inMax
 
1343
                    && input[inOffset] != input[inOffset + 1])
 
1344
                   || (inOffset < inMaxMinus1
 
1345
                    && input[inOffset] != input[inOffset + 2]))) {
1562
1346
                run++;
1563
1347
                output[++outOffset] = input[inOffset++];
1564
1348
            }