blob: ddc17235c3ffe61dfb976e2b271ba4f4b2ac87d9 [file] [log] [blame]
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* under the License.
*/
package org.apache.commons.imaging.formats.jpeg.segments;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class DhtSegment extends Segment
{
public final List<HuffmanTable> huffmanTables = new ArrayList<HuffmanTable>();
public static class HuffmanTable
{
// some arrays are better off one-based
// to avoid subtractions by one later when indexing them
public final int tableClass;
public final int destinationIdentifier;
public final int[] bits; // 1-based
public final int[] huffVal; // 0-based
// derived properties:
public final int[] huffSize = new int[16 * 256]; // 0-based
public final int[] huffCode; // 0-based
public final int[] minCode = new int[1 + 16]; // 1-based
public final int[] maxCode = new int[1 + 16]; // 1-based
public final int[] valPtr = new int[1 + 16]; // 1-based
public HuffmanTable(int tableClass, int destinationIdentifier,
int[] bits, int[] huffVal)
{
this.tableClass = tableClass;
this.destinationIdentifier = destinationIdentifier;
this.bits = bits;
this.huffVal = huffVal;
// "generate_size_table", section C.2, figure C.1, page 51 of ITU-T T.81:
int k = 0;
int i = 1;
int j = 1;
int lastK = -1;
while (true)
{
if (j > bits[i])
{
i++;
j = 1;
if (i > 16)
{
huffSize[k] = 0;
lastK = k;
break;
}
}
else
{
huffSize[k] = i;
k++;
j++;
}
}
// "generate_code_table", section C.2, figure C.2, page 52 of ITU-T T.81:
k = 0;
int code = 0;
int si = huffSize[0];
huffCode = new int[lastK];
while (true)
{
huffCode[k] = code;
code++;
k++;
if (huffSize[k] == si)
continue;
if (huffSize[k] == 0)
break;
do
{
code <<= 1;
si++;
} while (huffSize[k] != si);
}
// "Decoder_tables", section F.2.2.3, figure F.15, page 108 of T.81:
i = 0;
j = 0;
while (true)
{
i++;
if (i > 16)
break;
if (bits[i] == 0)
maxCode[i] = -1;
else
{
valPtr[i] = j;
minCode[i] = huffCode[j];
j += bits[i] - 1;
maxCode[i] = huffCode[j];
j++;
}
}
}
}
public DhtSegment(int marker, byte[] segmentData)
throws IOException
{
this(marker, segmentData.length, new ByteArrayInputStream(segmentData));
}
public DhtSegment(int marker, int length, InputStream is)
throws IOException
{
super(marker, length);
while (length > 0)
{
int tableClassAndDestinationId =
0xff & readByte("TableClassAndDestinationId",
is, "Not a Valid JPEG File");
length--;
int tableClass = (tableClassAndDestinationId >> 4) & 0xf;
int destinationIdentifier = tableClassAndDestinationId & 0xf;
int[] bits = new int[1 + 16];
int bitsSum = 0;
for (int i = 1; i < bits.length; i++)
{
bits[i] = 0xff & readByte("Li", is, "Not a Valid JPEG File");
length--;
bitsSum += bits[i];
}
int[] huffVal = new int[bitsSum];
for (int i = 0; i < bitsSum; i++)
{
huffVal[i] = 0xff & readByte("Vij", is, "Not a Valid JPEG File");
length--;
}
huffmanTables.add(new HuffmanTable(tableClass,
destinationIdentifier, bits, huffVal));
}
}
@Override
public String getDescription()
{
return "DHT (" + getSegmentType() + ")";
}
}