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

Revision 12217, 16.9 kB (checked in by robert, 4 years ago)

Removed the repeated called to jas_init() and jas_image_clearfmts() calls to make it possible to use the reading multi-threaded

  • 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            jas_init();
181
182            // little dance here to get around warnings created by jas_image_strtofmt use of char* rather than const char*
183            // as a parameted and modern compilers deprecating "jp2" string being treated as char*.
184            char* jp2 = strdup("jp2");
185            _fmt_jp2 = jas_image_strtofmt(jp2);
186            free(jp2);
187        }
188
189        ~ReaderWriterJP2()
190        {
191            jas_cleanup();
192        }
193
194        virtual const char* className() const { return "RGB Image Reader/Writer"; }
195
196        virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options) const
197        {
198            return readImage(file,options);
199        }
200
201        virtual ReadResult readObject(std::istream& fin, const Options* options) const
202        {
203            return readImage(fin,options);
204        }
205
206
207        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
208        {
209            std::string ext = osgDB::getFileExtension(file);
210            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
211
212            std::string fileName = osgDB::findDataFile( file, options );
213            if(fileName.empty())
214            {
215                // note from Robert, Dec03, I find returning a valid image when no
216                // file exists a bit odd...
217                osg::Image *img = new osg::Image;
218                img->setFileName(fileName);
219                return img;
220            }
221
222            jas_stream_t* in = jas_stream_fopen(fileName.c_str(), "rb");
223
224            char* opt = 0;
225            if(options)
226            {
227                opt = new char[options->getOptionString().size() + 1];
228                strcpy(opt, options->getOptionString().c_str());
229            }
230            jas_image_t* jimage = jas_image_decode(in, -1, opt); // last is the option string whatto put there?
231            if(opt) delete[] opt;
232
233            int internalFormat = jimage->numcmpts_;
234
235            int s = jas_image_width(jimage);
236            int t = jas_image_height(jimage);
237            int r = 1;
238
239            unsigned char* data = new unsigned char[internalFormat*s*t];
240
241            jas_stream_t* mem = jas_stream_memopen((char*)data, internalFormat*s*t);
242
243            putdata(mem, jimage, internalFormat);
244
245            jas_image_destroy(jimage);
246            jas_stream_close(in);
247
248            unsigned int pixelFormat =
249                internalFormat == 1 ? GL_LUMINANCE :
250                internalFormat == 2 ? GL_LUMINANCE_ALPHA :
251                internalFormat == 3 ? GL_RGB :
252                internalFormat == 4 ? GL_RGBA : (GLenum)-1;
253
254            unsigned int dataType = GL_UNSIGNED_BYTE;
255
256            Image* image = new Image();
257            image->setFileName(fileName.c_str());
258            image->setImage(s,t,r,
259                internalFormat,
260                pixelFormat,
261                dataType,
262                data,
263//                osg::Image::USE_NEW_DELETE);
264                osg::Image::NO_DELETE);
265
266            OSG_INFO << "image read ok "<<s<<"  "<<t<< std::endl;
267            return image;
268
269        }
270
271        virtual ReadResult readImage(std::istream& fin,const Options* options) const
272        {
273            char c;
274            char * sdata;
275            long ssize;
276            std::vector<char> vdata;
277
278            while(!fin.eof())
279            {
280                fin.read(&c, 1);
281                vdata.push_back(c);
282            }
283            ssize = vdata.size();
284
285            sdata = &vdata[0];
286
287            jas_stream_t* in = jas_stream_memopen((char*)sdata, ssize);
288
289            char* opt = 0;
290            if(options && !options->getOptionString().empty())
291            {
292                opt = new char[options->getOptionString().size() + 1];
293                strcpy(opt, options->getOptionString().c_str());
294            }
295            jas_image_t* jimage = jas_image_decode(in, -1, opt); // last is the option string whatto put there?
296            if(opt) delete[] opt;
297           
298            if (!jimage) return ReadResult::FILE_NOT_HANDLED;
299
300            int internalFormat = jimage->numcmpts_;
301
302            int s = jas_image_width(jimage);
303            int t = jas_image_height(jimage);
304            int r = 1;
305
306            unsigned char* data = new unsigned char[internalFormat*s*t];
307
308            jas_stream_t* mem = jas_stream_memopen((char*)data, internalFormat*s*t);
309
310            putdata(mem, jimage, internalFormat);
311
312            jas_image_destroy(jimage);
313            jas_stream_close(in);
314
315            unsigned int pixelFormat =
316                internalFormat == 1 ? GL_LUMINANCE :
317                internalFormat == 2 ? GL_LUMINANCE_ALPHA :
318                internalFormat == 3 ? GL_RGB :
319                internalFormat == 4 ? GL_RGBA : (GLenum)-1;
320
321            unsigned int dataType = GL_UNSIGNED_BYTE;
322
323            Image* image = new Image();
324//            image->setFileName(fileName.c_str());
325            image->setImage(s,t,r,
326                internalFormat,
327                pixelFormat,
328                dataType,
329                data,
330//                osg::Image::USE_NEW_DELETE);
331                osg::Image::NO_DELETE);
332
333            OSG_INFO << "image read ok "<<s<<"  "<<t<< std::endl;
334            return image;
335        }
336
337        virtual WriteResult writeObject(const osg::Object& object,const std::string& file, const osgDB::ReaderWriter::Options* options) const
338        {
339            const osg::Image* image = dynamic_cast<const osg::Image*>(&object);
340            if (!image) return WriteResult::FILE_NOT_HANDLED;
341
342            return writeImage(*image,file,options);
343        }
344
345        virtual WriteResult writeObject(const osg::Object& object,std::ostream& fout,const Options* options) const
346        {
347            const osg::Image* image = dynamic_cast<const osg::Image*>(&object);
348            if (!image) return WriteResult::FILE_NOT_HANDLED;
349
350            return writeImage(*image,fout,options);
351        }
352
353        virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
354        {
355            std::string ext = osgDB::getFileExtension(fileName);
356            if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
357
358            jas_image_cmptparm_t cmptparms[4];
359            jas_image_cmptparm_t *cmptparm;
360
361            int internalFormat = osg::Image::computeNumComponents(img.getPixelFormat());
362
363            jas_stream_t* mem = jas_stream_memopen((char*)img.data(), internalFormat*img.s()*img.t());
364
365            /* Create an image of the correct size. */
366            jas_image_t* jimage;
367            int i;
368            for (i = 0, cmptparm = cmptparms; i < internalFormat; ++i, ++cmptparm) {
369                cmptparm->tlx = 0;
370                cmptparm->tly = 0;
371                cmptparm->hstep = 1;
372                cmptparm->vstep = 1;
373                cmptparm->width = img.s();
374                cmptparm->height = img.t();
375                cmptparm->prec = 8;
376                cmptparm->sgnd = 0;
377            }
378            if (!(jimage = jas_image_create(internalFormat, cmptparms, JAS_CLRSPC_UNKNOWN))) {
379                return WriteResult::ERROR_IN_WRITING_FILE;
380            }
381
382            if(internalFormat == 1)
383            {
384                jas_image_setclrspc(jimage, JAS_CLRSPC_GENGRAY);
385                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
386            }
387            else if(internalFormat == 2)
388            {
389                jas_image_setclrspc(jimage, JAS_CLRSPC_GENGRAY);
390                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
391                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
392            }
393            else if(internalFormat == 3)
394            {
395                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
396                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
397                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
398                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
399            }
400            else if(internalFormat == 4)
401            {
402                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
403                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
404                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
405                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
406                jas_image_setcmpttype(jimage, 3, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
407            }
408
409            getdata(mem, jimage);
410
411            jas_stream_t* out = jas_stream_fopen(fileName.c_str(), "wb");
412            if (!out)
413                return WriteResult::ERROR_IN_WRITING_FILE;
414
415            char* opt = 0;
416            if(options)
417            {
418                opt = new char[options->getOptionString().size() + 1];
419                strcpy(opt, options->getOptionString().c_str());
420            }
421            jas_image_encode(jimage, out, _fmt_jp2,  opt);
422            if(opt) delete[] opt;
423
424            jas_stream_flush(out);
425
426            jas_stream_close(out);
427            jas_image_destroy(jimage);
428
429            return WriteResult::FILE_SAVED;
430        }
431
432        WriteResult writeImage(const osg::Image& img, std::ostream& fout, const Options* options) const
433        {
434            jas_image_cmptparm_t cmptparms[4];
435            jas_image_cmptparm_t *cmptparm;
436
437            int internalFormat = osg::Image::computeNumComponents(img.getPixelFormat());
438
439            jas_stream_t* mem = jas_stream_memopen((char*)img.data(), internalFormat*img.s()*img.t());
440
441            /* Create an image of the correct size. */
442            jas_image_t* jimage;
443            int i;
444            for (i = 0, cmptparm = cmptparms; i < internalFormat; ++i, ++cmptparm) {
445                cmptparm->tlx = 0;
446                cmptparm->tly = 0;
447                cmptparm->hstep = 1;
448                cmptparm->vstep = 1;
449                cmptparm->width = img.s();
450                cmptparm->height = img.t();
451                cmptparm->prec = 8;
452                cmptparm->sgnd = 0;
453            }
454            if (!(jimage = jas_image_create(internalFormat, cmptparms, JAS_CLRSPC_UNKNOWN))) {
455                return WriteResult::ERROR_IN_WRITING_FILE;
456            }
457
458            if(internalFormat == 1)
459            {
460                jas_image_setclrspc(jimage, JAS_CLRSPC_SGRAY);
461                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
462            }
463            else if(internalFormat == 2)
464            {
465                jas_image_setclrspc(jimage, JAS_CLRSPC_SGRAY);
466                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
467                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
468            }
469            else if(internalFormat == 3)
470            {
471                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
472                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
473                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
474                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
475            }
476            else if(internalFormat == 4)
477            {
478                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
479                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
480                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
481                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
482                jas_image_setcmpttype(jimage, 3, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
483            }
484
485            getdata(mem, jimage);
486
487            jas_stream_t* out = jas_stream_memopen(0, 0);
488//            jas_stream_t* out = jas_stream_fopen(fileName.c_str(), "wb");
489            if (!out)
490                return WriteResult::ERROR_IN_WRITING_FILE;
491
492            char* opt = 0;
493            if(options)
494            {
495                opt = new char[options->getOptionString().size() + 1];
496                strcpy(opt, options->getOptionString().c_str());
497            }
498
499            jas_image_encode(jimage, out, _fmt_jp2,  opt);
500            if(opt) delete[] opt;
501
502            jas_stream_flush(out);
503
504            // 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
505            jas_stream_memobj_t* obj = (jas_stream_memobj_t*) out->obj_;
506
507            fout.write((char*)obj->buf_, obj->len_);
508
509            fout << std::flush;
510
511            jas_stream_close(out);
512
513            jas_image_destroy(jimage);
514
515            return WriteResult::FILE_SAVED;
516        }
517
518
519        int _fmt_jp2;
520};
521
522// now register with Registry to instantiate the above
523// reader/writer.
524REGISTER_OSGPLUGIN(jp2, ReaderWriterJP2)
Note: See TracBrowser for help on using the browser.