tifupp.cpp

Zbigniew Rebacz, 09/22/2013 09:41 PM

Download (33.9 KB)

 
1
#include <Draw/Draw.h>
2
#include "tif.h"
3

    
4
#ifdef PLATFORM_WIN32
5
        #define        tif_int32 long
6
        #define        tif_uint32 unsigned long
7
#else
8
        #define        tif_int32 int
9
        #define        tif_uint32 unsigned int
10
#endif
11

    
12
#define LLOG(x) // LOG(x)
13

    
14
// #define DBGALLOC 1
15

    
16
NAMESPACE_UPP
17

    
18
#if DBGALLOC
19
double total_allocated = 0, total_freed = 0;
20
unsigned alloc_calls = 0, free_calls = 0, realloc_calls = 0;
21
Index<tsize_t> size_index;
22
Vector<int> size_alloc_calls, size_free_calls;
23
int op_id;
24

    
25
void dbgAddAlloc(void *p, tsize_t s)
26
{
27
        ++op_id;
28
        total_allocated += s;
29
        int i = size_index.Find(s);
30
        if(i >= 0)
31
                size_alloc_calls[i]++;
32
        else
33
        {
34
                size_index.Add(s);
35
                size_alloc_calls.Add(1);
36
                size_free_calls.Add(0);
37
        }
38
        LLOG(op_id << " tAlloc(" << s << ") = " << p << ": blks: " << alloc_calls - free_calls << ", alloc = " << total_allocated << ", free = " << total_freed << ", diff = " << (total_allocated - total_freed));
39
}
40

    
41
void dbgAddFree(void *p, tsize_t s)
42
{
43
        ++op_id;
44
        total_freed += s;
45
        int i = size_index.Find(s);
46
        if(i >= 0)
47
                size_free_calls[i]++;
48
        else
49
        {
50
                size_index.Add(s);
51
                size_alloc_calls.Add(0);
52
                size_free_calls.Add(1);
53
        }
54
        LLOG(op_id << " tFree(" << p << ") = " << s << ": blks: " << alloc_calls - free_calls << ", alloc = " << total_allocated << ", free = " << total_freed << ", diff = " << (total_allocated - total_freed));
55
}
56

    
57
void TiffAllocStat()
58
{
59
        for(int i = 0; i < size_index.GetCount(); i++)
60
                if(size_alloc_calls[i] != size_free_calls[i])
61
                        LOG("Alloc/free mismatch: size = " << size_index[i]
62
                        << ", alloc = " << size_alloc_calls[i] << ", frees = " << size_free_calls[i]);
63
}
64
#endif
65

    
66
extern "C" tdata_t _TIFFmalloc(tsize_t s)
67
{
68
        byte *p = new byte[s + 4];
69
        Poke32le(p, s);
70
#if DBGALLOC
71
        alloc_calls++;
72
        dbgAddAlloc(p, s);
73
#endif
74
        return (tdata_t)(p + 4);
75
}
76

    
77
extern "C" void    _TIFFfree(tdata_t p)
78
{
79
        if(p) {
80
                byte *rawp = (byte *)p - 4;
81
#if DBGALLOC
82
                free_calls++;
83
                dbgAddFree(p, Peek32le(rawp));
84
#endif
85
                delete[] (rawp);
86
        }
87
}
88

    
89
extern "C" tdata_t _TIFFrealloc(tdata_t p, tsize_t s)
90
{
91
        int oldsize = (p ? Peek32le((const byte *)p - 4) : 0);
92
        if(s <= oldsize) {
93
                Poke32le((byte *)p - 4, s);
94
                return p;
95
        }
96
        byte *newptr = new byte[s + 4];
97
#if DBGALLOC
98
        alloc_calls++;
99
        dbgAddAlloc(newptr, s);
100
#endif
101
        if(oldsize) {
102
                memcpy(newptr + 4, p, min<int>(oldsize, s));
103
#if DBGALLOC
104
                free_calls++;
105
                dbgAddFree(newptr, oldsize);
106
#endif
107
                delete[] ((byte *)p - 4);
108
        }
109
        Poke32le(newptr, s);
110
        return (tdata_t)(newptr + 4);
111
}
112

    
113
extern "C" void _TIFFmemset(void* p, int v, tsize_t c)           { memset(p, v, c); }
114
extern "C" void _TIFFmemcpy(void* d, const tdata_t s, tsize_t c) { memcpy(d, s, c); }
115
extern "C" int  _TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) { return memcmp(p1, p2, c); }
116

    
117
static void Blt2to4(byte *dest, const byte *src, unsigned count)
118
{
119
        byte b;
120

    
121
#define BLT2_4_4(o) \
122
        b = src[(o)]; \
123
        dest[2 * (o) + 0] = ((b >> 2) & 0x30) | ((b >> 4) & 0x03); \
124
        dest[2 * (o) + 1] = ((b << 2) & 0x30) | (b & 0x03);
125

    
126
        for(unsigned rep = count >> 5; rep; rep--) {
127
                BLT2_4_4(0) BLT2_4_4(1) BLT2_4_4(2) BLT2_4_4(3)
128
                BLT2_4_4(4) BLT2_4_4(5) BLT2_4_4(6) BLT2_4_4(7)
129
                dest += 8 * 2;
130
                src += 8;
131
        }
132
        if(count & 16) {
133
                BLT2_4_4(0) BLT2_4_4(1) BLT2_4_4(2) BLT2_4_4(3)
134
                dest += 4 * 2;
135
                src += 4;
136
        }
137
        if(count & 8) {
138
                BLT2_4_4(0) BLT2_4_4(1)
139
                dest += 2 * 2;
140
                src += 2;
141
        }
142
        if(count & 4) {
143
                BLT2_4_4(0)
144
                dest += 2;
145
                src++;
146
        }
147
        switch(count & 3) {
148
        case 0:
149
                break;
150

    
151
        case 1:
152
                *dest = ((*src >> 2) & 0x30);
153
                break;
154

    
155
        case 2:
156
                *dest = ((*src >> 2) & 0x30) | ((*src >> 4) & 0x03);
157
                break;
158

    
159
        case 3:
160
                *dest++ = ((*src >> 2) & 0x30) | ((*src >> 4) & 0x03);
161
                *dest = (*src << 2) & 0x30;
162
                break;
163
        }
164
}
165

    
166
static void BltPack11(byte *dest, const byte *src, byte bit_shift, unsigned count)
167
{
168
        if(bit_shift == 0)
169
        { // simple case
170
#if defined(CPU_IA32)
171
#define BLT_PACK_11_4(o) *(unsigned *)(dest + (o)) = *(const unsigned *)(src + (o));
172
#else
173
#define BLT_PACK_11_4(o) dest[(o) + 0] = src[(o) + 0]; dest[(o) + 1] = src[(o) + 1]; \
174
        dest[(o) + 2] = src[(o) + 2]; dest[(o) + 3] = src[(o) + 3];
175
#endif
176
                for(unsigned rep = count >> 7; rep; rep--)
177
                {
178
                        BLT_PACK_11_4(0) BLT_PACK_11_4(4) BLT_PACK_11_4(8) BLT_PACK_11_4(12)
179
                        dest += 16;
180
                        src += 16;
181
                }
182
                if(count & 0x40)
183
                {
184
                        BLT_PACK_11_4(0) BLT_PACK_11_4(4)
185
                        dest += 8;
186
                        src += 8;
187
                }
188
                if(count & 0x20)
189
                {
190
                        BLT_PACK_11_4(0)
191
                        dest += 4;
192
                        src += 4;
193
                }
194
                if(count & 0x10)
195
                {
196
                        dest[0] = src[0]; dest[1] = src[1];
197
                        dest += 2;
198
                        src += 2;
199
                }
200
                if(count & 8)
201
                        *dest++ = *src++;
202
                switch(count & 7)
203
                {
204
                case 0: break;
205
                case 1: *dest = (*src & 0x80) | (*dest | 0x7f); break;
206
                case 2: *dest = (*src & 0xc0) | (*dest | 0x3f); break;
207
                case 3: *dest = (*src & 0xe0) | (*dest | 0x1f); break;
208
                case 4: *dest = (*src & 0xf0) | (*dest | 0x0f); break;
209
                case 5: *dest = (*src & 0xf8) | (*dest | 0x07); break;
210
                case 6: *dest = (*src & 0xfc) | (*dest | 0x03); break;
211
                case 7: *dest = (*src & 0xfe) | (*dest | 0x01); break;
212
                }
213
        }
214
        else
215
        {
216
                const byte shift1 = bit_shift, shift2 = 8 - bit_shift;
217
                byte mask;
218
                if(count + shift1 <= 8)
219
                { // touch just 1 byte
220
                        mask = ((1 << count) - 1) << (8 - count - shift1);
221
                        *dest = (*dest & ~mask) | ((*src >> shift1) & mask);
222
                        return;
223
                }
224
                mask = 0xff00 >> shift1;
225
                *dest = (*dest & ~mask) | ((*src >> shift1) & mask);
226
                dest++;
227
                count -= shift2;
228
#define BLT_SHIFT_11_1(o) dest[(o)] = (src[(o)] << shift2) | (src[(o) + 1] >> shift1);
229
#define BLT_SHIFT_11_4(o) BLT_SHIFT_11_1((o)) BLT_SHIFT_11_1((o) + 1) BLT_SHIFT_11_1((o) + 2) BLT_SHIFT_11_1((o) + 3)
230
                for(unsigned rep = count >> 6; rep; rep--)
231
                {
232
                        BLT_SHIFT_11_4(0) BLT_SHIFT_11_4(4)
233
                        dest += 8;
234
                        src += 8;
235
                }
236
                if(count & 0x20)
237
                {
238
                        BLT_SHIFT_11_4(0)
239
                        dest += 4;
240
                        src += 4;
241
                }
242
                if(count & 0x10)
243
                {
244
                        BLT_SHIFT_11_1(0) BLT_SHIFT_11_1(1)
245
                        dest += 2;
246
                        src += 2;
247
                }
248
                if(count & 8)
249
                {
250
                        BLT_SHIFT_11_1(0)
251
                        dest++;
252
                        src++;
253
                }
254
                if(count &= 7)
255
                {
256
                        byte data = (count <= shift1 ? src[1] << shift2 : (src[1] << shift2) | (src[2] >> shift1));
257
                        mask = 0xff00 >> count;
258
                        *dest = (*dest & ~mask) | (data & mask);
259
                }
260
        }
261
}
262

    
263
// add support for 2 bpp tif - Massimo Del Fedele
264
// un-optimized way....
265
// bit_shift should be shift on destination, NOT source
266
static void BltPack22(byte *dest, const byte *src, byte bit_shift, unsigned count)
267
{
268
        unsigned c2 = count >> 2;
269
        count &= 0x03;
270
        byte shift1, shift2;
271
        byte sMask1, sMask2;
272
        byte dMask1, dMask2;
273
        
274
        if(!bit_shift) // fast path
275
        {
276
                if(c2)
277
                {
278
                        memcpy(dest, src, c2);
279
                        dest += c2;
280
                        src += c2;
281
                }
282
                switch(count)
283
                {
284
                        default:
285
                        case 0:
286
                                break;
287
                                
288
                        case 1:
289
                                *dest = (*dest & 0x3f) | (*src & 0x3f);
290
                                break;
291
                                
292
                        case 2:
293
                                *dest = (*dest & 0x0f) | (*src & 0x0f);
294
                                break;
295
                        
296
                        case 3:
297
                                *dest = (*dest & 0x03) | (*src & 0x03);
298
                                break;
299
                } // switch(count)
300
        }
301
        else // slow path
302
        {
303
                bit_shift <<= 1;
304
                shift1 = bit_shift;
305
                shift2 = (8 - bit_shift);
306
                sMask1 = 0xff << shift1;
307
                dMask1 = 0xff << shift2;
308
                sMask2 = 0xff >> shift2;
309
                dMask2 = 0xff >> shift1;
310
                while(c2--)
311
                {
312
                        *dest = (*dest & dMask1) | ((*src & sMask1) >> shift1);
313
                        dest++;
314
                        *dest = (*dest & dMask2) | ((*src & sMask2) << shift2);
315
                        src++;
316
                }
317
                switch(count)
318
                {
319
                        case 0:
320
                        default:
321
                                break;
322
                                
323
                        case 1:
324
                                *dest = (*dest & ~(0xc0 >> bit_shift)) | ((*src & 0xc0) >> bit_shift);
325
                                break;
326
                        
327
                        case 2:
328
                                if(bit_shift <= 4)
329
                                {
330
                                        *dest = (*dest & ~(0xf0 >> bit_shift)) | ((*src & 0xf0) >> bit_shift);
331
                                }
332
                                else
333
                                {
334
                                        *dest = (*dest & ~(0xc0 >> bit_shift)) | ((*src & 0xc0) >> bit_shift);
335
                                        dest++;
336
                                        *dest = (*dest & 0x3f) | ((*src & 0x30) << 2);
337
                                }
338
                                break;
339
                                
340
                        case 3:
341
                                if(bit_shift <= 2)
342
                                {
343
                                        *dest = (*dest & ~(0xfc >> bit_shift)) | ((*src & 0xfc) >> bit_shift);
344
                                }
345
                                else if(bit_shift <= 4)
346
                                {
347
                                        *dest = (*dest & ~(0xf0 >> bit_shift)) | ((*src & 0xf0) >> bit_shift);
348
                                        dest++;
349
                                        *dest = (*dest & 0x3f) | ((*src & 0x0c) << 4);
350
                                }
351
                                else
352
                                {
353
                                        *dest = (*dest & 0xfc) | ((*src & 0xc0) >> 6);
354
                                        dest++;
355
                                        *dest = (*dest & 0x0f) | ((*src & 0x3c) << 2);
356
                                }
357
                                break;
358
                } // switch(count)
359
        } // end slow path
360

    
361
}
362

    
363
static void BltPack44(byte *dest, const byte *src, bool shift, unsigned count)
364
{
365
//        RTIMING("BltPack44");
366
        ASSERT(count > 0);
367
        if(shift)
368
        {
369
                byte c = *src++, d;
370
                *dest = (*dest & 0xF0) | (c >> 4);
371
                dest++;
372
                count--;
373
                while(count >= 8)
374
                {
375
                        d = src[0]; dest[0] = (c << 4) | (d >> 4);
376
                        c = src[1]; dest[1] = (d << 4) | (c >> 4);
377
                        d = src[2]; dest[2] = (c << 4) | (d >> 4);
378
                        c = src[3]; dest[3] = (d << 4) | (c >> 4);
379
                        src += 4;
380
                        dest += 4;
381
                        count -= 8;
382
                }
383
                if(count & 4)
384
                {
385
                        d = src[0]; dest[0] = (c << 4) | (d >> 4);
386
                        c = src[1]; dest[1] = (d << 4) | (c >> 4);
387
                        src += 2;
388
                        dest += 2;
389
                }
390
                if(count & 2)
391
                {
392
                        d = src[0]; dest[0] = (c << 4) | (d >> 4);
393
                        c = d;
394
                        src++;
395
                        dest++;
396
                }
397
                if(count & 1)
398
                        dest[0] = (dest[0] & 15) | (c << 4);
399
        }
400
        else
401
        {
402
                unsigned c2 = count >> 1;
403
                if(c2)
404
                        memcpy(dest, src, c2);
405
                if(count & 1)
406
                        dest[c2] = (dest[c2] & 15) | (src[c2] & 0xF0);
407
        }
408
}
409

    
410
static void BltPack4(byte *dest, const byte *src, unsigned count)
411
{
412
#define BLT_PACK_4_4(o) dest[(o)] = src[4 * (o)]; dest[(o) + 1] = src[4 * (o) + 4]; \
413
        dest[(o) + 2] = src[4 * (o) + 8]; dest[(o) + 3] = src[4 * (o) + 12];
414
        for(unsigned rep = count >> 4; rep; rep--)
415
        {
416
                BLT_PACK_4_4(0) BLT_PACK_4_4(4) BLT_PACK_4_4(8) BLT_PACK_4_4(12)
417
                dest += 16;
418
                src += 4 * 16;
419
        }
420
        if(count & 8)
421
        {
422
                BLT_PACK_4_4(0) BLT_PACK_4_4(4)
423
                dest += 8;
424
                src += 4 * 8;
425
        }
426
        if(count & 4)
427
        {
428
                BLT_PACK_4_4(0)
429
                dest += 4;
430
                src += 4 * 4;
431
        }
432
        if(count & 2)
433
        {
434
                dest[0] = src[0]; dest[1] = src[4];
435
                dest += 2;
436
                src += 4 * 2;
437
        }
438
        if(count & 1)
439
                dest[0] = src[0];
440
}
441

    
442
static tsize_t ReadStream(thandle_t fd, tdata_t buf, tsize_t size)
443
{
444
        Stream *stream = reinterpret_cast<Stream *>(fd);
445
        if(!stream->IsOpen())
446
                return 0;
447
//        RLOG("TiffStream::TIFRaster::Data & " << (int)wrapper.stream.GetPos() << ", count = " << size
448
//                << ", end = " << (int)(wrapper.stream.GetPos() + size));
449
        return stream->Get(buf, size);
450
}
451

    
452
static tsize_t WriteStream(thandle_t fd, tdata_t buf, tsize_t size)
453
{
454
        Stream *stream = reinterpret_cast<Stream *>(fd);
455
        ASSERT(stream->IsOpen());
456
        stream->Put(buf, size);
457
        return stream->IsError() ? 0 : size;
458
}
459

    
460
static toff_t SeekStream(thandle_t fd, toff_t off, int whence)
461
{
462
        Stream *stream = reinterpret_cast<Stream *>(fd);
463
        ASSERT(stream->IsOpen());
464
        toff_t size = (toff_t)stream->GetSize();
465
        toff_t destpos = (toff_t)(off + (whence == 1 ? stream->GetPos() : whence == 2 ? size : 0));
466
        stream->Seek(destpos);
467
//        RLOG("TIFRaster::Data::SeekStream -> " << (int)off << ", whence = " << whence << " -> pos = " << (int)wrapper.stream.GetPos());
468
        return (toff_t)stream->GetPos();
469
}
470

    
471
static int CloseStream(thandle_t fd)
472
{
473
        return 0;
474
}
475

    
476
static int CloseOwnedStream(thandle_t fd)
477
{
478
        delete reinterpret_cast<Stream *>(fd);
479
        return 0;
480
}
481

    
482
static toff_t SizeStream(thandle_t fd)
483
{
484
        Stream *stream = reinterpret_cast<Stream *>(fd);
485
        ASSERT(stream->IsOpen());
486
//        RLOG("TIFRaster::Data::SizeStream -> " << (int)wrapper.stream.GetSize());
487
        return (toff_t)stream->GetSize();
488
}
489

    
490
static int MapStream(thandle_t fd, tdata_t *pbase, toff_t *psize)
491
{
492
        return 0;
493
}
494

    
495
static void UnmapStream(thandle_t fd, tdata_t base, toff_t size)
496
{
497
}
498

    
499
struct ::tiff *TIFFFileStreamOpen(const char *filename, const char *mode)
500
{
501
        One<FileStream> fs = new FileStream;
502
        int m = _TIFFgetMode(mode, "TIFFOpen");
503
        dword fmode = FileStream::READ;
504

    
505
        switch(m) {
506
                case O_RDONLY: {
507
                        fmode = FileStream::READ;
508
                        break;
509
                }
510
                case O_RDWR: {
511
                        fmode = FileStream::READWRITE;
512
                        break;
513
                }
514
                case O_RDWR|O_CREAT:
515
                case O_RDWR|O_TRUNC:
516
                case O_RDWR|O_CREAT|O_TRUNC: {
517
                        fmode = FileStream::CREATE;
518
                        break;
519
                }
520
        }
521
        if(!fs->Open(filename, fmode))
522
                return NULL;
523
        return TIFFStreamOpen(filename, mode, -fs, true);
524
}
525
/*
526

527
struct ::tiff* TIFFWrapOpen(const char *filename, const char *mode){
528
        return ::TIFFOpen(filename, mode);
529
}
530

531
int TIFFWrapGetField(::tiff* tif_data, uint32 tag, ...){
532
        va_list ap;
533
        return ::TIFFGetField(tif_data, tag, ap);
534
}
535
*/
536

    
537
struct ::tiff *TIFFStreamOpen(const char *filename, const char *mode, Stream *stream, bool destruct)
538
{
539
        return TIFFClientOpen(filename, mode, reinterpret_cast<thandle_t>(stream),
540
                &ReadStream, &WriteStream,
541
                &SeekStream,
542
                destruct ? &CloseOwnedStream : &CloseStream,
543
                &SizeStream,
544
                &MapStream, &UnmapStream);
545
}
546

    
547

    
548
struct TIFRaster::Data : public TIFFRGBAImage {
549
        Data(Stream& stream);
550
        ~Data();
551

    
552
        bool             Create();
553
        Raster::Info     GetInfo();
554
        Raster::Line     GetLine(int i, Raster *owner);
555
        bool             SeekPage(int page);
556
        bool             FetchPage();
557
        void             CloseTmpFile();
558

    
559
        static void      Warning(const char* module, const char* fmt, va_list ap);
560
        static void      Error(const char* module, const char* fmt, va_list ap);
561

    
562
        RasterFormat     format;
563

    
564
        Stream&          stream;
565
        TIFF             *tiff;
566

    
567
        struct Page {
568
                uint32       width, height;
569
                uint16       bits_per_sample;
570
                uint16       samples_per_pixel;
571
                uint16       photometric;
572
                Size         dot_size;
573
                bool         alpha;
574
        };
575
        Array<Page>      pages;
576
        int              page_index;
577

    
578
        byte *MapDown(int x, int y, int count, bool read);
579
        byte *MapUp(int x, int y, int count, bool read);
580
        void  Flush();
581
        void  Flush(int y);
582

    
583
        Size size;
584
        int bpp;
585
        int row_bytes;
586
        int cache_size;
587
        bool alpha;
588
        bool page_open;
589
        bool page_fetched;
590
        bool page_error;
591
        Vector<byte> imagebuf;
592
        String tmpfile;
593
        FileStream filebuffer;
594
        struct Row {
595
                Row() : x(0), size(0) {}
596

    
597
                Buffer<byte> mapping;
598
                int x, size;
599
        };
600
        enum { MAX_CACHE_SIZE = 50000000 };
601
        RGBA palette[256];
602
        int palette_count;
603
        Buffer<Row> rows;
604
        int64 mapping_offset;
605
        int mapping_size;
606
        Vector<uint32> buffer;
607
        tileContigRoutine contig;
608
        tileSeparateRoutine separate;
609
        int skewfac;
610
//        void (*pack)(TIFFImageHelper *helper, uint32 x, uint32 y, uint32 w, uint32 h);
611
//        String warnings;
612
//        String errors;
613
};
614

    
615
extern "C" {
616

    
617
TIFFErrorHandler _TIFFwarningHandler = TIFRaster::Data::Warning;
618
TIFFErrorHandler _TIFFerrorHandler   = TIFRaster::Data::Error;
619

    
620
};
621
static void packTileRGB(TIFRaster::Data *helper, uint32 x, uint32 y, uint32 w, uint32 h)
622
{
623
        if(helper->alpha) {
624
                int x4 = 4 * x, w4 = 4 * w;
625
        //        byte *dest = helper->dest.GetUpScan(y) + 3 * x;
626
                const byte *src = (const byte *)helper->buffer.Begin();
627
        //        unsigned srow = sizeof(uint32) * w; //, drow = helper->dest.GetUpRowBytes();
628
                for(; h; h--, /*src += srow,*/ /*dest += drow*/ y++) {
629
                        for(byte *dest = helper->MapUp(x4, y, w4, false), *end = dest + w4; dest < end; dest += 4, src += 4) {
630
                                dest[0] = src[2];
631
                                dest[1] = src[1];
632
                                dest[2] = src[0];
633
                                dest[3] = src[3];
634
                        }
635
                }
636
        }
637
        else {
638
                int x3 = 3 * x, w3 = 3 * w;
639
        //        byte *dest = helper->dest.GetUpScan(y) + 3 * x;
640
                const byte *src = (const byte *)helper->buffer.Begin();
641
        //        unsigned srow = sizeof(uint32) * w; //, drow = helper->dest.GetUpRowBytes();
642
                for(; h; h--, /*src += srow,*/ /*dest += drow*/ y++) {
643
                        for(byte *dest = helper->MapUp(x3, y, w3, false), *end = dest + w3; dest < end; dest += 3, src += 4) {
644
                                dest[0] = src[2];
645
                                dest[1] = src[1];
646
                                dest[2] = src[0];
647
                        }
648
                }
649
        }
650
}
651

    
652
static void putContig1(TIFFRGBAImage *img, tif_uint32 *cp,
653
        tif_uint32 x, tif_uint32 y, tif_uint32 w, tif_uint32 h,
654
        tif_int32 fromskew, tif_int32 toskew, byte *pp)
