Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
2 / 2 / 0
Регистрация: 24.05.2016
Сообщений: 88

LZW версия для декомпрессии TIFF (COMPRESSION_TAG = 5)

08.09.2021, 14:01. Показов 862. Ответов 0
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день уважаемые форумчане, столкнулся с следующей проблемой:
Необходимо реализовать распаковку схемой компрессии LZW применимо к файлам формата TIFF .
Написать её - написал, но результат удручает, для сравнения привожу вложение (слева результат работы моего декодера, а справа просмотрщик фотографий win7) ... и такая, в общем то, беда на других тестовых примерах.

Что говорит спецификация на формат:
Кликните здесь для просмотра всего текста


Whenever you add a code to the output stream, it “counts” toward the decision about bumping the code bit length. This is important when writing the last code word before an EOI code or ClearCode, to avoid code length errors.

What happens if we run out of room in our string table? This is where the ClearCode comes in. As soon as we use entry 4094, we write out a (12-bit) ClearCode. (If we wait any longer to write the ClearCode, the decompressor might try to interpret the ClearCode as a 13-bit code.) At this point, the compressor reinitializes the string table and then writes out 9-bit codes again.

Note that whenever you write a code and add a table entry, W is not left empty. It contains exactly one character. Be careful not to lose it when you write an end-oftable ClearCode. You can either write it out as a 12-bit code before writing the ClearCode, in which case you need to do it right after adding table entry 4093, or you can write it as a 9-bit code after the ClearCode . Decompression gives the same result in either case.

To make things a little simpler for the decompressor, we will require that each strip begins with a ClearCode and ends with an EndOfInformation code. Every LZW-compressed strip must begin on a byte boundary. It need not begin on a word boundary. LZW compression codes are stored into bytes in high-to-loworder fashion, i.e., FillOrder is assumed to be 1. The compressed codes are written as bytes (not words) so that the compressed data will be identical whether it is an ‘II’ or ‘MM’ file.

Note that the LZW string table is a continuously updated history of the strings that have been encountered in the data. Thus, it reflects the characteristics of the data, providing a high degree of adaptability.

The procedure for decompression is a little more complicated:
Кликните здесь для просмотра всего текста

C
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
while ((Code = GetNextCode()) != EoiCode) 
{
    if (Code == ClearCode) 
    {
        InitializeTable();
        Code = GetNextCode();
        if (Code == EoiCode)
            break;
        WriteString(StringFromCode(Code));
        OldCode = Code;
    } /* end of ClearCode case */
    else 
    {
        if (IsInTable(Code)) 
        {
            WriteString(StringFromCode(Code));
            AddStringToTable(StringFromCode(OldCode)+FirstChar(StringFromCode(Code)));
            OldCode = Code;
        } 
        else 
        {
            OutString = StringFromCode(OldCode) + FirstChar(StringFromCode(OldCode));
            WriteString(OutString);
            AddStringToTable(OutString);
            OldCode = Code;
        }
    } /* end of not-ClearCode case */
} /* end of while loop */


The function GetNextCode() retrieves the next code from the LZW-coded data. It must keep track of bit boundaries. It knows that the first code that it gets will be a 9-bit code. We add a table entry each time we get a code. So, GetNextCode() must switch over to 10-bit codes as soon as string #510 is stored into the table. Similarly, the switch is made to 11-bit codes after #1022 and to 12-bit codes after #2046.

The function StringFromCode() gets the string associated with a particular code from the string table.
The function AddStringToTable() adds a string to the string table. The “+” sign joining the two parts of the argument to AddStringToTable indicates string concatenation. StringFromCode() looks up the string associated with a given code. WriteString() adds a string to the output stream.


Вот что я наваял:

Класс для нарезки бит:

Кликните здесь для просмотра всего текста

