root/OpenSceneGraph/trunk/src/osgPlugins/jp2/ReaderWriterJP2.cpp @ 8578

Revision 8578, 17.1 kB (checked in by robert, 6 years ago)

Converted plugins to use the new supportsExtension()/supportsOptions/supportsProtocl() methods
to help enable better querying of supported features

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Image>
2#include <osg/Notify>
3
4#include <osg/Geode>
5
6#include <osg/GL>
7
8#include <osgDB/FileNameUtils>
9#include <osgDB/FileUtils>
10#include <osgDB/Registry>
11
12#include <string>
13#include <sstream>
14#include <vector>
15#include <stdio.h>
16#include <stdlib.h>
17
18extern "C"
19{
20    #include <jasper/jasper.h>
21}
22
23#ifndef SEEK_SET
24define SEEK_SET 0
25#endif
26
27using namespace osg;
28
29
30extern "C" {
31
32    static int putdata(jas_stream_t *out, jas_image_t *image, int numcmpts)
33    {
34        int ret;
35        int cmptno;
36        int x;
37        int y;
38        jas_matrix_t *data[4];
39        jas_seqent_t *d[4];
40        jas_seqent_t v;
41        int linelen;
42        int width, height;
43
44        width = jas_image_cmptwidth(image, 0);
45        height = jas_image_cmptheight(image, 0);
46
47        ret = -1;
48
49        data[0] = 0;
50        data[1] = 0;
51        data[2] = 0;
52        data[3] = 0;
53        for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
54            if (!(data[cmptno] = jas_matrix_create(1, width))) {
55                goto done;
56            }
57        }
58
59        for (y = height - 1; y >= 0; --y) {
60            for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
61                if (jas_image_readcmpt(image, cmptno, 0, y, width, 1,
62                  data[cmptno])) {
63                    goto done;
64                }
65                d[cmptno] = jas_matrix_getref(data[cmptno], 0, 0);
66            }
67            linelen = 0;
68            for (x = 0; x < width; ++x) {
69                for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
70                    v = *d[cmptno];
71                    if (v < 0) {
72                        v = 0;
73                    }
74                    if (v > 255) {
75                        v = 255;
76                    }
77                    unsigned char c;
78                    c = v;
79                    if (jas_stream_putc(out, c) == EOF) {
80                        goto done;
81                    }
82                    ++d[cmptno];
83                }
84            }
85            if (jas_stream_error(out)) {
86                goto done;
87            }
88        }
89
90        jas_stream_flush(out);
91        ret = 0;
92
93    done:
94
95        for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
96            if (data[cmptno]) {
97                jas_matrix_destroy(data[cmptno]);
98            }
99        }
100
101        return ret;
102    }
103
104    static int getdata(jas_stream_t *in, jas_image_t *image)
105    {
106        int ret;
107        int numcmpts;
108        int cmptno;
109        jas_matrix_t *data[4];
110        int x;
111        int y;
112        int width, height;
113
114        width = jas_image_cmptwidth(image, 0);
115        height = jas_image_cmptheight(image, 0);
116        numcmpts = jas_image_numcmpts(image);
117
118        ret = -1;
119
120        data[0] = 0;
121        data[1] = 0;
122        data[2] = 0;
123        data[3] = 0;
124        for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
125            if (!(data[cmptno] = jas_matrix_create(1, width))) {
126                goto done;
127            }
128        }
129
130        for (y = height - 1; y >= 0; --y)
131//        for (y = 0; y < height; ++y)
132        {
133            for (x = 0; x < width; ++x)
134            {
135                for (cmptno = 0; cmptno < numcmpts; ++cmptno)
136                {
137                    /* The sample data is unsigned. */
138                    int c;
139                    if ((c = jas_stream_getc(in)) == EOF) {
140                        return -1;
141                    }
142                    jas_matrix_set(data[cmptno], 0, x, c);
143                }
144            }
145            for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
146                if (jas_image_writecmpt(image, cmptno, 0, y, width, 1,
147                  data[cmptno])) {
148                    goto done;
149                }
150            }
151        }
152
153        jas_stream_flush(in);
154
155        ret = 0;
156
157    done:
158
159        for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
160            if (data[cmptno]) {
161                jas_matrix_destroy(data[cmptno]);
162            }
163        }
164
165        return ret;
166    }
167
168}
169
170class ReaderWriterJP2 : public osgDB::ReaderWriter
171{
172    public:
173
174
175        ReaderWriterJP2()
176        {
177            supportsExtension("jp2","Jpeg2000 image format");
178            supportsExtension("jpc","Jpeg2000 image format");
179       
180            // little dance here to get around warnings created by jas_image_strtofmt use of char* rather than const char*
181            // as a parameted and modern compilers deprecating "jp2" string being treated as char*.
182            char* jp2 = strdup("jp2");
183            _fmt_jp2 = jas_image_strtofmt(jp2);
184            free(jp2);
185        }
186
187        virtual const char* className() const { return "RGB Image Reader/Writer"; }
188       
189        virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options) const
190        {
191            return readImage(file,options);
192        }
193
194        virtual ReadResult readObject(std::istream& fin, const Options* options) const
195        {
196            return readImage(fin,options);
197        }
198
199
200        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
201        {
202            std::string ext = osgDB::getFileExtension(file);
203            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
204
205            std::string fileName = osgDB::findDataFile( file, options );
206            if(fileName.empty())
207            {
208                // note from Robert, Dec03, I find returning a valid image when no
209                // file exists a bit odd...
210                osg::Image *img = new osg::Image;
211                img->setFileName(fileName);
212                return img;
213            }
214
215            jas_init();
216
217            jas_stream_t* in = jas_stream_fopen(fileName.c_str(), "rb");
218
219            char* opt = 0;
220            if(options)
221            {
222                opt = new char[options->getOptionString().size() + 1];
223                strcpy(opt, options->getOptionString().c_str());
224            }
225            jas_image_t* jimage = jas_image_decode(in, -1, opt); // last is the option string whatto put there?
226            if(opt) delete[] opt;
227
228            int internalFormat = jimage->numcmpts_;
229
230            int s = jas_image_width(jimage);
231            int t = jas_image_height(jimage);
232            int r = 1;
233
234            unsigned char* data = new unsigned char[internalFormat*s*t];
235
236            jas_stream_t* mem = jas_stream_memopen((char*)data, internalFormat*s*t);
237
238            putdata(mem, jimage, internalFormat);
239
240            jas_image_destroy(jimage);
241            jas_stream_close(in);
242            jas_image_clearfmts();
243
244            unsigned int pixelFormat =
245                internalFormat == 1 ? GL_LUMINANCE :
246                internalFormat == 2 ? GL_LUMINANCE_ALPHA :
247                internalFormat == 3 ? GL_RGB :
248                internalFormat == 4 ? GL_RGBA : (GLenum)-1;
249
250            unsigned int dataType = GL_UNSIGNED_BYTE;
251
252            Image* image = new Image();
253            image->setFileName(fileName.c_str());
254            image->setImage(s,t,r,
255                internalFormat,
256                pixelFormat,
257                dataType,
258                data,
259//                osg::Image::USE_NEW_DELETE);
260                osg::Image::NO_DELETE);
261
262            notify(INFO) << "image read ok "<<s<<"  "<<t<< std::endl;
263            return image;
264
265        }
266
267        virtual ReadResult readImage(std::istream& fin,const Options* options) const
268        {
269            char c;
270            char * sdata;
271            long ssize;
272            std::vector<char> vdata;
273
274            while(!fin.eof())
275            {
276                fin.read(&c, 1);
277                vdata.push_back(c);
278            }
279            ssize = vdata.size();
280
281            sdata = &vdata[0];
282
283            jas_init();
284
285            jas_stream_t* in = jas_stream_memopen((char*)sdata, ssize);
286
287            char* opt = 0;
288            if(options && !options->getOptionString().empty())
289            {
290                opt = new char[options->getOptionString().size() + 1];
291                strcpy(opt, options->getOptionString().c_str());
292            }
293            jas_image_t* jimage = jas_image_decode(in, -1, opt); // last is the option string whatto put there?
294            if(opt) delete[] opt;
295           
296            if (!jimage) return ReadResult::FILE_NOT_HANDLED;
297
298            int internalFormat = jimage->numcmpts_;
299
300            int s = jas_image_width(jimage);
301            int t = jas_image_height(jimage);
302            int r = 1;
303
304            unsigned char* data = new unsigned char[internalFormat*s*t];
305
306            jas_stream_t* mem = jas_stream_memopen((char*)data, internalFormat*s*t);
307
308            putdata(mem, jimage, internalFormat);
309
310            jas_image_destroy(jimage);
311            jas_stream_close(in);
312            jas_image_clearfmts();
313
314            unsigned int pixelFormat =
315                internalFormat == 1 ? GL_LUMINANCE :
316                internalFormat == 2 ? GL_LUMINANCE_ALPHA :
317                internalFormat == 3 ? GL_RGB :
318                internalFormat == 4 ? GL_RGBA : (GLenum)-1;
319
320            unsigned int dataType = GL_UNSIGNED_BYTE;
321
322            Image* image = new Image();
323//            image->setFileName(fileName.c_str());
324            image->setImage(s,t,r,
325                internalFormat,
326                pixelFormat,
327                dataType,
328                data,
329//                osg::Image::USE_NEW_DELETE);
330                osg::Image::NO_DELETE);
331
332            notify(INFO) << "image read ok "<<s<<"  "<<t<< std::endl;
333            return image;
334        }
335
336        virtual WriteResult writeObject(const osg::Object& object,const std::string& file, const osgDB::ReaderWriter::Options* options) const
337        {
338            const osg::Image* image = dynamic_cast<const osg::Image*>(&object);
339            if (!image) return WriteResult::FILE_NOT_HANDLED;
340
341            return writeImage(*image,file,options);
342        }
343
344        virtual WriteResult writeObject(const osg::Object& object,std::ostream& fout,const Options* options) const
345        {
346            const osg::Image* image = dynamic_cast<const osg::Image*>(&object);
347            if (!image) return WriteResult::FILE_NOT_HANDLED;
348
349            return writeImage(*image,fout,options);
350        }
351
352        virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
353        {
354            std::string ext = osgDB::getFileExtension(fileName);
355            if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
356           
357            jas_init();
358
359            jas_image_cmptparm_t cmptparms[4];
360            jas_image_cmptparm_t *cmptparm;
361
362            int internalFormat = osg::Image::computeNumComponents(img.getPixelFormat());
363
364            jas_stream_t* mem = jas_stream_memopen((char*)img.data(), internalFormat*img.s()*img.t());
365
366            /* Create an image of the correct size. */
367            jas_image_t* jimage;
368            int i;
369            for (i = 0, cmptparm = cmptparms; i < internalFormat; ++i, ++cmptparm) {
370                cmptparm->tlx = 0;
371                cmptparm->tly = 0;
372                cmptparm->hstep = 1;
373                cmptparm->vstep = 1;
374                cmptparm->width = img.s();
375                cmptparm->height = img.t();
376                cmptparm->prec = 8;
377                cmptparm->sgnd = 0;
378            }
379            if (!(jimage = jas_image_create(internalFormat, cmptparms, JAS_CLRSPC_UNKNOWN))) {
380                return WriteResult::ERROR_IN_WRITING_FILE;
381            }
382
383            if(internalFormat == 1)
384            {
385                jas_image_setclrspc(jimage, JAS_CLRSPC_GENGRAY);
386                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
387            }
388            else if(internalFormat == 2)
389            {
390                jas_image_setclrspc(jimage, JAS_CLRSPC_GENGRAY);
391                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
392                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
393            }
394            else if(internalFormat == 3)
395            {
396                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
397                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
398                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
399                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
400            }
401            else if(internalFormat == 4)
402            {
403                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
404                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
405                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
406                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
407                jas_image_setcmpttype(jimage, 3, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
408            }
409
410            getdata(mem, jimage);
411
412            jas_stream_t* out = jas_stream_fopen(fileName.c_str(), "wb");
413            if (!out)
414                return WriteResult::ERROR_IN_WRITING_FILE;
415
416            char* opt = 0;
417            if(options)
418            {
419                opt = new char[options->getOptionString().size() + 1];
420                strcpy(opt, options->getOptionString().c_str());
421            }
422            jas_image_encode(jimage, out, _fmt_jp2,  opt);
423            if(opt) delete[] opt;
424
425            jas_stream_flush(out);
426
427            jas_stream_close(out);
428            jas_image_destroy(jimage);
429            jas_image_clearfmts();
430
431            return WriteResult::FILE_SAVED;
432        }
433
434        WriteResult writeImage(const osg::Image& img, std::ostream& fout, const Options* options) const
435        {
436            jas_init();
437
438            jas_image_cmptparm_t cmptparms[4];
439            jas_image_cmptparm_t *cmptparm;
440
441            int internalFormat = osg::Image::computeNumComponents(img.getPixelFormat());
442
443            jas_stream_t* mem = jas_stream_memopen((char*)img.data(), internalFormat*img.s()*img.t());
444
445            /* Create an image of the correct size. */
446            jas_image_t* jimage;
447            int i;
448            for (i = 0, cmptparm = cmptparms; i < internalFormat; ++i, ++cmptparm) {
449                cmptparm->tlx = 0;
450                cmptparm->tly = 0;
451                cmptparm->hstep = 1;
452                cmptparm->vstep = 1;
453                cmptparm->width = img.s();
454                cmptparm->height = img.t();
455                cmptparm->prec = 8;
456                cmptparm->sgnd = 0;
457            }
458            if (!(jimage = jas_image_create(internalFormat, cmptparms, JAS_CLRSPC_UNKNOWN))) {
459                return WriteResult::ERROR_IN_WRITING_FILE;
460            }
461
462            if(internalFormat == 1)
463            {
464                jas_image_setclrspc(jimage, JAS_CLRSPC_SGRAY);
465                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
466            }
467            else if(internalFormat == 2)
468            {
469                jas_image_setclrspc(jimage, JAS_CLRSPC_SGRAY);
470                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
471                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
472            }
473            else if(internalFormat == 3)
474            {
475                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
476                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
477                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
478                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
479            }
480            else if(internalFormat == 4)
481            {
482                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
483                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
484                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
485                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
486                jas_image_setcmpttype(jimage, 3, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
487            }
488
489            getdata(mem, jimage);
490
491            jas_stream_t* out = jas_stream_memopen(0, 0);
492//            jas_stream_t* out = jas_stream_fopen(fileName.c_str(), "wb");
493            if (!out)
494                return WriteResult::ERROR_IN_WRITING_FILE;
495
496            char* opt = 0;
497            if(options)
498            {
499                opt = new char[options->getOptionString().size() + 1];
500                strcpy(opt, options->getOptionString().c_str());
501            }
502           
503            jas_image_encode(jimage, out, _fmt_jp2,  opt);
504            if(opt) delete[] opt;
505
506            jas_stream_flush(out);
507
508            // now the encoded jp2 image resides in the out->buf_ member with size out->len_ we now need to stream it to a std::ostream
509            jas_stream_memobj_t* obj = (jas_stream_memobj_t*) out->obj_;
510
511            fout.write((char*)obj->buf_, obj->len_);
512
513            fout << std::flush;
514
515            jas_stream_close(out);
516
517            jas_image_destroy(jimage);
518            jas_image_clearfmts();
519
520            return WriteResult::FILE_SAVED;
521        }
522
523
524        int _fmt_jp2;
525};
526
527// now register with Registry to instantiate the above
528// reader/writer.
529REGISTER_OSGPLUGIN(jp2, ReaderWriterJP2)
Note: See TracBrowser for help on using the browser.