Added support for Huffman compression, though, it doesn't work fully yet

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3071 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Matthew Wilber 2003-04-18 03:19:36 +00:00
parent 28adeff1cb
commit c61687ba31
8 changed files with 612 additions and 47 deletions

View File

@ -0,0 +1,83 @@
/*****************************************************************************/
// BitReader
// Written by Michael Wilber, OBOS Translation Kit Team
//
// BitReader.cpp
//
// Wrapper class for StreamBuffer to make it convenient to read 1 bit at
// a time
//
//
// Copyright (c) 2003 OpenBeOS Project
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
/*****************************************************************************/
#include "BitReader.h"
BitReader::BitReader(StreamBuffer *pstreambuf)
{
finitStatus = B_BAD_VALUE;
fnbytesRead = 0;
fbitbuf = 0;
fcurrentbit = 0;
fpstreambuf = pstreambuf;
if (fpstreambuf)
finitStatus = ReadByte();
}
BitReader::~BitReader()
{
finitStatus = B_ERROR;
fpstreambuf = NULL;
fbitbuf = 0;
fcurrentbit = 0;
}
status_t
BitReader::NextBit()
{
status_t result;
result = PeekBit();
if (result >= 0)
fcurrentbit--;
return result;
}
status_t
BitReader::PeekBit()
{
// if fcurrentbit is zero, read in next byte
if (!fcurrentbit && ReadByte() != B_OK)
return B_ERROR;
return (fbitbuf >> (fcurrentbit - 1)) & 1;
}
status_t
BitReader::ReadByte()
{
if (fpstreambuf->Read(&fbitbuf, 1) != 1)
return B_ERROR;
fnbytesRead++;
fcurrentbit = 8;
return B_OK;
}

View File

@ -0,0 +1,66 @@
/*****************************************************************************/
// BitReader
// Written by Michael Wilber, OBOS Translation Kit Team
//
// BitReader.h
//
// Wrapper class for StreamBuffer to make it convenient to read 1 bit at
// a time
//
//
// Copyright (c) 2003 OpenBeOS Project
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
/*****************************************************************************/
#ifndef BIT_READER_H
#define BIT_READER_H
#include "StreamBuffer.h"
class BitReader {
public:
BitReader(StreamBuffer *pstreambuf);
~BitReader();
status_t InitCheck() const { return finitStatus; };
uint32 BytesRead() const { return fnbytesRead; };
// return the current bit and increment the position
// If the result is negative, an error occured
status_t NextBit();
// return the current bit without incrementing the position
// (if buffer is empty, will read next byte in StreamBuffer)
// If the result is negative, an error occured
status_t PeekBit();
private:
status_t ReadByte();
StreamBuffer *fpstreambuf;
status_t finitStatus;
uint32 fnbytesRead;
uint8 fbitbuf;
uint8 fcurrentbit;
};
#endif

View File