C++
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    template <typename SourceDataType>
    class BitsSlicer
    {
    private:
        SourceDataType                _sequenceComponent; ///< Элемент массива.
        unsigned long long int             _currentIndex; ///< Индекс текущего элемента.
        const SourceDataType                  *_ptrArray; ///< Указатель на данные.
        unsigned long long int                     _size; ///< Размер ресурса.
        unsigned int                         _sizeOfBits; ///< Размер типа данных в битах.
        unsigned int             _bitInSequenceComponent; ///< Остаток бит на текущий раунд.
        bool                                   _bitOrder; ///< Порядок бит(false - слева направо, true - справа налево).
        std::string                           _bitBuffer; ///< Битовый буфер в виде STL строки.
        static const unsigned char _reverseBitTable[256]; ///< Таблица инвертированных битов байта.
 
    public:
        BitsSlicer(const SourceDataType *ptrArray, const unsigned long long int size, bool bitOrder = false)
        : _sequenceComponent(0),
          _currentIndex(0),
          _ptrArray(ptrArray),
          _size(size),
          _sizeOfBits(sizeof(SourceDataType) * 8u),
          _bitInSequenceComponent(sizeof(SourceDataType) * 8u),
          _bitOrder(bitOrder),
          _bitBuffer("")
        {
            this->_sequenceComponent = this->_ptrArray[0];
            if (this->_bitOrder)
                this->reverseBitsInByts();
        }
       ~BitsSlicer()
        {
            this->_sequenceComponent      = 0;
            this->_currentIndex           = 0;
            this->_ptrArray               = nullptr;
            this->_size                   = 0;
            this->_sizeOfBits             = 0;
            this->_bitInSequenceComponent = 0;
            this->_bitBuffer              = "";
        }
        void reset()
        {
            this->_currentIndex           = 0;
            this->_bitBuffer              = "";
            this->_sequenceComponent      = this->_ptrArray[0];
            this->_bitInSequenceComponent = this->_sizeOfBits;
 
            if (this->_bitOrder)
                this->reverseBitsInByts();
        }
        bool jumpOverBeats(unsigned int numberOfBits)
        {
            if (numberOfBits <= this->_bitInSequenceComponent)
            {
                this->_bitInSequenceComponent -= numberOfBits;
                return true;
            }
            else
            {
                numberOfBits -= this->_bitInSequenceComponent;
 
                unsigned int coefficient = numberOfBits / this->_sizeOfBits;
 
                numberOfBits -= coefficient * this->_sizeOfBits;
                this->_currentIndex += coefficient + 1;
                this->_bitInSequenceComponent = this->_sizeOfBits - numberOfBits;
 
                if (this->_currentIndex >= this->_size)
                    return false;
 
                this->_sequenceComponent = this->_ptrArray[this->_currentIndex];
                return true;
            }
        }
        bool shiftToByteBoundary()
        {
            return this->jumpOverBeats(this->_bitInSequenceComponent % 8u);
        }
        template<typename BufferDataType>
        bool cutBits(BufferDataType &buffer, unsigned int numberOfBits)
        {
            if ((sizeof(BufferDataType) * 8u) < numberOfBits || !numberOfBits)
                return false;
 
            SourceDataType tempSequence(0);
 
            //обратный и прямой порядок бит
            while(numberOfBits)
            {
                if (!this->_bitInSequenceComponent)
                {
                    if (++this->_currentIndex >= this->_size)
                        return false;
 
                    this->_bitInSequenceComponent = this->_sizeOfBits;
                    this->_sequenceComponent      = this->_ptrArray[this->_currentIndex];
 
                    if (this->_bitOrder)
                        this->reverseBitsInByts();
                }
 
                tempSequence = this->_sequenceComponent;
 
                unsigned int bitCountsInRound
                                   = this->_bitInSequenceComponent <= numberOfBits
                                   ? this->_bitInSequenceComponent
                                   : numberOfBits;
 
                tempSequence <<= (this->_sizeOfBits - this->_bitInSequenceComponent);
                tempSequence >>= (this->_sizeOfBits - bitCountsInRound);
                (buffer <<= bitCountsInRound) |= tempSequence;
 
                this->_bitInSequenceComponent -= bitCountsInRound;
                numberOfBits                  -= bitCountsInRound;
            }
            return true;
        }
 
    private:
        void reverseBitsInByts()
        {
            if (!(8 ^ this->_sizeOfBits))
            {
                this->_sequenceComponent = this->_reverseBitTable[this->_sequenceComponent];
                return;
            }
 
            unsigned char begin  = 0;
            unsigned char end    = sizeof(SourceDataType);
            unsigned char *bytes = reinterpret_cast<unsigned char *>(&this->_sequenceComponent);
            for (;;)
            {
                --end;
                bytes[begin]  = this->_reverseBitTable[bytes[begin]];
                bytes[end]    = this->_reverseBitTable[bytes[end]];
                bytes[begin] ^= bytes[end];
                bytes[end]   ^= bytes[begin];
                bytes[begin] ^= bytes[end];
                ++begin;
                if (!(begin ^ end))
                    return;
            }
        }
    };
    template <typename SourceDataType>
    const unsigned char BitsSlicer<SourceDataType>::_reverseBitTable[256] =
    {
        0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
        0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
        0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
        0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
        0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
        0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
        0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
        0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
        0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
        0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
        0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
        0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
        0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
        0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
        0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
        0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
    };



