1 // Released under the OSGPL license, as part of the OpenSceneGraph distribution.
2 //
3 // ReaderWriter for sgi's .rgb format.
4 // specification can be found at http://local.wasp.uwa.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html
5 
6 #include <osg/Image>
7 #include <osg/Notify>
8 
9 #include <osg/Geode>
10 
11 #include <osg/GL>
12 
13 #include <osgDB/FileNameUtils>
14 #include <osgDB/FileUtils>
15 #include <osgDB/Registry>
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #ifndef SEEK_SET
22 #  define SEEK_SET 0
23 #endif
24 
25 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
26     #define GL_BITMAP               0x1A00
27     #define GL_RED                  0x1903
28     #define GL_GREEN                0x1904
29     #define GL_BLUE                 0x1905
30     #define GL_COLOR_INDEX          0x1900
31 #endif
32 
33 #if defined(OSG_GL3_AVAILABLE)
34     #define GL_BITMAP               0x1A00
35     #define GL_COLOR_INDEX          0x1900
36 #endif
37 
38 using namespace osg;
39 
40 
41 typedef struct _rawImageRec
42 {
43     unsigned short imagic;
44     unsigned short type;
45     unsigned short dim;
46     unsigned short sizeX, sizeY, sizeZ;
47     unsigned long min, max;
48     unsigned long wasteBytes;
49     char name[80];
50     unsigned long colorMap;
51     std::istream *file;
52     unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
53     unsigned long rleEnd;
54     GLuint *rowStart;
55     GLint *rowSize;
56     GLenum swapFlag;
57     short bpc;
58 
59     typedef unsigned char * BytePtr;
60 
needsBytesSwapped_rawImageRec61     bool needsBytesSwapped()
62     {
63         union {
64             int testWord;
65             char testByte[sizeof(int)];
66         }endianTest;
67         endianTest.testWord = 1;
68         if( endianTest.testByte[0] == 1 )
69             return true;
70         else
71             return false;
72     }
73 
74     template <class T>
swapBytes_rawImageRec75     inline void swapBytes(  T &s )
76     {
77         if( sizeof( T ) == 1 )
78             return;
79 
80         T d = s;
81         BytePtr sptr = (BytePtr)&s;
82         BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
83 
84         for( unsigned int i = 0; i < sizeof(T); i++ )
85             *(sptr++) = *(dptr--);
86     }
87 
swapBytes_rawImageRec88     void swapBytes()
89     {
90         swapBytes( imagic );
91         swapBytes( type );
92         swapBytes( dim );
93         swapBytes( sizeX );
94         swapBytes( sizeY );
95         swapBytes( sizeZ );
96         swapBytes( wasteBytes );
97         swapBytes( min );
98         swapBytes( max );
99         swapBytes( colorMap );
100     }
101 } rawImageRec;
102 
ConvertShort(unsigned short * array,long length)103 static void ConvertShort(unsigned short *array, long length)
104 {
105     unsigned long b1, b2;
106     unsigned char *ptr;
107 
108     ptr = (unsigned char *)array;
109     while (length--)
110     {
111         b1 = *ptr++;
112         b2 = *ptr++;
113         *array++ = (unsigned short) ((b1 << 8) | (b2));
114     }
115 }
116 
ConvertLong(GLuint * array,long length)117 static void ConvertLong(GLuint *array, long length)
118 {
119     unsigned long b1, b2, b3, b4;
120     unsigned char *ptr;
121 
122     ptr = (unsigned char *)array;
123     while (length--)
124     {
125         b1 = *ptr++;
126         b2 = *ptr++;
127         b3 = *ptr++;
128         b4 = *ptr++;
129         *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
130     }
131 }
132 
133 
RawImageClose(rawImageRec * raw)134 static void RawImageClose(rawImageRec *raw)
135 {
136     if (raw)
137     {
138 
139         if (raw->tmp) delete [] raw->tmp;
140         if (raw->tmpR) delete [] raw->tmpR;
141         if (raw->tmpG) delete [] raw->tmpG;
142         if (raw->tmpB) delete [] raw->tmpB;
143         if (raw->tmpA) delete [] raw->tmpA;
144 
145         if (raw->rowStart) delete [] raw->rowStart;
146         if (raw->rowSize) delete [] raw->rowSize;
147 
148         delete raw;
149     }
150 }
151 
152 
RawImageOpen(std::istream & fin)153 static rawImageRec *RawImageOpen(std::istream& fin)
154 {
155     union
156     {
157         int testWord;
158         char testByte[4];
159     } endianTest;
160     rawImageRec *raw;
161     int x;
162 
163     raw = new rawImageRec;
164     if (raw == NULL)
165     {
166         OSG_WARN<< "Out of memory!"<< std::endl;
167         return NULL;
168     }
169 
170     //Set istream pointer
171     raw->file = &fin;
172 
173     endianTest.testWord = 1;
174     if (endianTest.testByte[0] == 1)
175     {
176         raw->swapFlag = GL_TRUE;
177     }
178     else
179     {
180         raw->swapFlag = GL_FALSE;
181     }
182 
183     fin.read((char*)raw,12);
184     if (!fin.good())
185         return NULL;
186 
187     if (raw->swapFlag)
188     {
189         ConvertShort(&raw->imagic, 6);
190     }
191 
192     raw->tmp = raw->tmpR = raw->tmpG = raw->tmpB = raw->tmpA = 0L;
193     raw->rowStart = 0;
194     raw->rowSize = 0;
195     raw->bpc = (raw->type & 0x00FF);
196 
197     raw->tmp = new unsigned char [raw->sizeX*256*raw->bpc];
198     if (raw->tmp == NULL )
199     {
200         OSG_FATAL<< "Out of memory!"<< std::endl;
201         RawImageClose(raw);
202         return NULL;
203     }
204 
205     if( raw->sizeZ >= 1 )
206     {
207         if( (raw->tmpR = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
208         {
209             OSG_FATAL<< "Out of memory!"<< std::endl;
210             RawImageClose(raw);
211             return NULL;
212         }
213     }
214     if( raw->sizeZ >= 2 )
215     {
216         if( (raw->tmpG = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
217         {
218             OSG_FATAL<< "Out of memory!"<< std::endl;
219             RawImageClose(raw);
220             return NULL;
221         }
222     }
223     if( raw->sizeZ >= 3 )
224     {
225         if( (raw->tmpB = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
226         {
227             OSG_FATAL<< "Out of memory!"<< std::endl;
228             RawImageClose(raw);
229             return NULL;
230         }
231     }
232     if (raw->sizeZ >= 4)
233     {
234         if( (raw->tmpA = new unsigned char [raw->sizeX*raw->bpc]) == NULL )
235         {
236             OSG_FATAL<< "Out of memory!"<< std::endl;
237             RawImageClose(raw);
238             return NULL;
239         }
240     }
241 
242     if ((raw->type & 0xFF00) == 0x0100)
243     {
244         unsigned int ybyz = raw->sizeY * raw->sizeZ;
245         if ( (raw->rowStart = new GLuint [ybyz]) == NULL )
246         {
247             OSG_FATAL<< "Out of memory!"<< std::endl;
248             RawImageClose(raw);
249             return NULL;
250         }
251 
252         if ( (raw->rowSize = new GLint [ybyz]) == NULL )
253         {
254             OSG_FATAL<< "Out of memory!"<< std::endl;
255             RawImageClose(raw);
256             return NULL;
257         }
258         x = ybyz * sizeof(GLuint);
259         raw->rleEnd = 512 + (2 * x);
260                 fin.seekg(512,std::ios::beg);
261         fin.read((char*)raw->rowStart,x);
262         fin.read((char*)raw->rowSize,x);
263         if (raw->swapFlag)
264         {
265             ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
266             ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
267         }
268     }
269     return raw;
270 }
271 
272 
RawImageGetRow(rawImageRec * raw,unsigned char * buf,int y,int z)273 static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
274 {
275     unsigned char *iPtr, *oPtr;
276     unsigned short pixel;
277     int count, done = 0;
278     unsigned short *tempShort;
279 
280     if ((raw->type & 0xFF00) == 0x0100)
281     {
282         raw->file->seekg((long) raw->rowStart[y+z*raw->sizeY], std::ios::beg);
283         raw->file->read((char*)raw->tmp, (unsigned int)raw->rowSize[y+z*raw->sizeY]);
284 
285         iPtr = raw->tmp;
286         oPtr = buf;
287         while (!done)
288         {
289             if (raw->bpc == 1)
290                 pixel = *iPtr++;
291             else
292             {
293                 tempShort = reinterpret_cast<unsigned short*>(iPtr);
294                 pixel = *tempShort;
295                 tempShort++;
296                 iPtr = reinterpret_cast<unsigned char *>(tempShort);
297             }
298 
299             if(raw->bpc != 1)
300                 ConvertShort(&pixel, 1);
301 
302             count = (int)(pixel & 0x7F);
303 
304             // limit the count value to the remiaing row size
305             if (raw->sizeX*raw->bpc <= (oPtr - buf))
306             {
307                 count = raw->sizeX - (oPtr - buf) / raw->bpc;
308             }
309 
310             if (count<=0)
311             {
312                 done = 1;
313                 return;
314             }
315 
316             if (pixel & 0x80)
317             {
318                 while (count--)
319                 {
320                     if(raw->bpc == 1)
321                         *oPtr++ = *iPtr++;
322                     else{
323                         tempShort = reinterpret_cast<unsigned short*>(iPtr);
324                         pixel = *tempShort;
325                         tempShort++;
326                         iPtr = reinterpret_cast<unsigned char *>(tempShort);
327 
328                         ConvertShort(&pixel, 1);
329 
330                         tempShort = reinterpret_cast<unsigned short*>(oPtr);
331                         *tempShort = pixel;
332                         tempShort++;
333                         oPtr = reinterpret_cast<unsigned char *>(tempShort);
334                     }
335                 }
336             }
337             else
338             {
339                 if (raw->bpc == 1)
340                 {
341                     pixel = *iPtr++;
342                 }
343                 else
344                 {
345                     tempShort = reinterpret_cast<unsigned short*>(iPtr);
346                     pixel = *tempShort;
347                     tempShort++;
348                     iPtr = reinterpret_cast<unsigned char *>(tempShort);
349                 }
350                 if(raw->bpc != 1)
351                     ConvertShort(&pixel, 1);
352                 while (count--)
353                 {
354                     if(raw->bpc == 1)
355                         *oPtr++ = pixel;
356                     else
357                     {
358                         tempShort = reinterpret_cast<unsigned short*>(oPtr);
359                         *tempShort = pixel;
360                         tempShort++;
361                         oPtr = reinterpret_cast<unsigned char *>(tempShort);
362                     }
363                 }
364             }
365         }
366     }
367     else
368     {
369         raw->file->seekg(512+(y*raw->sizeX*raw->bpc)+(z*raw->sizeX*raw->sizeY*raw->bpc),std::ios::beg);
370         raw->file->read((char*)buf, raw->sizeX*raw->bpc);
371         if(raw->swapFlag && raw->bpc != 1){
372             ConvertShort(reinterpret_cast<unsigned short*>(buf), raw->sizeX);
373         }
374     }
375 }
376 
377 
RawImageGetData(rawImageRec * raw,unsigned char ** data)378 static void RawImageGetData(rawImageRec *raw, unsigned char **data )
379 {
380     unsigned char *ptr;
381     int i, j;
382     unsigned short *tempShort;
383 
384     //     // round the width to a factor 4
385     //     int width = (int)(floorf((float)raw->sizeX/4.0f)*4.0f);
386     //     if (width!=raw->sizeX) width += 4;
387 
388     // byte aligned.
389 
390     OSG_INFO<<"raw->sizeX = "<<raw->sizeX<<std::endl;
391     OSG_INFO<<"raw->sizeY = "<<raw->sizeY<<std::endl;
392     OSG_INFO<<"raw->sizeZ = "<<raw->sizeZ<<std::endl;
393     OSG_INFO<<"raw->bpc = "<<raw->bpc<<std::endl;
394 
395     *data = new unsigned char [(raw->sizeX)*(raw->sizeY)*(raw->sizeZ)*(raw->bpc)];
396 
397     ptr = *data;
398     for (i = 0; i < (int)(raw->sizeY); i++)
399     {
400         if( raw->sizeZ >= 1 )
401             RawImageGetRow(raw, raw->tmpR, i, 0);
402         if( raw->sizeZ >= 2 )
403             RawImageGetRow(raw, raw->tmpG, i, 1);
404         if( raw->sizeZ >= 3 )
405             RawImageGetRow(raw, raw->tmpB, i, 2);
406         if( raw->sizeZ >= 4 )
407             RawImageGetRow(raw, raw->tmpA, i, 3);
408         for (j = 0; j < (int)(raw->sizeX); j++)
409         {
410           if(raw->bpc == 1){
411             if( raw->sizeZ >= 1 )
412                 *ptr++ = *(raw->tmpR + j);
413             if( raw->sizeZ >= 2 )
414                 *ptr++ = *(raw->tmpG + j);
415             if( raw->sizeZ >= 3 )
416                 *ptr++ = *(raw->tmpB + j);
417             if( raw->sizeZ >= 4 )
418                 *ptr++ = *(raw->tmpA + j);
419           }else{
420             if( raw->sizeZ >= 1 )
421             {
422                 tempShort = reinterpret_cast<unsigned short*>(ptr);
423                 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpR) + j);
424                 tempShort++;
425                 ptr = reinterpret_cast<unsigned char *>(tempShort);
426             }
427             if( raw->sizeZ >= 2 )
428             {
429                 tempShort = reinterpret_cast<unsigned short*>(ptr);
430                 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpG) + j);
431                 tempShort++;
432                 ptr = reinterpret_cast<unsigned char *>(tempShort);
433             }
434             if( raw->sizeZ >= 3 )
435             {
436                 tempShort = reinterpret_cast<unsigned short*>(ptr);
437                 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpB) + j);
438                 tempShort++;
439                 ptr = reinterpret_cast<unsigned char *>(tempShort);
440             }
441             if( raw->sizeZ >= 4 )
442             {
443                 tempShort = reinterpret_cast<unsigned short*>(ptr);
444                 *tempShort = *(reinterpret_cast<unsigned short*>(raw->tmpA) + j);
445                 tempShort++;
446                 ptr = reinterpret_cast<unsigned char *>(tempShort);
447             }
448           }
449         }
450         //         // pad the image width with blanks to bring it up to the rounded width.
451         //         for(;j<width;++j) *ptr++ = 0;
452     }
453 }
454 
455 
456 class ReaderWriterRGB : public osgDB::ReaderWriter
457 {
458     public:
459 
ReaderWriterRGB()460         ReaderWriterRGB()
461         {
462             supportsExtension("rgb","rgb image format");
463             supportsExtension("rgba","rgba image format");
464             supportsExtension("sgi","sgi image format");
465             supportsExtension("int","int image format");
466             supportsExtension("inta","inta image format");
467             supportsExtension("bw","bw image format");
468         }
469 
className() const470         virtual const char* className() const { return "RGB Image Reader/Writer"; }
471 
readRGBStream(std::istream & fin) const472         ReadResult readRGBStream(std::istream& fin) const
473         {
474             rawImageRec *raw;
475 
476             if( (raw = RawImageOpen(fin)) == NULL )
477             {
478                 return ReadResult::ERROR_IN_READING_FILE;
479             }
480 
481             int s = raw->sizeX;
482             int t = raw->sizeY;
483             int r = 1;
484 
485             unsigned int pixelFormat =
486                 raw->sizeZ == 1 ? GL_LUMINANCE :
487                 raw->sizeZ == 2 ? GL_LUMINANCE_ALPHA :
488                 raw->sizeZ == 3 ? GL_RGB :
489                 raw->sizeZ == 4 ? GL_RGBA : (GLenum)-1;
490 
491             int internalFormat = pixelFormat;
492 
493             unsigned int dataType = raw->bpc == 1 ? GL_UNSIGNED_BYTE :
494               GL_UNSIGNED_SHORT;
495 
496             unsigned char *data;
497             RawImageGetData(raw, &data);
498             RawImageClose(raw);
499 
500             Image* image = new Image();
501             image->setImage(s,t,r,
502                 internalFormat,
503                 pixelFormat,
504                 dataType,
505                 data,
506                 osg::Image::USE_NEW_DELETE);
507 
508             OSG_INFO << "image read ok "<<s<<"  "<<t<< std::endl;
509             return image;
510         }
511 
readObject(std::istream & fin,const osgDB::ReaderWriter::Options * options=NULL) const512         virtual ReadResult readObject(std::istream& fin,const osgDB::ReaderWriter::Options* options =NULL) const
513         {
514             return readImage(fin, options);
515         }
516 
readObject(const std::string & file,const osgDB::ReaderWriter::Options * options=NULL) const517         virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const
518         {
519             return readImage(file, options);
520         }
521 
readImage(std::istream & fin,const osgDB::ReaderWriter::Options * =NULL) const522         virtual ReadResult readImage(std::istream& fin,const osgDB::ReaderWriter::Options* =NULL) const
523         {
524             return readRGBStream(fin);
525         }
526 
readImage(const std::string & file,const osgDB::ReaderWriter::Options * options) const527         virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
528         {
529             std::string ext = osgDB::getLowerCaseFileExtension(file);
530             if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
531 
532             std::string fileName = osgDB::findDataFile( file, options );
533             if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
534 
535             osgDB::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);
536             if(!istream) return ReadResult::FILE_NOT_HANDLED;
537             ReadResult rr = readRGBStream(istream);
538             if(rr.validImage()) rr.getImage()->setFileName(file);
539             return rr;
540         }
541 
writeRGBStream(const osg::Image & img,std::ostream & fout,const std::string & name) const542         WriteResult writeRGBStream(const osg::Image& img, std::ostream &fout, const std::string& name) const
543         {
544             rawImageRec raw;
545             raw.imagic = 0732;
546 
547             GLenum dataType = img.getDataType();
548 
549             raw.type  = dataType == GL_UNSIGNED_BYTE ? 1 :
550                 dataType == GL_BYTE ? 1 :
551                 dataType == GL_BITMAP ? 1 :
552                 dataType == GL_UNSIGNED_SHORT ? 2 :
553                 dataType == GL_SHORT ? 2 :
554                 dataType == GL_UNSIGNED_INT ? 4 :
555                 dataType == GL_INT ? 4 :
556                 dataType == GL_FLOAT ? 4 :
557                 dataType == GL_UNSIGNED_BYTE_3_3_2 ? 1 :
558                 dataType == GL_UNSIGNED_BYTE_2_3_3_REV ? 1 :
559                 dataType == GL_UNSIGNED_SHORT_5_6_5 ? 2 :
560                 dataType == GL_UNSIGNED_SHORT_5_6_5_REV ? 2 :
561                 dataType == GL_UNSIGNED_SHORT_4_4_4_4 ? 2 :
562                 dataType == GL_UNSIGNED_SHORT_4_4_4_4_REV ? 2 :
563                 dataType == GL_UNSIGNED_SHORT_5_5_5_1 ? 2 :
564                 dataType == GL_UNSIGNED_SHORT_1_5_5_5_REV ? 2 :
565                 dataType == GL_UNSIGNED_INT_8_8_8_8 ? 4 :
566                 dataType == GL_UNSIGNED_INT_8_8_8_8_REV ? 4 :
567                 dataType == GL_UNSIGNED_INT_10_10_10_2 ? 4 :
568                 dataType == GL_UNSIGNED_INT_2_10_10_10_REV ? 4 : 4;
569 
570             GLenum pixelFormat = img.getPixelFormat();
571 
572             raw.dim    = 3;
573             raw.sizeX = img.s();
574             raw.sizeY = img.t();
575             raw.sizeZ =
576                 pixelFormat == GL_COLOR_INDEX? 1 :
577                 pixelFormat == GL_RED? 1 :
578                 pixelFormat == GL_GREEN? 1 :
579                 pixelFormat == GL_BLUE? 1 :
580                 pixelFormat == GL_ALPHA? 1 :
581                 pixelFormat == GL_RGB? 3 :
582                 pixelFormat == GL_BGR ? 3 :
583                 pixelFormat == GL_RGBA? 4 :
584                 pixelFormat == GL_BGRA? 4 :
585                 pixelFormat == GL_LUMINANCE? 1 :
586                 pixelFormat == GL_LUMINANCE_ALPHA ? 2 : 1;
587             raw.min = 0;
588             raw.max = 0xFF;
589             raw.wasteBytes = 0;
590             strncpy( raw.name, name.c_str(), 80);
591             raw.colorMap = 0;
592             raw.bpc = (img.getPixelSizeInBits()/raw.sizeZ)/8;
593 
594             int isize = img.getImageSizeInBytes();
595             unsigned char *buffer = new unsigned char[isize];
596             if(raw.bpc == 1)
597             {
598                 unsigned char *dptr = buffer;
599                 int i, j;
600                 for( i = 0; i < raw.sizeZ; ++i )
601                 {
602                     const unsigned char *ptr = img.data();
603                     ptr += i;
604                     for( j = 0; j < isize/raw.sizeZ; ++j )
605                     {
606                         *(dptr++) = *ptr;
607                         ptr += raw.sizeZ;
608                     }
609                 }
610             }
611             else
612             { // bpc == 2
613                 unsigned short *dptr = reinterpret_cast<unsigned short*>(buffer);
614                 int i, j;
615                 for( i = 0; i < raw.sizeZ; ++i )
616                 {
617                     const unsigned short *ptr = reinterpret_cast<const unsigned short*>(img.data());
618                     ptr += i;
619                     for( j = 0; j < isize/(raw.sizeZ*2); ++j )
620                     {
621                         *dptr = *ptr;
622                         ConvertShort(dptr++, 1);
623                         ptr += raw.sizeZ;
624                     }
625                 }
626             }
627 
628 
629             if( raw.needsBytesSwapped() )
630                 raw.swapBytes();
631 
632             /*
633             swapBytes( raw.imagic );
634             swapBytes( raw.type );
635             swapBytes( raw.dim );
636             swapBytes( raw.sizeX );
637             swapBytes( raw.sizeY );
638             swapBytes( raw.sizeZ );
639             swapBytes( raw.min );
640             swapBytes( raw.max );
641             swapBytes( raw.colorMap );
642             */
643 
644 
645             char pad[512 - sizeof(rawImageRec)];
646             memset( pad, 0, sizeof(pad));
647 
648             fout.write((const char*)&raw,sizeof(rawImageRec));
649             fout.write((const char*)pad,sizeof(pad));
650             fout.write((const char*)buffer,isize);
651 
652             delete [] buffer;
653 
654             return WriteResult::FILE_SAVED;
655         }
656 
writeImage(const osg::Image & img,std::ostream & fout,const osgDB::ReaderWriter::Options *) const657         virtual WriteResult writeImage(const osg::Image& img,std::ostream& fout,const osgDB::ReaderWriter::Options*) const
658         {
659             if (img.isCompressed())
660             {
661                 OSG_NOTICE<<"Warning: RGB plugin does not supporting writing compressed imagery."<<std::endl;
662                 return WriteResult::ERROR_IN_WRITING_FILE;
663             }
664             if (!img.isDataContiguous())
665             {
666                 OSG_NOTICE<<"Warning: RGB plugin does not supporting writing non contiguous imagery."<<std::endl;
667                 return WriteResult::ERROR_IN_WRITING_FILE;
668             }
669 
670             return writeRGBStream(img,fout,"");
671         }
672 
writeImage(const osg::Image & img,const std::string & fileName,const osgDB::ReaderWriter::Options *) const673         virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options*) const
674         {
675             if (img.isCompressed())
676             {
677                 OSG_NOTICE<<"Warning: RGB plugin does not supporting writing compressed imagery."<<std::endl;
678                 return WriteResult::ERROR_IN_WRITING_FILE;
679             }
680             if (!img.isDataContiguous())
681             {
682                 OSG_NOTICE<<"Warning: RGB plugin does not supporting writing non contiguous imagery."<<std::endl;
683                 return WriteResult::ERROR_IN_WRITING_FILE;
684             }
685 
686             std::string ext = osgDB::getFileExtension(fileName);
687             if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
688 
689             osgDB::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary);
690             if(!fout) return WriteResult::ERROR_IN_WRITING_FILE;
691 
692             return writeRGBStream(img,fout,fileName);
693         }
694 
695 };
696 
697 // now register with Registry to instantiate the above
698 // reader/writer.
699 REGISTER_OSGPLUGIN(rgb, ReaderWriterRGB)
700