File: TIFFDecoderLogLuv.java

package info (click to toggle)
java-imaging-utilities 0.14.2%2B3-4
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 2,304 kB
  • ctags: 3,737
  • sloc: java: 31,190; sh: 238; xml: 30; makefile: 19
file content (146 lines) | stat: -rw-r--r-- 4,034 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * TIFFDecoderLogLuv
 *
 * Copyright (c) 2002, 2003 Marco Schmidt.
 * All rights reserved.
 */

package net.sourceforge.jiu.codecs.tiff;

import java.io.DataInput;
import java.io.IOException;
import net.sourceforge.jiu.codecs.tiff.TIFFConstants;
import net.sourceforge.jiu.codecs.tiff.TIFFDecoder;
import net.sourceforge.jiu.codecs.InvalidFileStructureException;
import net.sourceforge.jiu.ops.MissingParameterException;

/**
 * A TIFF decoder for files compressed with the <em>LogLuv RLE</em> method.
 * This compression algorithm has the value <code>34676</code> 
 * ({@link TIFFConstants#COMPRESSION_SGI_LOG_RLE})
 * in the compression tag of an image file directory.
 * Only image data with a photometric interpretation value of 
 * {@link TIFFConstants#PHOTOMETRIC_TRUECOLOR_LOGLUV} can be compressed with this method.
 * <p>
 * This implementation is based on the file <code>tif_luv.c</code> which
 * is part of the TIFF library <a target="_top" href="http://www.libtiff.org">libtiff</a>.
 * The original implementation was written by Greg W. Larson.
 * <p>
 * Learn more about the color type and its encoding on Greg's page
 * <a target="_top" href="http://positron.cs.berkeley.edu/~gwlarson/pixformat/tiffluv.html">LogLuv 
 * Encoding for TIFF Images</a>.
 * You will also find numerous sample image files there.
 * @author Marco Schmidt
 * @since 0.10.0
 */
public class TIFFDecoderLogLuv extends TIFFDecoder
{
	private DataInput in;
	private int compressedSize;
	private int tileWidth;
	private boolean rle;

	public void decode() throws 
		InvalidFileStructureException,
		IOException
	{
		byte[] row = new byte[getBytesPerRow()];
		rle = getImageFileDirectory().getCompression() == TIFFConstants.COMPRESSION_SGI_LOG_RLE;
		for (int y = getY1(); y <= getY2(); y++)
		{
			decodeRow(row);
			putBytes(row, 0, row.length);
		}
	}

	private void decodeRow(byte[] row) throws
		InvalidFileStructureException,
		IOException
	{
		if (rle)
		{
			decodeRowRLE(row);
		}
		else
		{
			decodeRowPacked24(row);
		}
	}

	private void decodeRowPacked24(byte[] row) throws 
		InvalidFileStructureException,
		IOException
	{
		int num = getImageFileDirectory().getTileWidth() * 3;
		in.readFully(row, 0, num);
	}

	private void decodeRowRLE(byte[] row) throws 
		InvalidFileStructureException,
		IOException
	{
		final int BYTES_PER_PIXEL;
		if (getImageFileDirectory().getPhotometricInterpretation() == TIFFConstants.PHOTOMETRIC_LOGL)
		{
			BYTES_PER_PIXEL = 2; // LogL
		}
		else
		{
			BYTES_PER_PIXEL = 4; // LogLuv
		}
		for (int initialOffset = 0; initialOffset < BYTES_PER_PIXEL; initialOffset++)
		{
			int offset = initialOffset;
			int numPixels = tileWidth;
			do
			{
				int v1 = in.readUnsignedByte();
				if ((v1 & 128) != 0)
				{
					// run
					int runCount = v1 + (2 - 128);
					numPixels -= runCount;
					compressedSize -= 2;
					byte v2 = in.readByte();
					while (runCount-- != 0)
					{
						row[offset] = v2;
						offset += BYTES_PER_PIXEL;
					}
				}
				else
				{
					// non-run, copy data
					int runCount = v1;
					numPixels -= runCount;
					compressedSize = compressedSize - runCount - 1;
					while (runCount-- != 0)
					{
						row[offset] = in.readByte();
						offset += BYTES_PER_PIXEL;
					}
				}
				if (compressedSize < 0)
				{
					throw new InvalidFileStructureException("Ran out of compressed input bytes before completing the decoding process.");
				}
			}
			while (numPixels > 0);
		}
	}

	public Integer[] getCompressionTypes()
	{
		return new Integer[] {new Integer(TIFFConstants.COMPRESSION_SGI_LOG_RLE), new Integer(TIFFConstants.COMPRESSION_SGI_LOG_24_PACKED)};
	}

	public void initialize() throws
		IOException, 
		MissingParameterException
	{
		super.initialize();
		in = getInput();
		compressedSize = getImageFileDirectory().getByteCount(getTileIndex());
		tileWidth = getImageFileDirectory().getTileWidth();
	}	
}