Кодек для LZW:

Кликните здесь для просмотра всего текста

C++
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
    class LZWScheme
    {
    private:
        class Dictionary
        {
        private:
        #pragma pack(1)
            struct entry
            {
                unsigned int  _value;       // строка
                unsigned int  _code;        // порядковый номер или код
                unsigned char _numberOfBits;// количество бит
            };
        #pragma pack()
 
        public:
            Dictionary(void):
            _numberOfEntrys(0),
            _validElements(0),
            _entrys(nullptr)
            {
                this->reset();
            }
           ~Dictionary(void)
            {
                this->_numberOfEntrys = 0;
                this->_validElements = 0;
                delete []this->_entrys;
                this->_entrys = nullptr;
            }
            void reset(void)
            {
                this->_numberOfEntrys = 4096;
                this->_validElements  = 0;
 
                if (this->_entrys)
                    delete [] this->_entrys;
 
                this->_entrys = new entry[this->_numberOfEntrys];
 
                std::memset(this->_entrys, 0, sizeof(entry) * this->_numberOfEntrys);
 
                for (unsigned int indxEntry(0); indxEntry < 258; ++indxEntry)
                    this->addEntry(indxEntry);
            }
            bool checkCode(const unsigned int code)
            {
                if (!this->_entrys)
                    throw "entrys is empty!";
 
                if (!this->_numberOfEntrys)
                    throw "number of entrys is null!";
 
                if (!this->_validElements)
                    throw "number of valid elements is null!";
 
                if (this->_numberOfEntrys <= code)
                    throw "the code is more than the number of valid records!";
 
                if (this->_validElements - 1 < code)
                    return false;
 
                if (this->_entrys[code]._code == code)
                    return true;
 
                return false;
            }
            bool checkValue(const unsigned int value)
            {
                if (!this->_entrys)
                    throw "entrys is empty!";
 
                if (!this->_numberOfEntrys)
                    throw "number of entrys is null!";
 
                if (!this->_validElements)
                    throw "number of valid elements is null!";
 
                for (unsigned int indxEntry(0); indxEntry < this->_validElements; ++indxEntry)
                    if (this->_entrys[indxEntry]._value == value)
                        return true;
 
                return false;
            }
            bool checkValue(const std::string value)
            {
                if (!this->_entrys)
                    throw "entrys is empty!";
 
                if (!this->_numberOfEntrys)
                    throw "number of entrys is null!";
 
                if (!this->_validElements)
                    throw "number of valid elements is null!";
 
                unsigned int tmp(0);
                std::memcpy(&tmp, value.data(), value.size());
 
                for (unsigned int indxEntry(0); indxEntry < this->_validElements; ++indxEntry)
                    if (this->_entrys[indxEntry]._value == tmp)
                        return true;
 
                return false;
            }
            bool addEntry(const unsigned int value)
            {
                if (this->_validElements + 1 > this->_numberOfEntrys)
                    return false;
 
                this->_entrys[this->_validElements]._code = this->_validElements;
                this->_entrys[this->_validElements]._value = value;
 
                unsigned char pow = 1;
                unsigned int number = this->_validElements;
                while(number >>= 1)
                    ++pow;
 
                this->_entrys[this->_validElements]._numberOfBits = pow;
 
                ++this->_validElements;
                return true;
            }
            bool addEntry(const std::string value)
            {
                if (this->_validElements + 1 > this->_numberOfEntrys)
                    return false;
 
                unsigned int tmp(0);
                std::memcpy(&tmp, value.data(), value.size());
 
                this->_entrys[this->_validElements]._code = this->_validElements;
                this->_entrys[this->_validElements]._value = tmp;
 
                unsigned char pow = 1;
                unsigned int number = this->_validElements;
                while(number >>= 1)
                    ++pow;
 
                this->_entrys[this->_validElements]._numberOfBits = pow;
 
                ++this->_validElements;
                return true;
            }
            unsigned int getNumberOfValidElements(void)
            {
                return this->_validElements;
            }
            void printValidTable(void)
            {
                for (unsigned int indx = 0; indx < this->_validElements; ++indx)
                    std::cout << "# "
                              << this->_entrys[indx]._code << "\t  "
                              << "#^k, k = "
                              << (int)this->_entrys[indx]._numberOfBits << "\t  "
                              << "value = "
                              << std::string(reinterpret_cast<char *>(&this->_entrys[indx]._value), this->_entrys[indx]._numberOfBits / 8 + (this->_entrys[indx]._numberOfBits % 8 ? 1 : 0))
                              << std::endl;
            }
            unsigned int getCodeByValue(const unsigned int value)
            {
                if (!this->_entrys)
                    throw "entrys is empty!";
 
                if (!this->_numberOfEntrys)
                    throw "number of entrys is null!";
 
                for (unsigned int indxEntry(0); indxEntry < this->_validElements; ++indxEntry)
                    if (this->_entrys[indxEntry]._value == value)
                        return this->_entrys[indxEntry]._code;
 
                return 0;
            }
            unsigned int getCodeByValue(const std::string value)
            {
                if (!this->_entrys)
                    throw "entrys is empty!";
 
                if (!this->_numberOfEntrys)
                    throw "number of entrys is null!";
 
                unsigned int tmp(0);
                std::memcpy(&tmp, value.data(), value.size());
 
                for (unsigned int indxEntry(0); indxEntry < this->_validElements; ++indxEntry)
                    if (this->_entrys[indxEntry]._value == tmp)
                        return this->_entrys[indxEntry]._code;
 
                return 0;
            }
            unsigned int getValueByCode(const unsigned int code)
            {
                if (this->checkCode(code))
                    return this->_entrys[code]._value;
 
                return 0;
            }
            std::string getSTLValueByCode(const unsigned int code)
            {
                if (this->checkCode(code))
                {
                    return std::string(
                        reinterpret_cast<char *>(&this->_entrys[code]._value),
                        this->_entrys[code]._numberOfBits / 8 +
                            (this->_entrys[code]._numberOfBits % 8 ? 1 : 0));
                }
 
                return std::string("");
            }
            unsigned char getNumberOfBitsByValue(const unsigned int value)
            {
                if (!this->_entrys)
                    throw "entrys is empty!";
 
                if (!this->_numberOfEntrys)
                    throw "number of entrys is null!";
 
                for (unsigned int indxEntry(0); indxEntry < this->_validElements; ++indxEntry)
                    if (this->_entrys[indxEntry]._value == value)
                        return this->_entrys[indxEntry]._numberOfBits;
 
                return 0;
            }
            unsigned char getNumberOfBitsByValue(const std::string value)
            {
                if (!this->_entrys)
                    throw "entrys is empty!";
 
                if (!this->_numberOfEntrys)
                    throw "number of entrys is null!";
 
                unsigned int tmp(0);
                std::memcpy(&tmp, value.data(), value.size());
 
                for (unsigned int indxEntry(0); indxEntry < this->_validElements; ++indxEntry)
                    if (this->_entrys[indxEntry]._value == tmp)
                        return this->_entrys[indxEntry]._numberOfBits;
 
                return 0;
            }
            unsigned char getNumberOfBitsByCode(const unsigned int code)
            {
                if (this->checkCode(code))
                    return this->_entrys[code]._numberOfBits;
 
                return 0;
            }
        private:
            unsigned int _numberOfEntrys;
            unsigned int _validElements;
            entry *_entrys;
        };
 
    public:
        enum Codes : unsigned int
        {
            Clear            = 256,
            EndOfInformation = 257
        };
 
        bool HF::LZWScheme::decode(char *encodedSource, unsigned long long int encodedSize,
                                   char *decodedSource, unsigned long long int decodedSize)
        {
            if (!encodedSource || !encodedSize || !decodedSource || !decodedSize)
                return false;
        
            std::memset(decodedSource, '0', decodedSize);
        
            unsigned char validNumberOfBit(9);
            unsigned int  oldCode(0);
            unsigned int  newCode(0);
            std::string   entry("");
        
            Dictionary *dict = new Dictionary();
            BitsSlicer<unsigned char> slicer(reinterpret_cast<unsigned char *>(encodedSource), encodedSize);
        
            while (slicer.cutBits(newCode, validNumberOfBit))
            {
                if (newCode == Codes::EndOfInformation)
                    break;
        
                if (newCode == Codes::Clear)
                {
                    dict->reset();
                    validNumberOfBit = 9;
                    newCode = 0;
                    if (!slicer.cutBits(newCode, validNumberOfBit))
                        break;
        
                    if (newCode == Codes::EndOfInformation)
                        break;
        
                    entry = dict->getSTLValueByCode(newCode);
        
                    if (decodedSize < entry.size())
                        break;
        
                    std::memcpy(decodedSource, entry.data(), entry.size());
                    decodedSource += entry.size();
                    decodedSize   -= entry.size();
        
                    oldCode       = newCode;
                    newCode       = 0;
                }
                else
                {
                    if (dict->checkCode(newCode))
                    {
                        entry = dict->getSTLValueByCode(newCode);
                        if (decodedSize < entry.size())
                            break;
        
                        std::memcpy(decodedSource, entry.data(), entry.size());
                        decodedSource += entry.size();
                        decodedSize   -= entry.size();
        
                        entry = dict->getSTLValueByCode(oldCode) +
                                dict->getSTLValueByCode(newCode).substr(0, 2);
                    }
                    else
                    {
                        entry = dict->getSTLValueByCode(oldCode) +
                                dict->getSTLValueByCode(oldCode).substr(0, 2);
        
                        if (decodedSize < entry.size())
                            break;
        
                        std::memcpy(decodedSource, entry.data(), entry.size());
                        decodedSource += entry.size();
                        decodedSize   -= entry.size();
                    }
        
                    if (!dict->addEntry(entry))
                        break;
        
                    oldCode       = newCode;
                    newCode       = 0;
                }
                switch (dict->getNumberOfValidElements() - 1)
                {
                    case 510:
                    case 1022:
                    case 2046:
                    case 4093:
                        ++validNumberOfBit;
                        break;
                    default:
                        break;
                }
            }
        
            delete dict;
            return true;
        }
 
    };