655
{
656
        TIFRaster::Data *helper = (TIFRaster::Data *)img;
657
        Size size = helper->size;
658
        int iw = toskew + w;
659
        bool keep_y = (iw >= 0);
660
        int x8 = x >> 3;
661
        int w8 = ((x + w + 7) >> 3) - x8;
662
        bool read = !!((x | w) & 7) && (int)w < helper->size.cx;
663
//        byte *dest = helper->dest.GetUpScan(y) + (x >> 3);
664
//        int drow = (keep_y ? helper->dest.GetUpRowBytes() : -helper->dest.GetUpRowBytes());
665
        int drow = keep_y ? 1 : -1;
666
        const byte *src = pp;
667
        int srow = (fromskew + w - 1) / helper->skewfac + 1;
668
        for(; h; h--, y += drow /*dest += drow*/, src += srow)
669
                BltPack11(helper->MapUp(x8, y, w8, read), src, (byte)(x & 7), w);
670
}
671

    
672
static void putContig2(TIFFRGBAImage *img, tif_uint32 *cp,
673
        tif_uint32 x, tif_uint32 y, tif_uint32 w, tif_uint32 h,
674
        tif_int32 fromskew, tif_int32 toskew, byte *pp)
675
{
676
        TIFRaster::Data *helper = (TIFRaster::Data *)img;
677
        Size size = helper->size;
678
        int iw = toskew + w;
679
        bool keep_y = (iw >= 0);
680
        int x4 = x >> 2;
681
        int w4 = ((x + w + 3) >> 2) - x4;
682
        bool read = !!((x | w) & 3) && (int)w < helper->size.cx;
683
//        byte *dest = helper->dest.GetUpScan(y) + (x >> 3);
684
//        int drow = (keep_y ? helper->dest.GetUpRowBytes() : -helper->dest.GetUpRowBytes());
685
        int drow = keep_y ? 1 : -1;
686
        const byte *src = pp;
687
        int srow = (fromskew + w - 1) / helper->skewfac + 1;
688
        for(; h; h--, y += drow /*dest += drow*/, src += srow)
689
                BltPack22(helper->MapUp(x4, y, w4, read), src, (byte)(x & 3), w);
690
}
691

    
692
static void putContig4(TIFFRGBAImage *img, tif_uint32 *cp,
693
        tif_uint32 x, tif_uint32 y, tif_uint32 w, tif_uint32 h,
694
        tif_int32 fromskew, tif_int32 toskew, byte *pp)
