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

Revision 10939, 17.2 kB (checked in by robert, 5 years ago)

From Laurens Voerman,"the current ReaderWriterJP2 has all the code for writing jp2 files (jpeg 2000), but the writing fails on my windows machine (jasper-1.900.1) because the ID for the "jp2" extention is requested before the jas_init() call. (bug introduced in svn 7645 - 10 dec 2007)"

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