root/OpenSceneGraph/trunk/src/osgPlugins/tiff/ReaderWriterTIFF.cpp @ 9556

Revision 9556, 25.6 kB (checked in by robert, 6 years ago)

From Jason Beverage, "Here is a small fix that enables writing 16 bit short images in the tiff plugin.
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1
2#include <osg/Image>
3#include <osg/Notify>
4#include <osg/Geode>
5#include <osg/GL>
6
7#include <osgDB/Registry>
8#include <osgDB/FileUtils>
9#include <osgDB/FileNameUtils>
10
11#include <stdio.h>
12#include <tiffio.h>
13
14/****************************************************************************
15 *
16 * Follows is code extracted from the simage library.  Original Authors:
17 *
18 *      Systems in Motion,
19 *      <URL:http://www.sim.no>
20 *
21 *      Peder Blekken <pederb@sim.no>
22 *      Morten Eriksen <mortene@sim.no>
23 *      Marius Bugge Monsen <mariusbu@sim.no>
24 *
25 * The original COPYING notice
26 *
27 *      All files in this library are public domain, except simage_rgb.cpp which is
28 *      Copyright (c) Mark J Kilgard <mjk@nvidia.com>. I will contact Mark
29 *      very soon to hear if this source also can become public domain.
30 *
31 *      Please send patches for bugs and new features to: <pederb@sim.no>.
32 *
33 *      Peder Blekken
34 *
35 *
36 * Ported into the OSG as a plugin, Robert Osfield Decemeber 2000.
37 * Note, reference above to license of simage_rgb is not relevent to the OSG
38 * as the OSG does not use it.  Also for patches, bugs and new features
39 * please send them direct to the OSG dev team rather than address above.
40 *
41 **********************************************************************/
42
43#include <string.h>
44#include <stdarg.h>
45#include <assert.h>
46#include <stdlib.h>
47
48#define ERR_NO_ERROR    0
49#define ERR_OPEN        1
50#define ERR_READ        2
51#define ERR_MEM         3
52#define ERR_UNSUPPORTED 4
53#define ERR_TIFFLIB     5
54
55/* Functions to read TIFF image from memory
56 *
57 */
58
59tsize_t libtiffStreamReadProc(thandle_t fd, tdata_t buf, tsize_t size)
60{
61    std::istream *fin = (std::istream*)fd;
62
63    fin->read((char*)buf,size);
64
65    if(fin->bad())
66        return -1;
67
68    if(fin->gcount() < size)
69        return 0;
70
71    return size;
72}
73
74tsize_t libtiffStreamWriteProc(thandle_t, tdata_t, tsize_t)
75{
76    return 0;
77}
78
79toff_t libtiffStreamSeekProc(thandle_t fd, toff_t off, int i)
80{
81    std::istream *fin = (std::istream*)fd;
82
83    toff_t ret;
84    switch(i)
85    {
86        case SEEK_SET:
87            fin->seekg(off,std::ios::beg);
88            ret = fin->tellg();
89            if(fin->bad())
90                ret = 0;
91            break;
92
93        case SEEK_CUR:
94            fin->seekg(off,std::ios::cur);
95            ret = fin->tellg();
96            if(fin->bad())
97                ret = 0;
98            break;
99
100        case SEEK_END:
101            fin->seekg(off,std::ios::end);
102            ret = fin->tellg();
103            if(fin->bad())
104                ret = 0;
105            break;
106        default:
107            ret = 0;
108            break;
109    }
110    return ret;
111}
112
113int libtiffStreamCloseProc(thandle_t)
114{
115    return 0;
116}
117
118toff_t libtiffStreamSizeProc(thandle_t fd)
119{
120    std::istream *fin = (std::istream*)fd;
121
122    std::streampos curPos = fin->tellg();
123
124    fin->seekg(0, std::ios::end);
125    toff_t size = fin->tellg();
126    fin->seekg(curPos, std::ios::beg);
127
128    return size;
129}
130
131int libtiffStreamMapProc(thandle_t, tdata_t*, toff_t*)
132{
133    return 0;
134}
135
136void libtiffStreamUnmapProc(thandle_t, tdata_t, toff_t)
137{
138}
139
140/* Functions to write TIFF image from memory
141 *
142 */
143
144tsize_t libtiffOStreamReadProc(thandle_t, tdata_t, tsize_t)
145{
146    return 0;
147}
148
149tsize_t libtiffOStreamWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
150{
151    std::ostream *fout = (std::ostream*)fd;
152
153    fout->write((const char*)buf,size);
154
155    if(fout->bad()) {
156        return -1;
157    }
158
159    return size;
160}
161
162toff_t libtiffOStreamSizeProc(thandle_t fd)
163{
164    std::ostream *fout = (std::ostream*)fd;
165
166    std::streampos curPos = fout->tellp();
167
168    fout->seekp(0, std::ios::end);
169    toff_t size = fout->tellp();
170    fout->seekp(curPos, std::ios::beg);
171
172    return size;
173}
174
175toff_t libtiffOStreamSeekProc(thandle_t fd, toff_t off, int i)
176{
177    std::ostream *fout = (std::ostream*)fd;
178
179    toff_t ret;
180    switch(i)
181    {
182        case SEEK_SET:
183            fout->seekp(off,std::ios::beg);
184            ret = fout->tellp();
185            if(fout->bad())
186                ret = 0;
187            break;
188
189        case SEEK_CUR:
190            fout->seekp(off,std::ios::cur);
191            ret = fout->tellp();
192            if(fout->bad())
193                ret = 0;
194            break;
195
196        case SEEK_END:
197            fout->seekp(off,std::ios::end);
198            ret = fout->tellp();
199            if(fout->bad())
200                ret = 0;
201            break;
202        default:
203            ret = 0;
204            break;
205    }
206    return ret;
207}
208
209static int tifferror = ERR_NO_ERROR;
210
211int
212simage_tiff_error(char * buffer, int buflen)
213{
214    switch (tifferror)
215    {
216        case ERR_OPEN:
217            strncpy(buffer, "TIFF loader: Error opening file", buflen);
218            break;
219        case ERR_MEM:
220            strncpy(buffer, "TIFF loader: Out of memory error", buflen);
221            break;
222        case ERR_UNSUPPORTED:
223            strncpy(buffer, "TIFF loader: Unsupported image type", buflen);
224            break;
225        case ERR_TIFFLIB:
226            strncpy(buffer, "TIFF loader: Illegal tiff file", buflen);
227            break;
228    }
229    return tifferror;
230}
231
232
233
234
235
236
237static void
238tiff_error(const char*, const char*, va_list)
239{
240    // values are (const char* module, const char* fmt, va_list list)
241    /* FIXME: store error message ? */
242}
243
244
245static void
246tiff_warn(const char *, const char *, va_list)
247{
248    // values are (const char* module, const char* fmt, va_list list)
249    /* FIXME: notify? */
250}
251
252
253static int
254checkcmap(int n, uint16* r, uint16* g, uint16* b)
255{
256    while (n-- > 0)
257        if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
258            return (16);
259    /* Assuming 8-bit colormap */
260    return (8);
261}
262
263static void
264invert_row(unsigned char *ptr, unsigned char *data, int n, int invert, uint16 bitspersample)
265{
266    // osg::notify(osg::NOTICE)<<"invert_row "<<invert<<std::endl;
267    if (bitspersample == 8)
268    {
269        while (n--)
270        {
271            if (invert) *ptr++ = 255 - *data++;
272            else *ptr++ = *data++;
273        }
274    }
275    else if (bitspersample == 16)
276    {
277        unsigned short *ptr1 = (unsigned short *)ptr;
278        unsigned short *data1 = (unsigned short *)data;
279       
280        while (n--)
281        {
282            if (invert) *ptr1++ = 65535 - *data1++;
283            else *ptr1++ = *data1++;
284        }
285    }
286    else if (bitspersample == 32)
287    {
288        float *ptr1 = (float *)ptr;
289        float *data1 = (float *)data;
290       
291        while (n--)
292        {
293            if (invert) *ptr1++ = 1.0 - *data1++;
294            else *ptr1++ = *data1++;
295        }
296    }
297}
298
299
300static void
301remap_row(unsigned char *ptr, unsigned char *data, int n,
302unsigned short *rmap, unsigned short *gmap, unsigned short *bmap)
303{
304    // osg::notify(osg::NOTICE)<<"remap row"<<std::endl;
305    unsigned int ix;
306    while (n--)
307    {
308        ix = *data++;
309        *ptr++ = (unsigned char) rmap[ix];
310        *ptr++ = (unsigned char) gmap[ix];
311        *ptr++ = (unsigned char) bmap[ix];
312    }
313}
314
315static void interleave_row(unsigned char *ptr,
316                           unsigned char *red, unsigned char *green, unsigned char *blue,
317                           int n, int numSamples, uint16 bitspersample)
318{
319    // osg::notify(osg::NOTICE)<<"Interleave row RGB"<<std::endl;
320    if (bitspersample == 8)
321    {
322        while (n--)
323        {
324            *ptr++ = *red++;
325            *ptr++ = *green++;
326            *ptr++ = *blue++;
327            if (numSamples==4) *ptr++ = 255;
328        }
329    }
330    else if (bitspersample == 16)
331    {
332        unsigned short *ptr1 = (unsigned short *)ptr;
333        unsigned short *red1 = (unsigned short *)red;
334        unsigned short *green1 = (unsigned short *)green;
335        unsigned short *blue1 = (unsigned short *)blue;
336       
337        while (n--)
338        {
339            *ptr1++ = *red1++;
340            *ptr1++ = *green1++;
341            *ptr1++ = *blue1++;
342            if (numSamples==4) *ptr1++ = 65535;
343        }
344    }
345    else if (bitspersample == 32)
346    {
347        float *ptr1 = (float *)ptr;
348        float *red1 = (float *)red;
349        float *green1 = (float *)green;
350        float *blue1 = (float *)blue;
351       
352        while (n--)
353        {
354            *ptr1++ = *red1++;
355            *ptr1++ = *green1++;
356            *ptr1++ = *blue1++;
357            if (numSamples==4) *ptr1++ = 1.0f;
358        }
359    }
360}
361
362static void interleave_row(unsigned char *ptr,
363                           unsigned char *red, unsigned char *green, unsigned char *blue, unsigned char *alpha,
364                           int n, int numSamples, uint16 bitspersample)
365{
366    // osg::notify(osg::NOTICE)<<"Interleave row RGBA"<<std::endl;
367    if (bitspersample == 8)
368    {
369        while (n--)
370        {
371            *ptr++ = *red++;
372            *ptr++ = *green++;
373            *ptr++ = *blue++;
374            if (numSamples==4) *ptr++ = *alpha++;
375        }
376    }
377    else if (bitspersample == 16)
378    {
379        unsigned short *ptr1 = (unsigned short *)ptr;
380        unsigned short *red1 = (unsigned short *)red;
381        unsigned short *green1 = (unsigned short *)green;
382        unsigned short *blue1 = (unsigned short *)blue;
383        unsigned short *alpha1 = (unsigned short *)alpha;
384       
385        while (n--)
386        {
387            *ptr1++ = *red1++;
388            *ptr1++ = *green1++;
389            *ptr1++ = *blue1++;
390            if (numSamples==4) *ptr1++ = *alpha1++;
391        }
392    }
393    else if (bitspersample == 32)
394    {
395        float *ptr1 = (float *)ptr;
396        float *red1 = (float *)red;
397        float *green1 = (float *)green;
398        float *blue1 = (float *)blue;
399        float *alpha1 = (float *)alpha;
400       
401        while (n--)
402        {
403            *ptr1++ = *red1++;
404            *ptr1++ = *green1++;
405            *ptr1++ = *blue1++;
406            if (numSamples==4) *ptr1++ = *alpha1++;
407        }
408    }
409}
410
411int
412simage_tiff_identify(const char *,
413const unsigned char *header,
414int headerlen)
415{
416    static unsigned char tifcmp[] = {0x4d, 0x4d, 0x0, 0x2a};
417    static unsigned char tifcmp2[] = {0x49, 0x49, 0x2a, 0};
418
419    if (headerlen < 4) return 0;
420    if (memcmp((const void*)header, (const void*)tifcmp, 4) == 0) return 1;
421    if (memcmp((const void*)header, (const void*)tifcmp2, 4) == 0) return 1;
422    return 0;
423}
424
425
426/* useful defines (undef'ed below) */
427#define CVT(x)      (((x) * 255L) / ((1L<<16)-1))
428#define pack(a,b)   ((a)<<8 | (b))
429
430unsigned char *
431simage_tiff_load(std::istream& fin,
432                 int& width_ret,
433                 int& height_ret,
434                 int& numComponents_ret,
435                 uint16& bitspersample)
436{
437    TIFF *in;
438    uint16 dataType;
439    uint16 samplesperpixel;
440    uint16 photometric;
441    uint32 w, h;
442    uint16 config;
443    uint16* red;
444    uint16* green;
445    uint16* blue;
446    unsigned char *inbuf = NULL;
447    tsize_t rowsize;
448    uint32 row;
449    int format;
450    unsigned char *buffer;
451    int width;
452    int height;
453    unsigned char *currPtr;
454
455    TIFFSetErrorHandler(tiff_error);
456    TIFFSetWarningHandler(tiff_warn);
457
458    in = TIFFClientOpen("inputstream", "r", (thandle_t)&fin,
459            libtiffStreamReadProc, //Custom read function
460            libtiffStreamWriteProc, //Custom write function
461            libtiffStreamSeekProc, //Custom seek function
462            libtiffStreamCloseProc, //Custom close function
463            libtiffStreamSizeProc, //Custom size function
464            libtiffStreamMapProc, //Custom map function
465            libtiffStreamUnmapProc); //Custom unmap function
466
467    if (in == NULL)
468    {
469        tifferror = ERR_OPEN;
470        return NULL;
471    }
472    if (TIFFGetField(in, TIFFTAG_PHOTOMETRIC, &photometric) == 1)
473    {
474        if (photometric != PHOTOMETRIC_RGB && photometric != PHOTOMETRIC_PALETTE &&
475            photometric != PHOTOMETRIC_MINISWHITE &&
476            photometric != PHOTOMETRIC_MINISBLACK)
477        {
478            osg::notify(osg::NOTICE) << "Photometric type "<<photometric<<" not handled; can only handle Grayscale, RGB and Palette images" << std::endl;
479            TIFFClose(in);
480            tifferror = ERR_UNSUPPORTED;
481            return NULL;
482        }
483    }
484    else
485    {
486        tifferror = ERR_READ;
487        TIFFClose(in);
488        return NULL;
489    }
490
491    if (TIFFGetField(in, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel) == 1)
492    {
493        if (samplesperpixel != 1 &&
494            samplesperpixel != 2 &&
495            samplesperpixel != 3 &&
496            samplesperpixel != 4)
497        {
498            osg::notify(osg::DEBUG_INFO) << "Bad samples/pixel" << std::endl;
499            tifferror = ERR_UNSUPPORTED;
500            TIFFClose(in);
501            return NULL;
502        }
503    }
504    else
505    {
506        tifferror = ERR_READ;
507        TIFFClose(in);
508        return NULL;
509    }
510
511    if (TIFFGetField(in, TIFFTAG_BITSPERSAMPLE, &bitspersample) == 1)
512    {
513         if (bitspersample != 8 && bitspersample != 16 && bitspersample != 32)
514        {
515            osg::notify(osg::NOTICE) << "can only handle 8, 16 and 32 bit samples" << std::endl;
516            TIFFClose(in);
517            tifferror = ERR_UNSUPPORTED;
518            return NULL;
519        }
520    }
521    else
522    {
523        tifferror = ERR_READ;
524        TIFFClose(in);
525        return NULL;
526    }
527   
528    if (TIFFGetField(in, TIFFTAG_IMAGEWIDTH, &w) != 1 ||
529        TIFFGetField(in, TIFFTAG_IMAGELENGTH, &h) != 1 ||
530        TIFFGetField(in, TIFFTAG_PLANARCONFIG, &config) != 1)
531    {
532        TIFFClose(in);
533        tifferror = ERR_READ;
534        return NULL;
535    }
536
537       
538    TIFFGetField(in, TIFFTAG_DATATYPE, &dataType);
539    osg::notify(osg::INFO)<<"TIFFTAG_DATATYPE="<<dataType<<std::endl;
540
541
542    /*
543    if (photometric == PHOTOMETRIC_MINISWHITE ||
544        photometric == PHOTOMETRIC_MINISBLACK)
545        format = 1;
546    else
547        format = 3;
548    */
549    // if it has a palette, data returned is 3 byte rgb
550    // so set format to 3.
551    if (photometric == PHOTOMETRIC_PALETTE)
552        format = 3;
553    else
554        format = samplesperpixel * bitspersample / 8;
555   
556   
557    int bytespersample = bitspersample / 8;
558    int bytesperpixel = bytespersample * samplesperpixel;
559   
560    osg::notify(osg::INFO)<<"format="<<format<<std::endl;
561    osg::notify(osg::INFO)<<"bytespersample="<<bytespersample<<std::endl;
562    osg::notify(osg::INFO)<<"bytesperpixel="<<bytesperpixel<<std::endl;
563   
564    buffer = new unsigned char [w*h*format];
565
566    if (!buffer)
567    {
568        tifferror = ERR_MEM;
569        TIFFClose(in);
570        return NULL;
571    }
572
573    // initialize memory
574    for(unsigned char* ptr=buffer;ptr<buffer+w*h*format;++ptr) *ptr = 0;
575
576    width = w;
577    height = h;
578
579    currPtr = buffer + (h-1)*w*format;
580
581    tifferror = ERR_NO_ERROR;
582
583    switch (pack(photometric, config))
584    {
585        case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_CONTIG):
586        case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_CONTIG):
587        case pack(PHOTOMETRIC_MINISWHITE, PLANARCONFIG_SEPARATE):
588        case pack(PHOTOMETRIC_MINISBLACK, PLANARCONFIG_SEPARATE):
589            inbuf = new unsigned char [TIFFScanlineSize(in)];
590            for (row = 0; row < h; row++)
591            {
592                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
593                {
594                    tifferror = ERR_READ;
595                    break;
596                }
597                invert_row(currPtr, inbuf, w, photometric == PHOTOMETRIC_MINISWHITE, bitspersample);
598                currPtr -= format*w;
599            }
600            break;
601
602        case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_CONTIG):
603        case pack(PHOTOMETRIC_PALETTE, PLANARCONFIG_SEPARATE):
604            if (TIFFGetField(in, TIFFTAG_COLORMAP, &red, &green, &blue) != 1)
605                tifferror = ERR_READ;
606            /* */
607            /* Convert 16-bit colormap to 8-bit (unless it looks */
608            /* like an old-style 8-bit colormap). */
609            /* */
610            if (!tifferror && checkcmap(1<<bitspersample, red, green, blue) == 16)
611            {
612                int i;
613                for (i = (1<<bitspersample)-1; i >= 0; i--)
614                {
615                    red[i] = CVT(red[i]);
616                    green[i] = CVT(green[i]);
617                    blue[i] = CVT(blue[i]);
618                }
619            }
620
621            inbuf = new unsigned char [TIFFScanlineSize(in)];
622            for (row = 0; row < h; row++)
623            {
624                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
625                {
626                    tifferror = ERR_READ;
627                    break;
628                }
629                remap_row(currPtr, inbuf, w, red, green, blue);
630                currPtr -= format*w;
631            }
632            break;
633
634        case pack(PHOTOMETRIC_RGB, PLANARCONFIG_CONTIG):
635            inbuf = new unsigned char [TIFFScanlineSize(in)];
636            for (row = 0; row < h; row++)
637            {
638                if (TIFFReadScanline(in, inbuf, row, 0) < 0)
639                {
640                    tifferror = ERR_READ;
641                    break;
642                }
643                memcpy(currPtr, inbuf, format*w);
644                currPtr -= format*w;
645            }
646            break;
647
648        case pack(PHOTOMETRIC_RGB, PLANARCONFIG_SEPARATE):
649            rowsize = TIFFScanlineSize(in);
650            inbuf = new unsigned char [format*rowsize];
651            for (row = 0; !tifferror && row < h; row++)
652            {
653                int s;
654                for (s = 0; s < format; s++)
655                {
656                    if (TIFFReadScanline(in, (tdata_t)(inbuf+s*rowsize), (uint32)row, (tsample_t)s) < 0)
657                    {
658                        tifferror = ERR_READ; break;
659                    }
660                }
661                if (!tifferror)
662                {
663                    if (format==3) interleave_row(currPtr, inbuf, inbuf+rowsize, inbuf+2*rowsize, w, format, bitspersample);
664                    else if (format==4) interleave_row(currPtr, inbuf, inbuf+rowsize, inbuf+2*rowsize, inbuf+3*rowsize, w, format, bitspersample);
665                    currPtr -= format*w;
666                }
667            }
668            break;
669        default:
670            tifferror = ERR_UNSUPPORTED;
671            break;
672    }
673
674    if (inbuf) delete [] inbuf;
675    TIFFClose(in);
676
677    if (tifferror)
678    {
679        if (buffer) delete [] buffer;
680        return NULL;
681    }
682    width_ret = width;
683    height_ret = height;
684    if (photometric == PHOTOMETRIC_PALETTE)
685        numComponents_ret = format;
686    else
687        numComponents_ret = samplesperpixel;
688
689    return buffer;
690}
691
692
693#undef CVT
694#undef pack
695
696class ReaderWriterTIFF : public osgDB::ReaderWriter
697{
698    public:
699   
700        ReaderWriterTIFF()
701        {
702            supportsExtension("tiff","Tiff image format");
703            supportsExtension("tif","Tiff image format");
704        }
705       
706        virtual const char* className() const { return "TIFF Image Reader"; }
707        virtual bool acceptsExtension(const std::string& extension) const
708        {
709            if( osgDB::equalCaseInsensitive(extension,"tiff")) return true;
710            if( osgDB::equalCaseInsensitive(extension,"tif") ) return true;
711            return false;
712        }
713
714        ReadResult readTIFStream(std::istream& fin) const
715        {
716            unsigned char *imageData = NULL;
717            int width_ret = -1;
718            int height_ret = -1;
719            int numComponents_ret = -1;
720            uint16 bitspersample_ret = 0;
721
722            imageData = simage_tiff_load(fin, width_ret, height_ret, numComponents_ret, bitspersample_ret);
723
724            if (imageData==NULL)
725            {
726                char err_msg[256];
727                simage_tiff_error( err_msg, sizeof(err_msg));
728                osg::notify(osg::WARN) << err_msg << std::endl;
729                return ReadResult::FILE_NOT_HANDLED;
730            }
731
732            int s = width_ret;
733            int t = height_ret;
734            int r = 1;
735
736            int internalFormat = numComponents_ret;
737
738            unsigned int pixelFormat =
739                numComponents_ret == 1 ? GL_LUMINANCE :
740                numComponents_ret == 2 ? GL_LUMINANCE_ALPHA :
741                numComponents_ret == 3 ? GL_RGB :
742                numComponents_ret == 4 ? GL_RGBA : (GLenum)-1;
743
744
745            unsigned int dataType =
746                bitspersample_ret == 8 ? GL_UNSIGNED_BYTE :
747                bitspersample_ret == 16 ? GL_UNSIGNED_SHORT :
748                bitspersample_ret == 32 ? GL_FLOAT : (GLenum)-1;
749
750            osg::Image* pOsgImage = new osg::Image;
751            pOsgImage->setImage(s,t,r,
752                internalFormat,
753                pixelFormat,
754                dataType,
755                imageData,
756                osg::Image::USE_NEW_DELETE);
757
758            return pOsgImage;
759        }
760
761        WriteResult::WriteStatus writeTIFStream(std::ostream& fout, const osg::Image& img) const
762        {
763            //Code is based from the following article on CodeProject.com
764            //http://www.codeproject.com/bitmap/BitmapsToTiffs.asp
765
766            TIFF *image;
767            int samplesPerPixel;
768            int bitsPerSample;
769            uint16 photometric;
770
771            image = TIFFClientOpen("outputstream", "w", (thandle_t)&fout,
772                                    libtiffOStreamReadProc, //Custom read function
773                                    libtiffOStreamWriteProc, //Custom write function
774                                    libtiffOStreamSeekProc, //Custom seek function
775                                    libtiffStreamCloseProc, //Custom close function
776                                    libtiffOStreamSizeProc, //Custom size function
777                                    libtiffStreamMapProc, //Custom map function
778                                    libtiffStreamUnmapProc); //Custom unmap function
779           
780            if(image == NULL)
781            {
782                return WriteResult::ERROR_IN_WRITING_FILE;
783            }
784
785            switch(img.getPixelFormat()) {
786                case GL_LUMINANCE:
787                case GL_ALPHA:
788                    photometric = PHOTOMETRIC_MINISBLACK;
789                    samplesPerPixel = 1;
790                    break;
791                case GL_LUMINANCE_ALPHA:
792                    photometric = PHOTOMETRIC_MINISBLACK;
793                    samplesPerPixel = 2;
794                    break;
795                case GL_RGB:
796                    photometric = PHOTOMETRIC_RGB;
797                    samplesPerPixel = 3;
798                    break;
799                case GL_RGBA:
800                    photometric = PHOTOMETRIC_RGB;
801                    samplesPerPixel = 4;
802                    break;
803                default:
804                    return WriteResult::ERROR_IN_WRITING_FILE;
805                    break;
806            }
807
808            switch(img.getDataType()){
809                case GL_FLOAT:
810                    TIFFSetField(image, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
811                    TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, 1);
812                    bitsPerSample = 32;
813                    break;
814                case GL_SHORT:
815                    TIFFSetField(image, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
816                    bitsPerSample = 16;
817                    break;
818                default:
819                    bitsPerSample = 8;
820                    break;
821            }
822
823            TIFFSetField(image, TIFFTAG_IMAGEWIDTH,img.s());
824            TIFFSetField(image, TIFFTAG_IMAGELENGTH,img.t());
825            TIFFSetField(image, TIFFTAG_BITSPERSAMPLE,bitsPerSample);
826            TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL,samplesPerPixel);
827            TIFFSetField(image, TIFFTAG_PHOTOMETRIC, photometric);
828            TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS);
829            TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
830            TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
831
832            //uint32 rowsperstrip = TIFFDefaultStripSize(image, -1);
833            //TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
834           
835            // Write the information to the file
836            for(int i = 0; i < img.t(); ++i) {
837                TIFFWriteScanline(image,(tdata_t)img.data(0,img.t()-i-1),i,0);
838            }
839
840            // Close the file
841            TIFFClose(image);
842
843            return WriteResult::FILE_SAVED;
844        }
845
846        virtual ReadResult readObject(std::istream& fin,const osgDB::ReaderWriter::Options* options =NULL) const
847        {
848            return readImage(fin, options);
849        }
850
851        virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const
852        {
853            return readImage(file, options);
854        }
855
856        virtual ReadResult readImage(std::istream& fin,const osgDB::ReaderWriter::Options* =NULL) const
857        {
858            return readTIFStream(fin);
859        }
860
861        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
862        {
863            std::string ext = osgDB::getLowerCaseFileExtension(file);
864            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
865
866            std::string fileName = osgDB::findDataFile( file, options );
867            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
868
869            std::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);
870            if(!istream) return ReadResult::FILE_NOT_HANDLED;
871            ReadResult rr = readTIFStream(istream);
872            if(rr.validImage()) rr.getImage()->setFileName(file);
873            return rr;
874        }
875
876        virtual WriteResult writeImage(const osg::Image& img,std::ostream& fout,const osgDB::ReaderWriter::Options* /*options*/) const
877        {
878            WriteResult::WriteStatus ws = writeTIFStream(fout,img);
879            return ws;
880        }
881
882        virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options *options) const
883        {
884            std::string ext = osgDB::getFileExtension(fileName);
885            if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
886
887            std::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary);
888            if(!fout) return WriteResult::ERROR_IN_WRITING_FILE;
889
890            return writeImage(img,fout,options);
891        }
892};
893
894// now register with Registry to instantiate the above
895// reader/writer.
896REGISTER_OSGPLUGIN(tiff, ReaderWriterTIFF)
Note: See TracBrowser for help on using the browser.