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

Revision 13041, 18.0 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

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