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

Revision 10940, 17.2 kB (checked in by robert, 4 years ago)

Added desctructor with jas_cleanup().

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