695
{
696
        TIFRaster::Data *helper = (TIFRaster::Data *)img;
697
        Size size = helper->size; //dest.GetSize();
698
        int iw = toskew + w;
699
        bool keep_y = (iw >= 0);
700
        int x2 = x >> 1;
701
        int w2 = ((x + w + 1) >> 1) - x2;
702
        bool read = !!((x | w) & 1) && (int)w < helper->size.cx;
703
//        byte *dest = helper->dest.GetUpScan(y) + (x >> 1);
704
        bool shift = (x & 1);
705
//        int drow = (keep_y ? helper->dest.GetUpRowBytes() : -helper->dest.GetUpRowBytes());
706
        int drow = (keep_y ? 1 : -1);
707
        const byte *src = pp;
708
        int srow = (fromskew + w - 1) / helper->skewfac + 1;
709
        for(; h; h--, y /*dest*/ += drow, src += srow)
710
                BltPack44(helper->MapUp(x2, y, w2, read), src, shift, w);
711
}
712

    
713
static void putContig8(TIFFRGBAImage *img, tif_uint32 *cp,
714
        tif_uint32 x, tif_uint32 y, tif_uint32 w, tif_uint32 h,
715
        tif_int32 fromskew, tif_int32 toskew, byte *pp)
716
{
717
        TIFRaster::Data *helper = (TIFRaster::Data *)img;
718
        Size size = helper->size;
719
        int iw = toskew + w;
720
        bool keep_y = (iw >= 0);
721
//        byte *dest = helper->dest.GetUpScan(y) + x;
722
//        int drow = (keep_y ? helper->dest.GetUpRowBytes() : -helper->dest.GetUpRowBytes());
723
        int drow = (keep_y ? 1 : -1);
724
        const byte *src = pp;
725
        int srow = (fromskew + w - 1) / helper->skewfac + 1;
726
        for(; h; h--, y /*dest*/ += drow, src += srow)
727
                memcpy(helper->MapUp(x, y, w, false), src, w);
728
}
729

    
730
static void putContigRGB(TIFFRGBAImage *img, tif_uint32 *cp, tif_uint32 x, tif_uint32 y, tif_uint32 w, tif_uint32 h,
731
        tif_int32 fromskew, tif_int32 toskew, byte *pp)