Буду благодарен любым советам и предложениям в решении проблемы, т.к. не представляю что я упускаю.

P.S.: пожалуйста без советов заглянуть в сорцы libtiff или её использование.
Миниатюры
LZW версия для декомпрессии TIFF (COMPRESSION_TAG = 5)  
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.09.2021, 14:01
Ответы с готовыми решениями:

программа на С++ для компрессии/декомпрессии файлов
Посоветуйте пожалуйста литературу по этому вопросу,а также посоветуйте какие библиотеки использовать для компрессии,а какие для...

Приложение для декомпрессии аудио файла
подскажите плиз прогу для декомпрессии аудио

Редактор tiff (удаление листа из многостраничного tiff)
необходимо сделать просмотр на форме изображение tiff и кнопку. и при нажатии на кнопку удалить выбранный лист. еще вариант, сделать...

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.09.2021, 14:01
Помогаю со студенческими работами здесь

LZW - восстановление. LZW GIF. C++
Всем привет.. задача такая: не могу понять, алгоритм декодирования LZW.. Необходимо как в этом примере ...

Выполнить процесс сжатия и декомпрессии для последовательности яркостей изображения с использование алгоритма RLE
Здравствуйте. Прошу помочь разобраться с заданием. Необходимо выполнить процесс сжатия и декомпрессии для последовательности...

Какая версия Apache подходит для windows10 ? (версия 2.2.14 не работает)
Подскажите,пожалуйста,какая версия Apache подходит для windows10. При переходе с windows 7 на windows 10 установленная версия 2.2.14 не...

Обычная версия страници VS Версия для печати
Итак. Есть Блог. И получается так, что 80% народу яндекс отпраляет на версии для печати. В чем может быть проблема? Содержание...

LZW для Gif на Delphi 7
:wall: По-порядку: пишу LZW-архиватор (с позволения сказать). Проблема в том, что до сжатия дело не дошло, а уже много проблем. Действую по...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru