I'm pretty sure you'll prefer merging with the modified file in hand :)
Base revision is 12597.

Sukender

----- Mail original -----
De: [email protected]
À: "OpenSceneGraph Submissions" <[email protected]>
Envoyé: Mercredi 2 Novembre 2011 20:40:23
Objet: [osg-submissions] Fixed using UTF8 paths in JP2 readerwriter under       
Windows

Hi Robert,

I just fixed using UTF8 paths in JP2 readerwriter under Windows. Jpeg2000 
plugin could not handle UTF8 paths as it was using an Japser open() function 
which seems to be based on the standard fopen(). The fix simply opens the file 
beforehand and only gives a FILE* to the Jasper lib (and then closes the file, 
of course).

Happy merging!

Sukender
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
#include <osg/Image>
#include <osg/Notify>

#include <osg/Geode>

#include <osg/GL>

#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/Registry>

#include <string>
#include <sstream>
#include <vector>
#include <stdio.h>
#include <stdlib.h>

extern "C"
{
    #include <jasper/jasper.h>
}

#ifndef SEEK_SET
#  define SEEK_SET 0
#endif

using namespace osg;


extern "C" {

    static int putdata(jas_stream_t *out, jas_image_t *image, int numcmpts)
    {
        int ret;
        int cmptno;
        int x;
        int y;
        jas_matrix_t *data[4];
        jas_seqent_t *d[4];
        jas_seqent_t v;
        int width, height;

        width = jas_image_cmptwidth(image, 0);
        height = jas_image_cmptheight(image, 0);

        ret = -1;

        data[0] = 0;
        data[1] = 0;
        data[2] = 0;
        data[3] = 0;
        for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
            if (!(data[cmptno] = jas_matrix_create(1, width))) {
                goto done;
            }
        }

        for (y = height - 1; y >= 0; --y) {
            for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
                if (jas_image_readcmpt(image, cmptno, 0, y, width, 1,
                  data[cmptno])) {
                    goto done;
                }
                d[cmptno] = jas_matrix_getref(data[cmptno], 0, 0);
            }
            for (x = 0; x < width; ++x) {
                for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
                    v = *d[cmptno];
                    if (v < 0) {
                        v = 0;
                    }
                    if (v > 255) {
                        v = 255;
                    }
                    unsigned char c;
                    c = v;
                    if (jas_stream_putc(out, c) == EOF) {
                        goto done;
                    }
                    ++d[cmptno];
                }
            }
            if (jas_stream_error(out)) {
                goto done;
            }
        }

        jas_stream_flush(out);
        ret = 0;

    done:

        for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
            if (data[cmptno]) {
                jas_matrix_destroy(data[cmptno]);
            }
        }

        return ret;
    }

    static int getdata(jas_stream_t *in, jas_image_t *image)
    {
        int ret;
        int numcmpts;
        int cmptno;
        jas_matrix_t *data[4];
        int x;
        int y;
        int width, height;

        width = jas_image_cmptwidth(image, 0);
        height = jas_image_cmptheight(image, 0);
        numcmpts = jas_image_numcmpts(image);

        ret = -1;

        data[0] = 0;
        data[1] = 0;
        data[2] = 0;
        data[3] = 0;
        for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
            if (!(data[cmptno] = jas_matrix_create(1, width))) {
                goto done;
            }
        }

        for (y = height - 1; y >= 0; --y)
//        for (y = 0; y < height; ++y)
        {
            for (x = 0; x < width; ++x)
            {
                for (cmptno = 0; cmptno < numcmpts; ++cmptno)
                {
                    /* The sample data is unsigned. */
                    int c;
                    if ((c = jas_stream_getc(in)) == EOF) {
                        return -1;
                    }
                    jas_matrix_set(data[cmptno], 0, x, c);
                }
            }
            for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
                if (jas_image_writecmpt(image, cmptno, 0, y, width, 1,
                  data[cmptno])) {
                    goto done;
                }
            }
        }

        jas_stream_flush(in);

        ret = 0;

    done:

        for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
            if (data[cmptno]) {
                jas_matrix_destroy(data[cmptno]);
            }
        }

        return ret;
    }

}