732
{
733
        TIFRaster::Data *helper = (TIFRaster::Data *)img;
734
        Size size = helper->size;
735
        int iw = toskew + w;
736
        int wh = w * h;
737
        if(wh > helper->buffer.GetCount())
738
                helper->buffer.SetCount(wh);
739
        bool keep_y = (iw >= 0);
740
        helper->contig(img, (tif_uint32 *)(keep_y ? &helper->buffer[0] : &helper->buffer[0] + w * (h - 1)),
741
                0, 0, w, h, fromskew, keep_y ? 0 : -2 * (int)w, pp);
742
        packTileRGB(helper, x, keep_y ? y : y - h + 1, w, h);
743
}
744

    
745
static void putSeparate(TIFFRGBAImage *img, tif_uint32 *cp,
746
        tif_uint32 x, tif_uint32 y, tif_uint32 w, tif_uint32 h,
747
        tif_int32 fromskew, tif_int32 toskew, byte *r, byte *g, byte *b, byte *a)
748
{
749
        TIFRaster::Data *helper = (TIFRaster::Data *)img;
750
        Size size = helper->size;
751
        int wh = w * h;
752
        if(wh > helper->buffer.GetCount())
753
                helper->buffer.SetCount(wh);
754
        int iw = toskew + w;
755
        bool keep_y = (iw >= 0);
756
        helper->separate(img, (tif_uint32 *)(keep_y ? &helper->buffer[0] : &helper->buffer[0] + w * (h - 1)),
757
                0, 0, w, h, fromskew, keep_y ? 0 : -2 * (int)w, r, g, b, a);
758
        packTileRGB(helper, x, keep_y ? y : y - h + 1, w, h);
759
}
760

    
761
byte *TIFRaster::Data::MapUp(int x, int y, int count, bool read)
762
{
763
        return MapDown(x, size.cy - 1 - y, count, read);
764
}
765

    
766
byte *TIFRaster::Data::MapDown(int x, int y, int count, bool read)
767
{
768
        if(!imagebuf.IsEmpty())
769
                return &imagebuf[row_bytes * y] + x;
770
        else {
771
                ASSERT(filebuffer.IsOpen());
772
                Row& row = rows[y];
773
                if(row.size >= count && row.x <= x && row.x + row.size >= x + count)
774
                        return &row.mapping[x - row.x];
775
                if(cache_size + count >= MAX_CACHE_SIZE)
776
                        Flush();
777
                row.mapping.Alloc(count);
778
                row.x = x;
779
                row.size = count;
780
                cache_size += count;
781
                if(read) {
782
                        filebuffer.Seek(row_bytes * y + x);
783
                        filebuffer.GetAll(row.mapping, count);
784
                }
785
                return row.mapping;
786
        }
787
}
788

    
789
void TIFRaster::Data::Flush()
790
{
791
        LLOG("Flush, cache size = " << cache_size);
792
        for(int y = 0; y < size.cy; y++)
793
                Flush(y);
794
        ASSERT(cache_size == 0);
795
}
796

    
797
void TIFRaster::Data::Flush(int y)
798
{
799
        Row& row = rows[y];
800
        if(filebuffer.IsOpen() && row.size > 0) {
801
                int64 fpos = row_bytes * y + row.x;
802
//                RLOG("writing row " << y << " from " << fpos << " + " << row.size << " = " << (fpos + row.size));
803
                filebuffer.Seek(fpos);
804
                filebuffer.Put(row.mapping, row.size);
805
                cache_size -= row.size;
806
                row.size = 0;
807
                row.mapping.Clear();
808
        }
809
}
810

    
811
void TIFRaster::Data::Warning(const char *fn, const char *fmt, va_list ap)
812
{
813
        if(!memcmp(fn, "tiff@", 5) && IsDigit(fn[5])) {
814
                int addr = stou(fn + 5);
815
                if(addr != -1 && addr != 0) {
816
                        TIFRaster::Data& wrapper = *reinterpret_cast<TIFRaster::Data *>(addr);
817
                        LLOG("TIF warning: " << VFormat(fmt, ap));
818
//                        RLOG("TiffWrapper::Warning: " << wrapper.errors);
819
                }
820
        }
821
}
822

    
823
void TIFRaster::Data::Error(const char *fn, const char *fmt, va_list ap)
824
{
825
        if(!memcmp(fn, "tiff@", 5) && IsDigit(fn[5])) {
826
                int addr = stou(fn + 5);
827
                if(addr != -1 && addr != 0) {
828
                        Data& wrapper = *reinterpret_cast<Data *>(addr);
829
                        LLOG("TIF error: " << VFormat(fmt, ap));
830
//                        RLOG("TiffWrapper::Error: " << wrapper.errors);
831
                }
832
        }
833
}
834

    
835
TIFRaster::Data::Data(Stream& stream)
836
: stream(stream)
837
{
838
        tiff = NULL;
839
        page_index = 0;
840
        cache_size = 0;
841
        page_open = false;
842
        page_fetched = false;
843
        page_error = false;
844
}
845

    
846
TIFRaster::Data::~Data()
847
{
848
        if(tiff) {
849
                if(page_open)
850
                        TIFFRGBAImageEnd(this);
851
                CloseTmpFile();
852
                TIFFClose(tiff);
853
        }
854
}
855

    
856
bool TIFRaster::Data::Create()
857
{
858
        tiff = TIFFStreamOpen("tiff@" + Format64((intptr_t)this), "r", &stream);
859
        if(!tiff)
860
                return false;
861

    
862
        int count = TIFFNumberOfDirectories(tiff);
863
        if(count <= 0)
864
                return false;
865
        for(int i = 0; i < count; i++) {
866
                Page& page = pages.Add();
867
                TIFFSetDirectory(tiff, i);
868
                TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &page.width);
869
                TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &page.height);
870
                float xres, yres;
871
                TIFFGetFieldDefaulted(tiff, TIFFTAG_XRESOLUTION, &xres);
872
                TIFFGetFieldDefaulted(tiff, TIFFTAG_YRESOLUTION, &yres);
873
                uint16 resunit;
874
                TIFFGetFieldDefaulted(tiff, TIFFTAG_RESOLUTIONUNIT, &resunit);
875
                TIFFGetFieldDefaulted(tiff, TIFFTAG_BITSPERSAMPLE, &page.bits_per_sample);
876
                TIFFGetFieldDefaulted(tiff, TIFFTAG_SAMPLESPERPIXEL, &page.samples_per_pixel);
877
                TIFFGetFieldDefaulted(tiff, TIFFTAG_PHOTOMETRIC, &page.photometric);
878
                double dots_per_unit = (resunit == RESUNIT_INCH ? 600.0 : resunit == RESUNIT_CENTIMETER
879
                        ? 600.0 / 2.54 : 0);
880
                page.dot_size.cx = (xres ? fround(page.width * dots_per_unit / xres) : 0);
881
                page.dot_size.cy = (yres ? fround(page.height * dots_per_unit / yres) : 0);
882
                page.alpha = false;
883
                uint16 extrasamples, *sampletypes;
884
                TIFFGetFieldDefaulted(tiff, TIFFTAG_EXTRASAMPLES, &extrasamples, &sampletypes);
885
                for(int e = 0; e < extrasamples; e++)
886
                        if(sampletypes[e] == EXTRASAMPLE_ASSOCALPHA) {
887
                                page.alpha = true;
888
                                break;
889
                        }
890
        }
891
        return SeekPage(0);
892
}
893

    
894
bool TIFRaster::Data::SeekPage(int pgx)
895
{
896
        if(page_open) {
897
                TIFFRGBAImageEnd(this);
898
                page_open = false;
899
        }
900
        
901
        ASSERT(pgx >= 0 && pgx < pages.GetCount());
902
        page_index = pgx;
903
        page_error = false;
904
        TIFFSetDirectory(tiff, page_index);
905
        CloseTmpFile();
906

    
907
        char emsg[1024];
908
        if(!TIFFRGBAImageBegin(this, tiff, 0, emsg)) {
909
                TIFFError(TIFFFileName(tiff), "%s", emsg);
910
                page_error = true;
911
                return false;
912
        }
913
        
914
        page_open = true;
915
        const Page& page = pages[page_index];
916

    
917
        size = Size(page.width, page.height);
918
        if(isContig) {
919
                contig = put.contig;
920
                put.contig = putContigRGB;
921
        }
922
        else {
923
                separate = put.separate;
924
                put.separate = putSeparate;
925
        }
926
        if(alpha = pages[page_index].alpha) {
927
                format.Set32le(0xFF << 16, 0xFF << 8, 0xFF, 0xFF << 24);
928
                bpp = 32;
929
        }
930
        else {
931
                format.Set24le(0xFF << 16, 0xFF << 8, 0xFF);
932
                bpp = 24;
933
        }
934
        palette_count = 0;
935
        if(isContig        && (photometric == PHOTOMETRIC_PALETTE
936
        || photometric == PHOTOMETRIC_MINISWHITE || photometric == PHOTOMETRIC_MINISBLACK)
937
        && (bitspersample == 1 || bitspersample == 2 || bitspersample == 4 || bitspersample == 8)) {
938
                bpp = 8;
939
                tif_uint32 **ppal = (photometric == PHOTOMETRIC_PALETTE ? PALmap : BWmap);
940
                ASSERT(ppal);
941
//                byte rshift = 8 - img.bitspersample;
942
                palette_count = 1 << min<int>(bitspersample, 8);
943
                byte mask = (1 << bitspersample) - 1;
944
                int part_last = 8 / bitspersample - 1;
945
                int i;
946
                for(i = 0; i <= mask; i++) {
947
                        uint32 rgba = ppal[i][part_last];
948
                        palette[i].r = (byte)TIFFGetR(rgba);
949
                        palette[i].g = (byte)TIFFGetG(rgba);
950
                        palette[i].b = (byte)TIFFGetB(rgba);
951
                        palette[i].a = 255;
952
                }
953
                put.contig = putContig8;
954
                switch(bitspersample) {
955
                case 1: bpp = 1; put.contig = putContig1; format.Set1mf(); break;
956
                case 2: bpp = 2; put.contig = putContig2; format.Set2mf(); break;
957
                case 4: bpp = 4; put.contig = putContig4; format.Set4mf(); break;
958
                case 8: format.Set8(); break;
959
                default: NEVER();
960
                }
961
                skewfac = 8 / bitspersample;
962
        }
963
        row_bytes = (bpp * width + 31) >> 5 << 2;
964

    
965
        page_fetched = false;
966
        return true;
967
}
968

    
969
void TIFRaster::Data::CloseTmpFile()
970
{
971
        if(filebuffer.IsOpen()) {
972
                filebuffer.Close();
973
                FileDelete(tmpfile);
974
        }
975
        tmpfile = Null;
976
}
977

    
978
bool TIFRaster::Data::FetchPage()
979
{
980
        if(page_error)
981
                return false;
982
        if(page_fetched)
983
                return true;
984

    
985
        cache_size = 0;
986
        rows.Clear();
987
        int64 bytes = row_bytes * (int64)height;
988
        if(bytes >= 1 << 28) {
989
                tmpfile = GetTempFileName();
990
                if(!filebuffer.Open(tmpfile, FileStream::CREATE)) {
991
                        page_error = true;
992
                        return false;
993
                }
994
                filebuffer.SetSize(bytes);
995
                if(filebuffer.IsError()) {
996
                        filebuffer.Close();
997
                        FileDelete(tmpfile);
998
                        page_error = true;
999
                        return false;
1000
                }
1001
                rows.Alloc(size.cy);
1002
        }
1003
        else
1004
                imagebuf.SetCount(size.cy * row_bytes, 0);
1005

    
1006
//        RTIMING("TiffWrapper::GetArray/RGBAImageGet");
1007

    
1008
        bool res = TIFFRGBAImageGet(this, 0, width, height);
1009
        TIFFRGBAImageEnd(this);
1010
        page_open = false;
1011

    
1012
        if(filebuffer.IsOpen()) {
1013
                Flush();
1014
                if(filebuffer.IsError() || !res) {
1015
                        filebuffer.Close();
1016
                        FileDelete(tmpfile);
1017
                        page_error = true;
1018
                        return false;
1019
                }
1020
//                imagebuf.SetCount(size.cy * row_bytes);
1021
//                filebuffer.Seek(0);
1022
//                filebuffer.GetAll(imagebuf.Begin(), imagebuf.GetCount());
1023
//                filebuffer.Close();
1024
//                FileDelete(tmpfile);
1025
        }
1026
//        imagebuf.SetDotSize(pages[page_index].dot_size);
1027
//        dest_image.palette = palette;
1028
//        return dest_image;
1029

    
1030
        page_fetched = true;
1031
        return true;
1032
}
1033

    
1034
Raster::Info TIFRaster::Data::GetInfo()
1035
{
1036
        const Page& page = pages[page_index];
1037
        Raster::Info out;
1038
        out.kind = (page.alpha ? IMAGE_ALPHA : IMAGE_OPAQUE);
1039
        out.bpp = bpp;
1040
        out.colors = 0;
1041
        out.dots = page.dot_size;
1042
        out.hotspot = Null;
1043
        return out;
1044
}
1045

    
1046
Raster::Line TIFRaster::Data::GetLine(int line, Raster *raster)
1047
{
1048
        if(!page_error && !page_fetched)
1049
                FetchPage();
1050
        if(page_error) {
1051
                byte *tmp = new byte[row_bytes];
1052
                memset(tmp, 0, row_bytes);
1053
                return Raster::Line(tmp, raster, true);
1054
        }
1055
        if(!imagebuf.IsEmpty())
1056
                return Raster::Line(&imagebuf[row_bytes * line], raster, false);
1057
        const byte *data = MapDown(0, line, row_bytes, raster);
1058
        byte *tmp = new byte[row_bytes];
1059
        memcpy(tmp, data, row_bytes);
1060
        return Raster::Line(tmp, raster, true);
1061
}
1062

    
1063
TIFRaster::TIFRaster()
1064
{
1065
}
1066

    
1067
TIFRaster::~TIFRaster()
1068
{
1069
}
1070

    
1071
bool TIFRaster::Create()
1072
{
1073
        data = new Data(GetStream());
1074
        return data->Create();
1075
}
1076

    
1077
Size TIFRaster::GetSize()
1078
{
1079
        return data->size;
1080
}
1081

    
1082
Raster::Info TIFRaster::GetInfo()
1083
{
1084
        return data->GetInfo();
1085
}
1086

    
1087
Raster::Line TIFRaster::GetLine(int line)
1088
{
1089
        return data->GetLine(line, this);
1090
}
1091

    
1092
int TIFRaster::GetPaletteCount()
1093
{
1094
        return data->palette_count;
1095
}
1096

    
1097
const RGBA *TIFRaster::GetPalette()
1098
{
1099
        return data->palette;
1100
}
1101

    
1102
const RasterFormat *TIFRaster::GetFormat()
1103
{
1104
        return &data->format;
1105
}
1106

    
1107
int TIFRaster::GetPageCount()
1108
{
1109
        return data->pages.GetCount();
1110
}
1111

    
1112
int TIFRaster::GetActivePage() const
1113
{
1114
        return data->page_index;
1115
}
1116

    
1117
void TIFRaster::SeekPage(int n)
1118
{
1119
        data->SeekPage(n);
1120
}
1121

    
1122
class TIFEncoder::Data {
1123
public:
1124
        Data(Stream& stream, RasterFormat& format);
1125
        ~Data();
1126

    
1127
        void             Start(Size size, Size dots, int bpp, const RGBA *palette);
1128
        void             WriteLineRaw(const byte *line);
1129

    
1130
private:
1131
        Stream&          stream;
1132
        TIFF             *tiff;
1133
        Size             size;
1134
        int              bpp;
1135
        const RGBA       *palette;
1136
        Vector<byte>     rowbuf;
1137
        int              linebytes;
1138
        RasterFormat&    format;
1139
        int              line;
1140

    
1141
        static tsize_t   ReadStream(thandle_t fd, tdata_t buf, tsize_t size);
1142
        static tsize_t   WriteStream(thandle_t fd, tdata_t buf, tsize_t size);
1143
        static toff_t    SeekStream(thandle_t fd, toff_t off, int whence);
1144
        static int       CloseStream(thandle_t fd);
1145
        static toff_t    SizeStream(thandle_t fd);
1146
        static int       MapStream(thandle_t fd, tdata_t *pbase, toff_t *psize);
1147
        static void      UnmapStream(thandle_t fd, tdata_t base, toff_t size);
1148
};
1149

    
1150
TIFEncoder::Data::Data(Stream& stream, RasterFormat& format)
1151
: stream(stream), format(format)
1152
{
1153
        tiff = NULL;
1154
}
1155

    
1156
TIFEncoder::Data::~Data()
1157
{
1158
        if(tiff) TIFFClose(tiff);
1159
}
1160

    
1161
tsize_t TIFEncoder::Data::ReadStream(thandle_t fd, tdata_t buf, tsize_t size)
1162
{
1163
        Data& wrapper = *reinterpret_cast<Data *>(fd);
1164
        ASSERT(wrapper.stream.IsOpen());
1165
//        RLOG("TiffStream::ReadStream & " << (int)wrapper.stream.GetPos() << ", count = " << size
1166
//                << ", end = " << (int)(wrapper.stream.GetPos() + size));
1167
        return wrapper.stream.Get(buf, size);
1168
        return 0;
1169
}
1170

    
1171
tsize_t TIFEncoder::Data::WriteStream(thandle_t fd, tdata_t buf, tsize_t size)
1172
{
1173
        Data& wrapper = *reinterpret_cast<Data *>(fd);
1174
        ASSERT(wrapper.stream.IsOpen());
1175
//        RLOG("TIFRaster::Data::WriteStream & " << (int)wrapper.stream.GetPos() << ", count = " << (int)size
1176
//                << ", end = " << (int)(wrapper.stream.GetPos() + size));
1177
        wrapper.stream.Put(buf, size);
1178
        return size;
1179
}
1180

    
1181
toff_t TIFEncoder::Data::SeekStream(thandle_t fd, toff_t off, int whence)
1182
{
1183
        Data& wrapper = *reinterpret_cast<Data *>(fd);
1184
        ASSERT(wrapper.stream.IsOpen());
1185
        toff_t size = (toff_t)wrapper.stream.GetSize();
1186
        toff_t destpos = (toff_t)(off + (whence == 1 ? wrapper.stream.GetPos() : whence == 2 ? size : 0));
1187
        if(destpos > size) {
1188
                wrapper.stream.Seek(size);
1189
                wrapper.stream.Put((int)0, (int)(destpos - size));
1190
        }
1191
        else
1192
                wrapper.stream.Seek(destpos);
1193
//        RLOG("TIFRaster::Data::SeekStream -> " << (int)off << ", whence = " << whence << " -> pos = " << (int)wrapper.stream.GetPos());
1194
        return (toff_t)wrapper.stream.GetPos();
1195
}
1196

    
1197
int TIFEncoder::Data::CloseStream(thandle_t fd)
1198
{
1199
        return 0;
1200
}
1201

    
1202
toff_t TIFEncoder::Data::SizeStream(thandle_t fd)
1203
{
1204
        Data& wrapper = *reinterpret_cast<Data *>(fd);
1205
        ASSERT(wrapper.stream.IsOpen());
1206
//        RLOG("TIFRaster::Data::SizeStream -> " << (int)wrapper.stream.GetSize());
1207
        return (toff_t)wrapper.stream.GetSize();
1208
}
1209

    
1210
int TIFEncoder::Data::MapStream(thandle_t fd, tdata_t *pbase, toff_t *psize)
1211
{
1212
        return 0;
1213
}
1214

    
1215
void TIFEncoder::Data::UnmapStream(thandle_t fd, tdata_t base, toff_t size)
1216
{
1217
}
1218

    
1219
void TIFEncoder::Data::Start(Size sz, Size dots, int bpp_, const RGBA *palette)
1220
{
1221
        size = sz;
1222
        bpp = bpp_;
1223
        line = 0;
1224

    
1225
        tiff = TIFFClientOpen("tiff@" + Format64((intptr_t)this), "w", reinterpret_cast<thandle_t>(this),
1226
                ReadStream, WriteStream, SeekStream, CloseStream, SizeStream, MapStream, UnmapStream);
1227

    
1228
        TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, size.cx);