@ -30,14 +30,234 @@
#include "DecodeTree.h"
DecodeTree::DecodeTree()
// Encodings used to populate
// the decode trees
const HuffmanEncoding g_encWhiteTerm[] = {
{0, 0x35, 8}, // "00110101"
{1, 0x07, 6}, // "000111"
{2, 0x07, 4}, // "0111"
{3, 0x08, 4}, // "1000"
{4, 0x0b, 4}, // "1011"
{5, 0x0c, 4}, // "1100"
{6, 0x0e, 4}, // "1110"
{7, 0x0f, 4}, // "1111"
{8, 0x13, 5}, // "10011"
{9, 0x14, 5}, // "10100"
{10, 0x07, 5}, // "00111"
{11, 0x08, 5}, // "01000"
{12, 0x08, 6}, // "001000"
{13, 0x03, 6}, // "000011"
{14, 0x34, 6}, // "110100"
{15, 0x35, 6}, // "110101"
{16, 0x2a, 6}, // "101010"
{17, 0x2b, 6}, // "101011"
{18, 0x27, 7}, // "0100111"
{19, 0x0c, 7}, // "0001100"
{20, 0x08, 7}, // "0001000"
{21, 0x17, 7}, // "0010111"
{22, 0x03, 7}, // "0000011"
{23, 0x04, 7}, // "0000100"
{24, 0x28, 7}, // "0101000"
{25, 0x2b, 7}, // "0101011"
{26, 0x13, 7}, // "0010011"
{27, 0x24, 7}, // "0100100"
{28, 0x18, 7}, // "0011000"
{29, 0x02, 8}, // "00000010"
{30, 0x03, 8}, // "00000011"
{31, 0x1a, 8}, // "00011010"
{32, 0x1b, 8}, // "00011011"
{33, 0x12, 8}, // "00010010"
{34, 0x13, 8}, // "00010011"
{35, 0x14, 8}, // "00010100"
{36, 0x15, 8}, // "00010101"
{37, 0x16, 8}, // "00010110"
{38, 0x17, 8}, // "00010111"
{39, 0x28, 8}, // "00101000"
{40, 0x29, 8}, // "00101001"
{41, 0x2a, 8}, // "00101010"
{42, 0x2b, 8}, // "00101011"
{43, 0x2c, 8}, // "00101100"
{44, 0x2d, 8}, // "00101101"
{45, 0x04, 8}, // "00000100"
{46, 0x05, 8}, // "00000101"
{47, 0x0a, 8}, // "00001010"
{48, 0x0b, 8}, // "00001011"
{49, 0x52, 8}, // "01010010"
{50, 0x53, 8}, // "01010011"
{51, 0x54, 8}, // "01010100"
{52, 0x55, 8}, // "01010101"
{53, 0x24, 8}, // "00100100"
{54, 0x25, 8}, // "00100101"
{55, 0x58, 8}, // "01011000"
{56, 0x59, 8}, // "01011001"
{57, 0x5a, 8}, // "01011010"
{58, 0x5b, 8}, // "01011011"
{59, 0x4a, 8}, // "01001010"
{60, 0x4b, 8}, // "01001011"
{61, 0x32, 8}, // "00110010"
{62, 0x33, 8}, // "00110011"
{63, 0x34, 8}, // "00110100"
}; // g_encWhiteTerm
const HuffmanEncoding g_encWhiteMakeup[] = {
{64, 0x1b, 5}, // "11011"
{128, 0x12, 5}, // "10010"
{192, 0x17, 6}, // "010111"
{256, 0x37, 7}, // "0110111"
{320, 0x36, 8}, // "00110110"
{384, 0x37, 8}, // "00110111"
{448, 0x64, 8}, // "01100100"
{512, 0x65, 8}, // "01100101"
{576, 0x68, 8}, // "01101000"
{640, 0x67, 8}, // "01100111"
{704, 0xcc, 9}, // "011001100"
{768, 0xcd, 9}, // "011001101"
{832, 0xd2, 9}, // "011010010"
{896, 0xd3, 9}, // "011010011"
{960, 0xd4, 9}, // "011010100"
{1024, 0xd5, 9}, // "011010101"
{1088, 0xd6, 9}, // "011010110"
{1152, 0xd7, 9}, // "011010111"
{1216, 0xd8, 9}, // "011011000"
{1280, 0xd9, 9}, // "011011001"
{1344, 0xda, 9}, // "011011010"
{1408, 0xdb, 9}, // "011011011"
{1472, 0x98, 9}, // "010011000"
{1536, 0x99, 9}, // "010011001"
{1600, 0x9a, 9}, // "010011010"
{1664, 0x18, 6}, // "011000"
{1728, 0x9b, 9}, // "010011011"
}; // g_encWhiteMakeup
const HuffmanEncoding g_encBlackTerm[] = {
{0, 0x37, 10}, // "0000110111"
{1, 0x02, 3}, // "010"
{2, 0x03, 2}, // "11"
{3, 0x02, 2}, // "10"
{4, 0x03, 3}, // "011"
{5, 0x03, 4}, // "0011"
{6, 0x02, 4}, // "0010"
{7, 0x03, 5}, // "00011"
{8, 0x05, 6}, // "000101"
{9, 0x04, 6}, // "000100"
{10, 0x04, 7}, // "0000100"
{11, 0x05, 7}, // "0000101"
{12, 0x07, 7}, // "0000111"
{13, 0x04, 8}, // "00000100"
{14, 0x07, 8}, // "00000111"
{15, 0x18, 9}, // "000011000"
{16, 0x17, 10}, // "0000010111"
{17, 0x18, 10}, // "0000011000"
{18, 0x08, 10}, // "0000001000"
{19, 0x67, 11}, // "00001100111"
{20, 0x68, 11}, // "00001101000"
{21, 0x6c, 11}, // "00001101100"
{22, 0x37, 11}, // "00000110111"
{23, 0x28, 11}, // "00000101000"
{24, 0x17, 11}, // "00000010111"
{25, 0x18, 11}, // "00000011000"
{26, 0xca, 12}, // "000011001010"
{27, 0xcb, 12}, // "000011001011"
{28, 0xcc, 12}, // "000011001100"
{29, 0xcd, 12}, // "000011001101"
{30, 0x68, 12}, // "000001101000"
{31, 0x69, 12}, // "000001101001"
{32, 0x6a, 12}, // "000001101010"
{33, 0x6b, 12}, // "000001101011"
{34, 0xd2, 12}, // "000011010010"
{35, 0xd3, 12}, // "000011010011"
{36, 0xd4, 12}, // "000011010100"
{37, 0xd5, 12}, // "000011010101"
{38, 0xd6, 12}, // "000011010110"
{39, 0xd7, 12}, // "000011010111"
{40, 0x6c, 12}, // "000001101100"
{41, 0x6d, 12}, // "000001101101"
{42, 0xda, 12}, // "000011011010"
{43, 0xdb, 12}, // "000011011011"
{44, 0x54, 12}, // "000001010100"
{45, 0x55, 12}, // "000001010101"
{46, 0x56, 12}, // "000001010110"
{47, 0x57, 12}, // "000001010111"
{48, 0x64, 12}, // "000001100100"
{49, 0x65, 12}, // "000001100101"
{50, 0x52, 12}, // "000001010010"
{51, 0x53, 12}, // "000001010011"
{52, 0x24, 12}, // "000000100100"
{53, 0x37, 12}, // "000000110111"
{54, 0x38, 12}, // "000000111000"
{55, 0x27, 12}, // "000000100111"
{56, 0x28, 12}, // "000000101000"
{57, 0x58, 12}, // "000001011000"
{58, 0x59, 12}, // "000001011001"
{59, 0x2b, 12}, // "000000101011"
{60, 0x2c, 12}, // "000000101100"
{61, 0x5a, 12}, // "000001011010"
{62, 0x66, 12}, // "000001100110"
{63, 0x67, 12}, // "000001100111"
}; // g_encBlackTerm
const HuffmanEncoding g_encBlackMakeup[] = {
{64, 0x0f, 10}, // "0000001111"
{128, 0xc8, 12}, // "000011001000"
{192, 0xc9, 12}, // "000011001001"
{256, 0x5b, 12}, // "000001011011"
{320, 0x33, 12}, // "000000110011"
{384, 0x34, 12}, // "000000110100"
{448, 0x35, 12}, // "000000110101"
{512, 0x6c, 13}, // "0000001101100"
{576, 0x6d, 13}, // "0000001101101"
{640, 0x4a, 13}, // "0000001001010"
{704, 0x4b, 13}, // "0000001001011"
{768, 0x4c, 13}, // "0000001001100"
{832, 0x4d, 13}, // "0000001001101"
{896, 0x72, 13}, // "0000001110010"
{960, 0x73, 13}, // "0000001110011"
{1024, 0x74, 13}, // "0000001110100"
{1088, 0x75, 13}, // "0000001110101"
{1152, 0x76, 13}, // "0000001110110"
{1216, 0x77, 13}, // "0000001110111"
{1280, 0x52, 13}, // "0000001010010"
{1344, 0x53, 13}, // "0000001010011"
{1408, 0x54, 13}, // "0000001010100"
{1472, 0x55, 13}, // "0000001010101"
{1536, 0x5a, 13}, // "0000001011010"
{1600, 0x5b, 13}, // "0000001011011"
{1664, 0x64, 13}, // "0000001100100"
{1728, 0x65, 13}, // "0000001100101"
}; // g_encBlackMakeup
const HuffmanEncoding g_encBothMakeup[] = {
{1792, 0x08, 11}, // "00000001000"
{1856, 0x0c, 11}, // "00000001100"
{1920, 0x0d, 11}, // "00000001101"
{1984, 0x12, 12}, // "000000010010"
{2048, 0x13, 12}, // "000000010011"
{2112, 0x14, 12}, // "000000010100"
{2176, 0x15, 12}, // "000000010101"
{2240, 0x16, 12}, // "000000010110"
{2304, 0x17, 12}, // "000000010111"
{2368, 0x1c, 12}, // "000000011100"
{2432, 0x1d, 12}, // "000000011101"
{2496, 0x1e, 12}, // "000000011110"
{2560, 0x1f, 12}, // "000000011111"
}; // g_encBothMakeup
DecodeTree::DecodeTree(bool bwhite)
{
finitStatus = B_ERROR;
fptop = new DecodeNode;
if (fptop) {
fptop->value = -1;
fptop->branches[0] = NULL;
fptop->branches[1] = NULL;
}
if (bwhite)
finitStatus = LoadWhiteEncodings();
else
finitStatus = LoadBlackEncodings();
} else
finitStatus = B_NO_MEMORY;
}
void
@ -58,11 +278,65 @@ DecodeTree::~DecodeTree()
}
}
status_t
DecodeTree::LoadBlackEncodings()
{
status_t result = B_ERROR;
result = AddEncodings(g_encBlackTerm,
sizeof(g_encBlackTerm) / sizeof(HuffmanEncoding));
if (result != B_OK)
return result;
result = AddEncodings(g_encBlackMakeup,
sizeof(g_encBlackMakeup) / sizeof(HuffmanEncoding));
if (result != B_OK)
return result;
result = AddEncodings(g_encBothMakeup,
sizeof(g_encBothMakeup) / sizeof(HuffmanEncoding));
return result;
}
status_t
DecodeTree::LoadWhiteEncodings()
{
status_t result = B_ERROR;
result = AddEncodings(g_encWhiteTerm,
sizeof(g_encWhiteTerm) / sizeof(HuffmanEncoding));
if (result != B_OK)
return result;
result = AddEncodings(g_encWhiteMakeup,
sizeof(g_encWhiteMakeup) / sizeof(HuffmanEncoding));
if (result != B_OK)
return result;
result = AddEncodings(g_encBothMakeup,
sizeof(g_encBothMakeup) / sizeof(HuffmanEncoding));
return result;
}
status_t
DecodeTree::AddEncodings(const HuffmanEncoding *pencs, uint32 length)
{
status_t result = B_ERROR;
for (uint32 i = 0; i < length; i++) {
result = AddEncoding(pencs[i].encoding, pencs[i].length,
pencs[i].value);
if (result != B_OK)
break;
}
return result;
}
status_t
DecodeTree::AddEncoding(uint16 encoding, uint8 length, uint16 value)
{
if (!fptop)
return B_NO_MEMORY;
if (!length || length > 16)
return B_BAD_VALUE;
@ -101,32 +375,24 @@ DecodeTree::AddEncoding(uint16 encoding, uint8 length, uint16 value)
}
status_t
DecodeTree::GetValue(uint16 encdata, uint8 nbits, uint8 &bitsread) const
DecodeTree::GetValue(BitReader &stream) const
{
if (!fptop)
return B_NO_MEMORY;
if (!nbits || nbits > 16)
return B_BAD_VALUE;
if (InitCheck() != B_OK)
return InitCheck();
uint32 branch;
status_t branch;
DecodeNode *pnode = fptop;
bitsread = 0;
while (bitsread < nbits) {
branch = (encdata >> (16 - (bitsread + 1))) & 1;
if (!pnode->branches[branch])
// if I can't go any further, I've either successfully
// decoded some bits or I'm returning -1
while (pnode) {
branch = stream.NextBit();
if (branch < 0)
return branch;
pnode = pnode->branches[branch];
if (!pnode)
return B_ERROR;
else if (pnode->value > -1)
return pnode->value;
else {
pnode = pnode->branches[branch];
bitsread++;
if (bitsread == nbits)
return pnode->value;
}
}
return B_ERROR;
}

View File

@ -32,7 +32,17 @@
#define DECODE_TREE_H
#include <SupportDefs.h>
#include "BitReader.h"
// structure used to populate
// the decode trees
struct HuffmanEncoding {
uint16 value;
uint8 encoding;
uint8 length;
};
// node used by the decode tree
struct DecodeNode {
int16 value;
DecodeNode *branches[2];
@ -40,13 +50,27 @@ struct DecodeNode {
class DecodeTree {
public:
DecodeTree();
DecodeTree(bool bwhite);
~DecodeTree();
status_t AddEncoding(uint16 encoding, uint8 length, uint16 value);
status_t GetValue(uint16 encdata, uint8 nbits, uint8 &bitsread) const;
// returns B_OK if the tree was initialized without error,
// returns B_ERROR or B_NO_MEMORY if unable to initialize
status_t InitCheck() const { return finitStatus; };
// Decodes nbits bits from encdata, starting with the
// highest order bit. If successful, returns the corresponding
// value for the encdata and bitsread contains the
// number of bits from encdata that were decoded. If not successful,
// B_ERROR, B_NO_MEMORY or B_BAD_VALUE is returned
status_t GetValue(BitReader &stream) const;
private:
private:
status_t LoadBlackEncodings();
status_t LoadWhiteEncodings();
status_t AddEncodings(const HuffmanEncoding *pencs, uint32 length);
status_t AddEncoding(uint16 encoding, uint8 length, uint16 value);
status_t finitStatus;
DecodeNode *fptop;
};

View File

@ -5,6 +5,8 @@ SEARCH_SOURCE += [ FDirName $(OBOS_TOP) src add-ons translators tgatranslator ]
Translator TIFFTranslator :
StreamBuffer.cpp
BitReader.cpp
DecodeTree.cpp
TiffField.cpp
TiffUintField.cpp
TiffUnknownField.cpp

View File

@ -35,6 +35,7 @@
#include "TIFFView.h"
#include "TiffIfd.h"
#include "StreamBuffer.h"
#include "BitReader.h"
// The input formats that this translator supports.
translation_format gInputFormats[] = {
@ -124,6 +125,9 @@ make_nth_translator(int32 n, image_id you, uint32 flags, ...)
TIFFTranslator::TIFFTranslator()
: BTranslator()
{
fpblackTree = NULL;
fpwhiteTree = NULL;
strcpy(fName, "TIFF Images");
sprintf(fInfo, "TIFF image translator v%d.%d.%d %s",
TIFF_TRANSLATOR_VERSION / 100, (TIFF_TRANSLATOR_VERSION / 10) % 10,
@ -401,6 +405,7 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
else
dtls.compression = ifd.GetUint(TAG_COMPRESSION);
if (dtls.compression != COMPRESSION_NONE &&
dtls.compression != COMPRESSION_HUFFMAN &&
dtls.compression != COMPRESSION_PACKBITS)
return B_NO_TRANSLATOR;
@ -498,7 +503,8 @@ check_tiff_fields(TiffIfd &ifd, TiffDetails *pdetails)
status_t
identify_tiff_header(BPositionIO *inSource, translator_info *outInfo,
ssize_t amtread, uint8 *read, swap_action swp, TiffDetails *pdetails = NULL)
ssize_t amtread, uint8 *read, swap_action swp,
TiffDetails *pdetails = NULL)
{
if (amtread != 4)
return B_ERROR;
@ -509,7 +515,8 @@ identify_tiff_header(BPositionIO *inSource, translator_info *outInfo,
printf("Unable to read first IFD offset\n");
return B_NO_TRANSLATOR;
}
if (swap_data(B_UINT32_TYPE, &firstIFDOffset, sizeof(uint32), swp) != B_OK) {
if (swap_data(B_UINT32_TYPE, &firstIFDOffset,
sizeof(uint32), swp) != B_OK) {
printf("swap_data() error\n");
return B_ERROR;
}
@ -765,9 +772,60 @@ unpack(StreamBuffer *pstreambuf, uint8 *tiffbuffer, uint32 tiffbufferlen)
return read;
}
ssize_t
TIFFTranslator::decode_huffman(StreamBuffer *pstreambuf, TiffDetails &details,
uint8 *pbits)
{
BitReader stream(pstreambuf);
if (stream.InitCheck() != B_OK) {
debugger("stream init error");
return B_ERROR;
}
const uint8 kblack = 0x00, kwhite = 0xff;
uint8 colors[2];
if (details.interpretation == PHOTO_WHITEZERO) {
colors[0] = kwhite;
colors[1] = kblack;
} else {
colors[0] = kblack;
colors[1] = kwhite;
}
uint32 pixelswrit = 0;
DecodeTree *ptrees[2] = {fpwhiteTree, fpblackTree};
uint8 currentcolor = 0;
uint8 *pcurrentpixel = pbits;
while (pixelswrit < details.width) {
status_t value = ptrees[currentcolor]->GetValue(stream);
if (value < 0) {
debugger("value < 0");
return B_ERROR;
}
if (pixelswrit + value > details.width) {
debugger("gone past end of line");
return B_ERROR;
}
pixelswrit += value;
// covert run length to B_RGB32 pixels
uint32 pixelsleft = value;
while (pixelsleft--) {
memset(pcurrentpixel, colors[currentcolor], 3);
pcurrentpixel += 4;
}
if (value < 64)
currentcolor = 1 - currentcolor;
}
return stream.BytesRead();
}
status_t
translate_from_tiff(BPositionIO *inSource, ssize_t amtread, uint8 *read,
swap_action swp, uint32 outType, BPositionIO *outDestination)
TIFFTranslator::translate_from_tiff(BPositionIO *inSource, ssize_t amtread,
uint8 *read, swap_action swp, uint32 outType, BPositionIO *outDestination)
{
// Can only output to bits for now
if (outType != B_TRANSLATOR_BITMAP)
@ -781,6 +839,14 @@ translate_from_tiff(BPositionIO *inSource, ssize_t amtread, uint8 *read,
if (result == B_OK) {
// If the TIFF is supported by this translator
// If TIFF uses Huffman compression, load
// trees for decoding Huffman compression
if (details.compression == COMPRESSION_HUFFMAN) {
result = LoadHuffmanTrees();
if (result != B_OK)
return result;
}
TranslatorBitmap bitsHeader;
bitsHeader.magic = B_TRANSLATOR_BITMAP;
bitsHeader.bounds.left = 0;
@ -828,18 +894,18 @@ translate_from_tiff(BPositionIO *inSource, ssize_t amtread, uint8 *read,
// buffer for making reading compressed data
// fast and convenient
StreamBuffer *pstreambuf = NULL;
if (details.compression == COMPRESSION_PACKBITS) {
if (details.compression != COMPRESSION_NONE) {
pstreambuf = new StreamBuffer(inSource, 2048, false);
if (pstreambuf->InitCheck() != B_OK)
return B_NO_MEMORY;
return B_NO_MEMORY;
}
for (uint32 i = 0; i < details.stripsPerImage; i++) {
uint32 read = 0;
// If Packbits compression, prepare streambuffer
// If using compression, prepare streambuffer
// for reading
if (details.compression == COMPRESSION_PACKBITS &&
if (details.compression != COMPRESSION_NONE &&
!pstreambuf->Seek(details.pstripOffsets[i]))
return B_NO_TRANSLATOR;
@ -848,25 +914,47 @@ translate_from_tiff(BPositionIO *inSource, ssize_t amtread, uint8 *read,
while (read < details.pstripByteCounts[i]) {
ssize_t ret = 0;
if (details.compression == COMPRESSION_NONE) {
ret = inSource->ReadAt(details.pstripOffsets[i] + read,
inbuffer, inbufferlen);
if (ret != static_cast<ssize_t>(inbufferlen))
switch (details.compression) {
case COMPRESSION_NONE:
ret = inSource->ReadAt(details.pstripOffsets[i] + read,
inbuffer, inbufferlen);
if (ret != static_cast<ssize_t>(inbufferlen))
// break out of while loop
ret = -1;
break;
case COMPRESSION_HUFFMAN:
ret = decode_huffman(pstreambuf, details, outbuffer);
if (ret < 1)
// break out of while loop
ret = -1;
break;
} else if (details.compression == COMPRESSION_PACKBITS) {
ret = unpack(pstreambuf, inbuffer, inbufferlen);
if (ret < 1)
case COMPRESSION_PACKBITS:
ret = unpack(pstreambuf, inbuffer, inbufferlen);
if (ret < 1)
// break out of while loop
ret = -1;
break;
}
if (ret < 0)
break;
read += ret;
tiff_to_bits(inbuffer, inbufferlen, outbuffer, details);
if (details.compression != COMPRESSION_HUFFMAN)
tiff_to_bits(inbuffer, inbufferlen, outbuffer, details);
outDestination->Write(outbuffer, outbufferlen);
}
// If while loop was broken...
if (read < details.pstripByteCounts[i])
if (read < details.pstripByteCounts[i]) {
printf("-- WHILE LOOP BROKEN!!\n");
printf("i: %d\n", i);
printf("ByteCount: %d\n",
details.pstripByteCounts[i]);
printf("read: %d\n", read);
debugger("while loop broken");
break;
}
}
// Clean up
@ -1034,3 +1122,26 @@ TIFFTranslator::MakeConfigurationView(BMessage *ioExtension, BView **outView,
return B_OK;
}
// Initialize the Huffman decoding trees and
// verify that there were no initialization errors
status_t
TIFFTranslator::LoadHuffmanTrees()
{
if (!fpblackTree) {
fpblackTree = new DecodeTree(false);
if (!fpblackTree)
return B_NO_MEMORY;
}
if (!fpwhiteTree) {
fpwhiteTree = new DecodeTree(true);
if (!fpwhiteTree)
return B_NO_MEMORY;
}
if (fpblackTree->InitCheck() != B_OK)
return fpblackTree->InitCheck();
return fpwhiteTree->InitCheck();
}

View File

@ -41,6 +41,7 @@
#include <File.h>
#include <ByteOrder.h>
#include <fs_attr.h>
#include "DecodeTree.h"
#define TIFF_TRANSLATOR_VERSION 100
@ -122,6 +123,18 @@ protected:
// the user
private:
status_t LoadHuffmanTrees();
ssize_t decode_huffman(StreamBuffer *pstreambuf, TiffDetails &details,
uint8 *pbits);
status_t translate_from_tiff(BPositionIO *inSource, ssize_t amtread,
uint8 *read, swap_action swp, uint32 outType,
BPositionIO *outDestination);
DecodeTree *fpblackTree;
DecodeTree *fpwhiteTree;
char fName[30];
char fInfo[100];
};

View File

@ -66,7 +66,7 @@
#define TAG_ORIENTATION 274
#define TAG_SAMPLES_PER_PIXEL 277
#define TAG_ROWS_PER_STRIP 278
#define DEFAULT_ROWS_PER_STRIP 4294967295L
#define DEFAULT_ROWS_PER_STRIP 4294967295UL
#define TAG_STRIP_BYTE_COUNTS 279
#define TAG_PLANAR_CONFIGURATION 284
#define TAG_RESOLUTION_UNIT 296