class ReaderWriterJP2 : public osgDB::ReaderWriter
{
    public:


        ReaderWriterJP2()
        {
            supportsExtension("jp2","Jpeg2000 image format");
            supportsExtension("jpc","Jpeg2000 image format");

            jas_init();

            // little dance here to get around warnings created by jas_image_strtofmt use of char* rather than const char*
            // as a parameted and modern compilers deprecating "jp2" string being treated as char*.
            char* jp2 = strdup("jp2");
            _fmt_jp2 = jas_image_strtofmt(jp2);
            free(jp2);
        }

        ~ReaderWriterJP2()
        {
            jas_cleanup();
        }

        virtual const char* className() const { return "JPEG 2000 Image Reader/Writer"; }

        virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options) const
        {
            return readImage(file,options);
        }

        virtual ReadResult readObject(std::istream& fin, const Options* options) const
        {
            return readImage(fin,options);
        }


        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = osgDB::getFileExtension(file);
            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;

            std::string fileName = osgDB::findDataFile( file, options );
            if(fileName.empty())
            {
                // note from Robert, Dec03, I find returning a valid image when no
                // file exists a bit odd...
                osg::Image *img = new osg::Image;
                img->setFileName(fileName);
                return img;
            }

            //jas_stream_t* in = jas_stream_fopen(fileName.c_str(), "rb");        // Does not support UTF8 under Windows
            FILE * fileHandle = osgDB::fopen(fileName.c_str(), "rb");
            if (!fileHandle) {
                return ReadResult::ERROR_IN_READING_FILE;
            }
            jas_stream_t* in = jas_stream_freopen(fileName.c_str(), "rb", fileHandle);        // Replacement for jas_stream_fopen() to be able to support UTF8
            if (!in) {
                fclose(fileHandle);
                return ReadResult::ERROR_IN_READING_FILE;
            }

            char* opt = 0;
            if(options)
            {
                opt = new char[options->getOptionString().size() + 1];
                strcpy(opt, options->getOptionString().c_str());
            }
            jas_image_t* jimage = jas_image_decode(in, -1, opt); // last is the option string whatto put there?
            if(opt) delete[] opt;

            int internalFormat = jimage->numcmpts_;

            int s = jas_image_width(jimage);
            int t = jas_image_height(jimage);
            int r = 1;

            unsigned char* data = new unsigned char[internalFormat*s*t];

            jas_stream_t* mem = jas_stream_memopen((char*)data, internalFormat*s*t);

            putdata(mem, jimage, internalFormat);

            jas_image_destroy(jimage);
            jas_stream_close(in);
            fclose(fileHandle);

            unsigned int pixelFormat =
                internalFormat == 1 ? GL_LUMINANCE :
                internalFormat == 2 ? GL_LUMINANCE_ALPHA :
                internalFormat == 3 ? GL_RGB :
                internalFormat == 4 ? GL_RGBA : (GLenum)-1;

            unsigned int dataType = GL_UNSIGNED_BYTE;

            Image* image = new Image();
            image->setFileName(fileName.c_str());
            image->setImage(s,t,r,
                internalFormat,
                pixelFormat,
                dataType,
                data,
//                osg::Image::USE_NEW_DELETE);
                osg::Image::NO_DELETE);

            OSG_INFO << "image read ok "<<s<<"  "<<t<< std::endl;
            return image;

        }

        virtual ReadResult readImage(std::istream& fin,const Options* options) const
        {
            char c;
            char * sdata;
            long ssize;
            std::vector<char> vdata;

            while(!fin.eof())
            {
                fin.read(&c, 1);
                vdata.push_back(c);
            }
            ssize = vdata.size();

            sdata = &vdata[0];

            jas_stream_t* in = jas_stream_memopen((char*)sdata, ssize);

            char* opt = 0;
            if(options && !options->getOptionString().empty())
            {
                opt = new char[options->getOptionString().size() + 1];
                strcpy(opt, options->getOptionString().c_str());
            }
            jas_image_t* jimage = jas_image_decode(in, -1, opt); // last is the option string whatto put there?
            if(opt) delete[] opt;
            
            if (!jimage) return ReadResult::FILE_NOT_HANDLED; 

            int internalFormat = jimage->numcmpts_;

            int s = jas_image_width(jimage);
            int t = jas_image_height(jimage);
            int r = 1;

            unsigned char* data = new unsigned char[internalFormat*s*t];

            jas_stream_t* mem = jas_stream_memopen((char*)data, internalFormat*s*t);

            putdata(mem, jimage, internalFormat);

            jas_image_destroy(jimage);
            jas_stream_close(in);

            unsigned int pixelFormat =
                internalFormat == 1 ? GL_LUMINANCE :
                internalFormat == 2 ? GL_LUMINANCE_ALPHA :
                internalFormat == 3 ? GL_RGB :
                internalFormat == 4 ? GL_RGBA : (GLenum)-1;

            unsigned int dataType = GL_UNSIGNED_BYTE;

            Image* image = new Image();
//            image->setFileName(fileName.c_str());
            image->setImage(s,t,r,
                internalFormat,
                pixelFormat,
                dataType,
                data,
//                osg::Image::USE_NEW_DELETE);
                osg::Image::NO_DELETE);

            OSG_INFO << "image read ok "<<s<<"  "<<t<< std::endl;
            return image;
        }

        virtual WriteResult writeObject(const osg::Object& object,const std::string& file, const osgDB::ReaderWriter::Options* options) const
        {
            const osg::Image* image = dynamic_cast<const osg::Image*>(&object);
            if (!image) return WriteResult::FILE_NOT_HANDLED;

            return writeImage(*image,file,options);
        }

        virtual WriteResult writeObject(const osg::Object& object,std::ostream& fout,const Options* options) const
        {
            const osg::Image* image = dynamic_cast<const osg::Image*>(&object);
            if (!image) return WriteResult::FILE_NOT_HANDLED;

            return writeImage(*image,fout,options);
        }

        virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options* options) const
        {
            std::string ext = osgDB::getFileExtension(fileName);
            if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;

            jas_image_cmptparm_t cmptparms[4];
            jas_image_cmptparm_t *cmptparm;

            int internalFormat = osg::Image::computeNumComponents(img.getPixelFormat());

            jas_stream_t* mem = jas_stream_memopen((char*)img.data(), internalFormat*img.s()*img.t());

            /* Create an image of the correct size. */
            jas_image_t* jimage;
            int i;
            for (i = 0, cmptparm = cmptparms; i < internalFormat; ++i, ++cmptparm) {
                cmptparm->tlx = 0;
                cmptparm->tly = 0;
                cmptparm->hstep = 1;
                cmptparm->vstep = 1;
                cmptparm->width = img.s();
                cmptparm->height = img.t();
                cmptparm->prec = 8;
                cmptparm->sgnd = 0;
            }
            if (!(jimage = jas_image_create(internalFormat, cmptparms, JAS_CLRSPC_UNKNOWN))) {
                return WriteResult::ERROR_IN_WRITING_FILE;
            }

            if(internalFormat == 1)
            {
                jas_image_setclrspc(jimage, JAS_CLRSPC_GENGRAY);
                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
            }
            else if(internalFormat == 2)
            {
                jas_image_setclrspc(jimage, JAS_CLRSPC_GENGRAY);
                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
            }
            else if(internalFormat == 3)
            {
                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
            }
            else if(internalFormat == 4)
            {
                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
                jas_image_setcmpttype(jimage, 3, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
            }

            getdata(mem, jimage);

            //jas_stream_t* out = jas_stream_fopen(fileName.c_str(), "wb");        // Does not support UTF8 under Windows
            FILE * fileHandle = osgDB::fopen(fileName.c_str(), "wb");
            if (!fileHandle) {
                return WriteResult::ERROR_IN_WRITING_FILE;
            }
            jas_stream_t* out = jas_stream_freopen(fileName.c_str(), "wb", fileHandle);        // Replacement for jas_stream_fopen() to be able to support UTF8
            if (!out) {
                fclose(fileHandle);
                return WriteResult::ERROR_IN_WRITING_FILE;
            }

            char* opt = 0;
            if(options)
            {
                opt = new char[options->getOptionString().size() + 1];
                strcpy(opt, options->getOptionString().c_str());
            }
            jas_image_encode(jimage, out, _fmt_jp2,  opt);
            if(opt) delete[] opt;

            jas_stream_flush(out);

            jas_stream_close(out);
            jas_image_destroy(jimage);
            fclose(fileHandle);

            return WriteResult::FILE_SAVED;
        }

        WriteResult writeImage(const osg::Image& img, std::ostream& fout, const Options* options) const
        {
            jas_image_cmptparm_t cmptparms[4];
            jas_image_cmptparm_t *cmptparm;

            int internalFormat = osg::Image::computeNumComponents(img.getPixelFormat());

            jas_stream_t* mem = jas_stream_memopen((char*)img.data(), internalFormat*img.s()*img.t());

            /* Create an image of the correct size. */
            jas_image_t* jimage;
            int i;
            for (i = 0, cmptparm = cmptparms; i < internalFormat; ++i, ++cmptparm) {
                cmptparm->tlx = 0;
                cmptparm->tly = 0;
                cmptparm->hstep = 1;
                cmptparm->vstep = 1;
                cmptparm->width = img.s();
                cmptparm->height = img.t();
                cmptparm->prec = 8;
                cmptparm->sgnd = 0;
            }
            if (!(jimage = jas_image_create(internalFormat, cmptparms, JAS_CLRSPC_UNKNOWN))) {
                return WriteResult::ERROR_IN_WRITING_FILE;
            }

            if(internalFormat == 1)
            {
                jas_image_setclrspc(jimage, JAS_CLRSPC_SGRAY);
                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
            }
            else if(internalFormat == 2)
            {
                jas_image_setclrspc(jimage, JAS_CLRSPC_SGRAY);
                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
            }
            else if(internalFormat == 3)
            {
                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
            }
            else if(internalFormat == 4)
            {
                jas_image_setclrspc(jimage, JAS_CLRSPC_SRGB);
                jas_image_setcmpttype(jimage, 0, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
                jas_image_setcmpttype(jimage, 1, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
                jas_image_setcmpttype(jimage, 2, JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
                jas_image_setcmpttype(jimage, 3, JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY));
            }

            getdata(mem, jimage);

            jas_stream_t* out = jas_stream_memopen(0, 0);
//            jas_stream_t* out = jas_stream_fopen(fileName.c_str(), "wb");        // Does not support UTF8 under Windows
            if (!out) 
                return WriteResult::ERROR_IN_WRITING_FILE;

            char* opt = 0;
            if(options)
            {
                opt = new char[options->getOptionString().size() + 1];
                strcpy(opt, options->getOptionString().c_str());
            }

            jas_image_encode(jimage, out, _fmt_jp2,  opt);
            if(opt) delete[] opt;

            jas_stream_flush(out);

            // 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
            jas_stream_memobj_t* obj = (jas_stream_memobj_t*) out->obj_;

            fout.write((char*)obj->buf_, obj->len_);

            fout << std::flush;

            jas_stream_close(out);

            jas_image_destroy(jimage);

            return WriteResult::FILE_SAVED;
        }


        int _fmt_jp2;
};

// now register with Registry to instantiate the above
// reader/writer.
REGISTER_OSGPLUGIN(jp2, ReaderWriterJP2)
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to