1229
        TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, size.cy);
1230
        TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, min<int>(bpp, 8));
1231
        TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
1232
        TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, bpp <= 8 ? PHOTOMETRIC_PALETTE : PHOTOMETRIC_RGB);
1233
        TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, bpp <= 8 ? 1 : bpp != 32 ? 3 : 4);
1234
        TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, 1);
1235
        TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
1236
        if(bpp == 32) {
1237
                uint16 es = EXTRASAMPLE_ASSOCALPHA;
1238
                TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, &es);
1239
        }
1240
//        TIFFSetField(tiff, TIFFTAG_REFERENCEBLACKWHITE, refblackwhite);
1241
//        TIFFSetField(tiff, TIFFTAG_TRANSFERFUNCTION, gray);
1242
        if (dots.cx && dots.cy) { 
1243
                TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, (uint16)RESUNIT_INCH);
1244
                float xres = float(sz.cx * 600.0 / dots.cx);
1245
                TIFFSetField(tiff, TIFFTAG_XRESOLUTION, xres);
1246
                float yres = float(sz.cy * 600.0 / dots.cy);
1247
                TIFFSetField(tiff, TIFFTAG_YRESOLUTION, yres);
1248
        }
1249
        switch(bpp) {
1250
                case 1: format.Set1mf(); break;
1251
                case 2: format.Set2mf(); break;
1252
                case 4: format.Set4mf(); break;
1253
                case 8: format.Set8(); break;
1254
                default: NEVER();
1255
                case 24: format.Set24le(0xFF, 0xFF << 8, 0xFF << 16); break;
1256
                case 32: format.Set32le(0xFF, 0xFF << 8, 0xFF << 16, 0xFF << 24); break;
1257
        }
1258
        if(bpp <= 8) {
1259
                uint16 rpal[256], gpal[256], bpal[256];
1260
                int c = 1 << bpp;
1261
                memset(rpal, 0, sizeof(uint16) * c);
1262
                memset(gpal, 0, sizeof(uint16) * c);
1263
                memset(bpal, 0, sizeof(uint16) * c);
1264
                for(int i = 0; i < c; i++) {
1265
                        rpal[i] = palette[i].r << 8;
1266
                        gpal[i] = palette[i].g << 8;
1267
                        bpal[i] = palette[i].b << 8;
1268
                }
1269
                TIFFSetField(tiff, TIFFTAG_COLORMAP, rpal, gpal, bpal);
1270
        }
1271
        int rowbytes = (bpp * size.cx + 31) >> 5 << 2;
1272
        rowbuf.SetCount(rowbytes);
1273
        linebytes = format.GetByteCount(size.cx);
1274
}
1275

    
1276
void TIFEncoder::Data::WriteLineRaw(const byte *s)
1277
{
1278
        memcpy(rowbuf.Begin(), s, linebytes);
1279
        TIFFWriteScanline(tiff, rowbuf.Begin(), line, 0);
1280
        if(++line >= size.cy) {
1281
                TIFFClose(tiff);
1282
                tiff = NULL;
1283
        }
1284
}
1285

    
1286
TIFEncoder::TIFEncoder(int bpp)
1287
: bpp(bpp)
1288
{
1289
}
1290

    
1291
TIFEncoder::~TIFEncoder()
1292
{
1293
}
1294

    
1295
int TIFEncoder::GetPaletteCount()
1296
{
1297
        return (bpp > 8 ? 0 : 1 << bpp);
1298
}
1299

    
1300
void TIFEncoder::Start(Size sz)
1301
{
1302
        data = new Data(GetStream(), format);
1303
        data->Start(sz, GetDots(), bpp, bpp <= 8 ? GetPalette() : NULL);
1304
}
1305

    
1306
void TIFEncoder::WriteLineRaw(const byte *s)
1307
{
1308
        data->WriteLineRaw(s);
1309
}
1310

    
1311
END_UPP_NAMESPACE