From 6d66e1abaa3af6ffde94d44942555ac91d990a64 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 24 Jan 2012 14:34:02 +0000 Subject: [PATCH] Added support for using GL_UNPACK_ROW_LENGTH in conjunction with texture's + osg::Image via new RowLength parameter in osg::Image. To support this Image::setData(..) now has a new optional rowLength parameter which defaults to 0, which provides the original behaviour, Image::setRowLength(int) and int Image::getRowLength() are also provided. With the introduction of RowLength support in osg::Image it is now possible to create a sub image where the t size of the image are smaller than the row length, useful for when you have a large image on the CPU and which to use a small portion of it on the GPU. However, when these sub images are created the data within the image is no longer contiguous so data access can no longer assume that all the data is in one block. The new method Image::isDataContiguous() enables the user to check whether the data is contiguous, and if not one can either access the data row by row using Image::data(column,row,image) accessor, or use the new Image::DataIterator for stepping through each block on memory assocatied with the image. To support the possibility of non contiguous osg::Image usage of image objects has had to be updated to check DataContiguous and handle the case or use access via the DataIerator or by row by row. To achieve this a relatively large number of files has had to be modified, in particular the texture classes and image plugins that doing writing. --- examples/osgphotoalbum/PhotoArchive.cpp | 2 + .../osgscreencapture/osgscreencapture.cpp | 1 + examples/osgtexture2D/osgtexture2D.cpp | 43 +++ include/osg/Array | 4 + include/osg/BufferObject | 9 + include/osg/Image | 74 +++- include/osg/PrimitiveSet | 4 + src/osg/BufferObject.cpp | 16 +- src/osg/DrawPixels.cpp | 3 + src/osg/Image.cpp | 335 ++++++++++++++---- src/osg/Texture.cpp | 12 + src/osg/Texture1D.cpp | 1 + src/osg/Texture2DArray.cpp | 1 + src/osg/Texture3D.cpp | 1 + src/osg/TextureRectangle.cpp | 7 +- src/osgDB/OutputStream.cpp | 30 +- .../Inventor/ConvertFromInventor.cpp | 13 +- src/osgPlugins/Inventor/ReaderWriterIV.cpp | 4 +- src/osgPlugins/bmp/ReaderWriterBMP.cpp | 2 +- src/osgPlugins/dds/ReaderWriterDDS.cpp | 10 +- src/osgPlugins/exr/ReaderWriterEXR.cpp | 2 +- src/osgPlugins/hdr/hdrwriter.cpp | 45 +-- src/osgPlugins/hdr/hdrwriter.h | 3 +- .../imageio/ReaderWriterImageIO.cpp | 17 + src/osgPlugins/ive/Image.cpp | 5 +- src/osgPlugins/jp2/ReaderWriterJP2.cpp | 12 + src/osgPlugins/jpeg/ReaderWriterJPEG.cpp | 6 + src/osgPlugins/logo/ReaderWriterLOGO.cpp | 2 + src/osgPlugins/nvtt/NVTTImageProcessor.cpp | 45 ++- src/osgPlugins/pov/ReaderWriterPOV.cpp | 3 +- src/osgPlugins/rgb/ReaderWriterRGB.cpp | 22 ++ src/osgPlugins/tga/ReaderWriterTGA.cpp | 6 +- src/osgPlugins/xine/ReaderWriterXine.cpp | 20 +- src/osgText/Glyph.cpp | 1 + 34 files changed, 593 insertions(+), 168 deletions(-) diff --git a/examples/osgphotoalbum/PhotoArchive.cpp b/examples/osgphotoalbum/PhotoArchive.cpp index 1cf750ee7..76db14477 100644 --- a/examples/osgphotoalbum/PhotoArchive.cpp +++ b/examples/osgphotoalbum/PhotoArchive.cpp @@ -222,6 +222,7 @@ void PhotoArchive::buildArchive(const std::string& filename, const FileNameList& osg::PixelStorageModes psm; psm.pack_alignment = image->getPacking(); + psm.pack_row_length = image->getRowLength(); psm.unpack_alignment = image->getPacking(); GLint status = osg::gluScaleImage(&psm, image->getPixelFormat(), @@ -289,6 +290,7 @@ void PhotoArchive::buildArchive(const std::string& filename, const FileNameList& osg::PixelStorageModes psm; psm.pack_alignment = image->getPacking(); + psm.pack_row_length = image->getRowLength(); psm.unpack_alignment = image->getPacking(); GLint status = osg::gluScaleImage(&psm, image->getPixelFormat(), diff --git a/examples/osgscreencapture/osgscreencapture.cpp b/examples/osgscreencapture/osgscreencapture.cpp index c899d7faf..9de19b634 100644 --- a/examples/osgscreencapture/osgscreencapture.cpp +++ b/examples/osgscreencapture/osgscreencapture.cpp @@ -384,6 +384,7 @@ void WindowCaptureCallback::ContextData::singlePBO(osg::GLBufferObject::Extensio if(src) { memcpy(image->data(), src, image->getTotalSizeInBytes()); + ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); } diff --git a/examples/osgtexture2D/osgtexture2D.cpp b/examples/osgtexture2D/osgtexture2D.cpp index b0329f01d..15cdc8ad2 100644 --- a/examples/osgtexture2D/osgtexture2D.cpp +++ b/examples/osgtexture2D/osgtexture2D.cpp @@ -536,8 +536,50 @@ public: _prevTime(0.0) { +#if 1 + osg::ref_ptr originalImage = osgDB::readImageFile("Images/dog_left_eye.jpg"); + + osg::ref_ptr subImage = new osg::Image; + subImage->setUserData(originalImage.get()); // attach the originalImage as user data to prevent it being deleted. + + // now assign the appropriate portion data from the originalImage + subImage->setImage(originalImage->s()/2, originalImage->t()/2, originalImage->r(), // half the width and height + originalImage->getInternalTextureFormat(), // same internal texture format + originalImage->getPixelFormat(),originalImage->getDataType(), // same pixel foramt and data type + originalImage->data(originalImage->s()/4,originalImage->t()/4), // offset teh start point to 1/4 into the image + osg::Image::NO_DELETE, // don't attempt to delete the image data, leave this to the originalImage + originalImage->getPacking(), // use the the same packing + originalImage->s()); // use the width of the original image as the row width + + + subImage->setPixelBufferObject(new osg::PixelBufferObject(subImage.get())); + +#if 0 + OSG_NOTICE<<"orignalImage iterator"<s()<<", "<t()<(itr.data()); d<(itr.data()+itr.size()); ++d) + { + *d = 255-*d; + } + } +#endif + + _imageList.push_back(subImage.get()); + +#else _imageList.push_back(osgDB::readImageFile("Images/dog_left_eye.jpg")); +#endif _textList.push_back("Subloaded Image 1 - dog_left_eye.jpg"); _imageList.push_back(osgDB::readImageFile("Images/dog_right_eye.jpg")); @@ -584,6 +626,7 @@ public: protected: + typedef std::vector< osg::ref_ptr > ImageList; typedef std::vector TextList; diff --git a/include/osg/Array b/include/osg/Array index 19d7396c0..47266df35 100644 --- a/include/osg/Array +++ b/include/osg/Array @@ -104,6 +104,10 @@ class OSG_EXPORT Array : public BufferData Type getType() const { return _arrayType; } GLint getDataSize() const { return _dataSize; } GLenum getDataType() const { return _dataType; } + + virtual osg::Array* asArray() { return this; } + virtual const osg::Array* asArray() const { return this; } + virtual const GLvoid* getDataPointer() const = 0; virtual unsigned int getTotalDataSize() const = 0; virtual unsigned int getNumElements() const = 0; diff --git a/include/osg/BufferObject b/include/osg/BufferObject index 00dc421dc..4b9d5f3c6 100644 --- a/include/osg/BufferObject +++ b/include/osg/BufferObject @@ -620,6 +620,15 @@ class OSG_EXPORT BufferData : public Object virtual const GLvoid* getDataPointer() const = 0; virtual unsigned int getTotalDataSize() const = 0; + virtual osg::Array* asArray() { return 0; } + virtual const osg::Array* asArray() const { return 0; } + + virtual osg::PrimitiveSet* asPrimitiveSet() { return 0; } + virtual const osg::PrimitiveSet* asPrimitiveSet() const { return 0; } + + virtual osg::Image* asImage() { return 0; } + virtual const osg::Image* asImage() const { return 0; } + void setBufferObject(BufferObject* bufferObject); BufferObject* getBufferObject() { return _bufferObject.get(); } const BufferObject* getBufferObject() const { return _bufferObject.get(); } diff --git a/include/osg/Image b/include/osg/Image index 95f9351b7..7c0083f80 100644 --- a/include/osg/Image +++ b/include/osg/Image @@ -114,6 +114,9 @@ class OSG_EXPORT Image : public BufferData virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "Image"; } + virtual osg::Image* asImage() { return this; } + virtual const osg::Image* asImage() const { return this; } + virtual const GLvoid* getDataPointer() const { return data(); } virtual unsigned int getTotalDataSize() const { return getTotalSizeInBytesIncludingMipmaps(); } @@ -157,7 +160,7 @@ class OSG_EXPORT Image : public BufferData GLenum pixelFormat,GLenum type, unsigned char* data, AllocationMode mode, - int packing=1); + int packing=1, int rowLength=0); /** Read pixels from current frame buffer at specified position and size, using glReadPixels. * Create memory for storage if required, reuse existing pixel coords if possible. @@ -213,6 +216,9 @@ class OSG_EXPORT Image : public BufferData /** Depth of image. */ inline int r() const { return _r; } + + void setRowLength(int length) { _rowLength = length; } + inline int getRowLength() const { return _rowLength; } void setInternalTextureFormat(GLint internalFormat); inline GLint getInternalTextureFormat() const { return _internalTextureFormat; } @@ -241,9 +247,17 @@ class OSG_EXPORT Image : public BufferData /** Return the number of bytes each row of pixels occupies once it has been packed. */ inline unsigned int getRowSizeInBytes() const { return computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing); } + /** Return the number of bytes between each successive row. + * Note, getRowSizeInBytes() will only equal getRowStepInBytes() when isDataContiguous() return true. */ + inline unsigned int getRowStepInBytes() const { return computeRowWidthInBytes(_rowLength==0?_s:_rowLength,_pixelFormat,_dataType,_packing); } + /** Return the number of bytes each image (_s*_t) of pixels occupies. */ inline unsigned int getImageSizeInBytes() const { return getRowSizeInBytes()*_t; } + /** Return the number of bytes between each successive image. + * Note, getImageSizeInBytes() will only equal getImageStepInBytes() when isDataContiguous() return true. */ + inline unsigned int getImageStepInBytes() const { return getRowStepInBytes()*_t; } + /** Return the number of bytes the whole row/image/volume of pixels occupies. */ inline unsigned int getTotalSizeInBytes() const { return getImageSizeInBytes()*_r; } @@ -253,25 +267,64 @@ class OSG_EXPORT Image : public BufferData /** Return true if the Image represent a valid and usable imagery.*/ bool valid() const { return _s!=0 && _t!=0 && _r!=0 && _data!=0 && _dataType!=0; } - /** Raw image data. */ + /** Raw image data. + * Note, data in successive rows may not be contiguous, isDataContiguous() return false then you should + * take care to access the data per row rather than treating the whole data as a single block. */ inline unsigned char* data() { return _data; } - /** Raw const image data. */ + /** Raw const image data. + * Note, data in successive rows may not be contiguous, isDataContiguous() return false then you should + * take care to access the data per row rather than treating the whole data as a single block. */ inline const unsigned char* data() const { return _data; } - inline unsigned char* data(int column, int row=0,int image=0) { if (!_data) return NULL; - return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes(); + return _data+(column*getPixelSizeInBits())/8+row*getRowStepInBytes()+image*getImageSizeInBytes(); } inline const unsigned char* data(int column, int row=0,int image=0) const { if (!_data) return NULL; - return _data+(column*getPixelSizeInBits())/8+row*getRowSizeInBytes()+image*getImageSizeInBytes(); + return _data+(column*getPixelSizeInBits())/8+row*getRowStepInBytes()+image*getImageSizeInBytes(); } + /** return true if the data stored in the image is a contiguous block of data.*/ + bool isDataContiguous() const { return _rowLength==0 || _rowLength==_s; } + + /** Convenience class for assisting the copying of image data when the image data isn't contiguous.*/ + class OSG_EXPORT DataIterator + { + public: + DataIterator(const Image* image); + DataIterator(const DataIterator& ri); + ~DataIterator() {} + + /** advance iterator to next block of data.*/ + void operator ++ (); + + /** is iterator valid.*/ + bool valid() const { return _currentPtr!=0; } + + /** data pointer of current block to copy.*/ + const unsigned char* data() const { return _currentPtr; } + + /** Size of current block to copy.*/ + unsigned int size() const { return _currentSize; } + + protected: + + + void assign(); + + const osg::Image* _image; + int _rowNum; + int _imageNum; + unsigned int _mipmapNum; + const unsigned char* _currentPtr; + unsigned int _currentSize; + }; + /** Get the color value for specified texcoord.*/ Vec4 getColor(unsigned int s,unsigned t=0,unsigned r=0) const; @@ -301,9 +354,11 @@ class OSG_EXPORT Image : public BufferData static bool isPackedType(GLenum type); static GLenum computePixelFormat(GLenum pixelFormat); static GLenum computeFormatDataType(GLenum pixelFormat); + static unsigned int computeBlockSize(GLenum pixelFormat, GLenum packing); static unsigned int computeNumComponents(GLenum pixelFormat); static unsigned int computePixelSizeInBits(GLenum pixelFormat,GLenum type); static unsigned int computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing); + static unsigned int computeImageSizeInBytes(int width,int height, int depth, GLenum pixelFormat,GLenum type,int packing); static int computeNearestPowerOfTwo(int s,float bias=0.5f); static int computeNumberOfMipmapLevels(int s,int t = 1, int r = 1); @@ -341,12 +396,6 @@ class OSG_EXPORT Image : public BufferData return _data+getMipmapOffset(mipmapLevel); } - /*inline const unsigned char* getMipmapData(unsigned int row, unsigned int column, unsigned int mipmapLevel) const - { - if (!_data) return NULL; - return getMipmapData(mipmapLevel) + (column*getPixelSizeInBits())/8+row*getRowSizeInBytes(); - }*/ - /** Return true if this image is translucent - i.e. it has alpha values that are less 1.0 (when normalized). */ virtual bool isImageTranslucent() const; @@ -399,6 +448,7 @@ class OSG_EXPORT Image : public BufferData Origin _origin; int _s, _t, _r; + int _rowLength; GLint _internalTextureFormat; GLenum _pixelFormat; GLenum _dataType; diff --git a/include/osg/PrimitiveSet b/include/osg/PrimitiveSet index 294725ba1..3cd4a11c3 100644 --- a/include/osg/PrimitiveSet +++ b/include/osg/PrimitiveSet @@ -197,6 +197,10 @@ class OSG_EXPORT PrimitiveSet : public BufferData virtual const char* className() const { return "PrimitiveSet"; } Type getType() const { return _primitiveType; } + + virtual osg::PrimitiveSet* asPrimitiveSet() { return this; } + virtual const osg::PrimitiveSet* asPrimitiveSet() const { return this; } + virtual const GLvoid* getDataPointer() const { return 0; } virtual unsigned int getTotalDataSize() const { return 0; } virtual bool supportsBufferObject() const { return false; } diff --git a/src/osg/BufferObject.cpp b/src/osg/BufferObject.cpp index c51079c67..9d2389e94 100644 --- a/src/osg/BufferObject.cpp +++ b/src/osg/BufferObject.cpp @@ -204,7 +204,21 @@ void GLBufferObject::compileBuffer() // OSG_NOTICE<<"GLBufferObject::compileBuffer(..) downloading BufferEntry "<<&entry<getModifiedCount(); - _extensions->glBufferSubData(_profile._target, (GLintptrARB)entry.offset, (GLsizeiptrARB)entry.dataSize, entry.dataSource->getDataPointer()); + const osg::Image* image = entry.dataSource->asImage(); + if (image && !(image->isDataContiguous())) + { + unsigned int offset = entry.offset; + for(osg::Image::DataIterator img_itr(image); img_itr.valid(); ++img_itr) + { + //OSG_NOTICE<<"Copying to buffer object using DataIterator, offset="<isDataContiguous()) + { + _currentPtr = _image->data(); + _currentSize = _image->getTotalSizeInBytesIncludingMipmaps(); + + //OSG_NOTICE<<" _currentPtr="<<(void*)_currentPtr<isMipmap()) + { + //OSG_NOTICE<<"DataIterator::assign D"<=_image->getNumMipmapLevels()) + { + _currentPtr = 0; + _currentSize = 0; + return; + } + const unsigned char* ptr = _image->getMipmapData(_mipmapNum); + + int rowLength = _image->getRowLength()>>_mipmapNum; + if (rowLength==0) rowLength = 1; + + int imageHeight = _image->t()>>_mipmapNum; + if (imageHeight==0) imageHeight = 1; + + unsigned int rowWidthInBytes = Image::computeRowWidthInBytes(rowLength,_image->getPixelFormat(),_image->getDataType(),_image->getPacking()); + unsigned int imageSizeInBytes = rowWidthInBytes*imageHeight; + + _currentPtr = ptr + rowWidthInBytes*_rowNum + imageSizeInBytes*_imageNum; + _currentSize = rowWidthInBytes; + } + else + { + //OSG_NOTICE<<"DataIterator::assign E"<=_image->r() || _rowNum>=_image->t()) + { + _currentPtr = 0; + _currentSize = 0; + return; + } + + //OSG_NOTICE<<"DataIterator::assign F"<data(0, _rowNum, _imageNum); + _currentSize = _image->getRowSizeInBytes(); + return; + } +} + + Image::Image() :BufferData(), _fileName(""), _writeHint(NO_PREFERENCE), _origin(BOTTOM_LEFT), _s(0), _t(0), _r(0), + _rowLength(0), _internalTextureFormat(0), _pixelFormat(0), _dataType(0), @@ -71,6 +223,7 @@ Image::Image(const Image& image,const CopyOp& copyop): _writeHint(image._writeHint), _origin(image._origin), _s(image._s), _t(image._t), _r(image._r), + _rowLength(0), _internalTextureFormat(image._internalTextureFormat), _pixelFormat(image._pixelFormat), _dataType(image._dataType), @@ -84,7 +237,12 @@ Image::Image(const Image& image,const CopyOp& copyop): { int size = image.getTotalSizeInBytesIncludingMipmaps(); setData(new unsigned char [size],USE_NEW_DELETE); - memcpy(_data,image._data,size); + unsigned char* dest_ptr = _data; + for(DataIterator itr(&image); itr.valid(); ++itr) + { + memcpy(dest_ptr, itr.data(), itr.size()); + dest_ptr += itr.size(); + } } } @@ -510,6 +668,34 @@ unsigned int Image::computePixelSizeInBits(GLenum format,GLenum type) } +unsigned int Image::computeBlockSize(GLenum pixelFormat, GLenum packing) +{ + switch(pixelFormat) + { + case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): + case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): + return osg::maximum(8u,packing); // block size of 8 + case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): + case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): + case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG): + case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG): + case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG): + case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG): + case(GL_ETC1_RGB8_OES): + return osg::maximum(16u,packing); // block size of 16 + case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT): + case(GL_COMPRESSED_RED_RGTC1_EXT): + return osg::maximum(8u,packing); // block size of 8 + break; + case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): + case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT): + return osg::maximum(16u,packing); // block size of 16 + default: + break; + } + return packing; +} + unsigned int Image::computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum type,int packing) { unsigned int pixelSize = computePixelSizeInBits(pixelFormat,type); @@ -519,6 +705,16 @@ unsigned int Image::computeRowWidthInBytes(int width,GLenum pixelFormat,GLenum t return (widthInBits/packingInBits + ((widthInBits%packingInBits)?1:0))*packing; } +unsigned int Image::computeImageSizeInBytes(int width,int height, int depth, GLenum pixelFormat,GLenum type,int packing) +{ + if (width==0 || height==0 || depth==0) return 0; + + return osg::maximum( + Image::computeRowWidthInBytes(width,pixelFormat,type,packing)*height*depth, + computeBlockSize(pixelFormat, packing) + ); +} + int Image::computeNearestPowerOfTwo(int s,float bias) { if ((s & (s-1))!=0) @@ -581,51 +777,21 @@ unsigned int Image::getTotalSizeInBytesIncludingMipmaps() const int s = _s; int t = _t; int r = _r; - - unsigned int maxValue = 0; - for(unsigned int i=0;i<_mipmapData.size() && _mipmapData[i];++i) + unsigned int totalSize = 0; + for(unsigned int i=0;i<_mipmapData.size()+1;++i) { + totalSize += computeImageSizeInBytes(s, t, r, _pixelFormat, _dataType, _packing); + s >>= 1; t >>= 1; r >>= 1; - maxValue = maximum(maxValue,_mipmapData[i]); - } - - if (s==0) s=1; - if (t==0) t=1; - if (r==0) r=1; - - unsigned int sizeOfLastMipMap = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing)* r*t; - switch(_pixelFormat) - { - case(GL_COMPRESSED_RGB_S3TC_DXT1_EXT): - case(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): - sizeOfLastMipMap = maximum(sizeOfLastMipMap, 8u); // block size of 8 - break; - case(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): - case(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): - case(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG): - case(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG): - case(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG): - case(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG): - case(GL_ETC1_RGB8_OES): - sizeOfLastMipMap = maximum(sizeOfLastMipMap, 16u); // block size of 16 - break; - case(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT): - case(GL_COMPRESSED_RED_RGTC1_EXT): - sizeOfLastMipMap = maximum(sizeOfLastMipMap, 8u); // block size of 8 - break; - case(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): - case(GL_COMPRESSED_RED_GREEN_RGTC2_EXT): - sizeOfLastMipMap = maximum(sizeOfLastMipMap, 16u); // block size of 8 - break; - default: break; + + if (s<1) s=1; + if (t<1) t=1; + if (r<1) r=1; } - // OSG_INFO<<"sizeOfLastMipMap="<glGetCompressedTexImage(textureMode, i, getMipmapData(i)); @@ -886,6 +1061,8 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalformat); glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing); glPixelStorei(GL_PACK_ALIGNMENT, packing); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowLength); + glPixelStorei(GL_PACK_ROW_LENGTH, rowLength); unsigned int total_size = 0; GLint i; @@ -927,6 +1104,7 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps _mipmapData = mipMapData; _allocationMode=USE_NEW_DELETE; _packing = packing; + _rowLength = rowLength; for(i=0;igetPacking(); + psm.unpack_row_length = source->getRowLength(); GLint status = gluScaleImage(&psm, _pixelFormat, source->s(), @@ -1047,8 +1228,6 @@ void Image::copySubImage(int s_offset, int t_offset, int r_offset, const osg::Im _dataType, data_destination); - glPixelStorei(GL_PACK_ROW_LENGTH,0); - if (status!=0) { OSG_WARN << "Error Image::scaleImage() did not succeed : errorString = "<< gluErrorString((GLenum)status) << ". The rendering context may be invalid." << std::endl; @@ -1067,12 +1246,14 @@ void Image::flipHorizontal() if (_mipmapData.empty()) { - + unsigned int rowStepInBytes = getRowStepInBytes(); + unsigned int imageStepInBytes = getImageStepInBytes(); + for(int r=0;r<_r;++r) { for (int t=0; t<_t; ++t) { - unsigned char* rowData = _data+t*getRowSizeInBytes()+r*getImageSizeInBytes(); + unsigned char* rowData = _data + t*rowStepInBytes + r*imageStepInBytes; unsigned char* left = rowData ; unsigned char* right = rowData + ((_s-1)*getPixelSizeInBits())/8; @@ -1097,17 +1278,20 @@ void Image::flipHorizontal() dirty(); } -void flipImageVertical(unsigned char* top, unsigned char* bottom, unsigned int rowSize) +void flipImageVertical(unsigned char* top, unsigned char* bottom, unsigned int rowSize, unsigned int rowStep) { while(topsetMode(GL_LIGHTING,osg::StateAttribute::OFF); dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); - // set up the geoset. + // set up the geoset. unsigned int rowSize = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing); + Geometry* geom = new Geometry; geom->setStateSet(dstate); diff --git a/src/osg/Texture.cpp b/src/osg/Texture.cpp index dd7ffdc89..83affc2be 100644 --- a/src/osg/Texture.cpp +++ b/src/osg/Texture.cpp @@ -1842,6 +1842,7 @@ void Texture::applyTexImage2D_load(State& state, GLenum target, const Image* ima } glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking()); + unsigned int rowLength = image->getRowLength(); bool useClientStorage = extensions->isClientStorageSupported() && getClientStorageHint(); if (useClientStorage) @@ -1891,6 +1892,7 @@ void Texture::applyTexImage2D_load(State& state, GLenum target, const Image* ima PixelStorageModes psm; psm.pack_alignment = image->getPacking(); + psm.pack_row_length = image->getRowLength(); psm.unpack_alignment = image->getPacking(); // rescale the image to the correct size. @@ -1899,6 +1901,7 @@ void Texture::applyTexImage2D_load(State& state, GLenum target, const Image* ima inwidth,inheight,image->getDataType(), dataPtr); + rowLength = 0; } bool mipmappingRequired = _min_filter != LINEAR && _min_filter != NEAREST; @@ -1910,6 +1913,7 @@ void Texture::applyTexImage2D_load(State& state, GLenum target, const Image* ima { state.bindPixelBufferObject(pbo); dataPtr = reinterpret_cast(pbo->getOffset(image->getBufferIndex())); + rowLength = 0; #ifdef DO_TIMING OSG_NOTICE<<"after PBO "<delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<getPixelFormat()); glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking()); + unsigned int rowLength = image->getRowLength(); unsigned char* dataPtr = (unsigned char*)image->data(); @@ -2147,6 +2154,8 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image* image->s(),image->t(),image->getDataType(),image->data(), inwidth,inheight,image->getDataType(), dataPtr); + + rowLength = 0; } @@ -2159,6 +2168,7 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image* { state.bindPixelBufferObject(pbo); dataPtr = reinterpret_cast(pbo->getOffset(image->getBufferIndex())); + rowLength = 0; #ifdef DO_TIMING OSG_NOTICE<<"after PBO "<delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<getPacking()); + glPixelStorei(GL_UNPACK_ROW_LENGTH,image->getRowLength()); static MyCompressedTexImage1DArbProc glCompressedTexImage1D_ptr = convertPointerType(getGLExtensionFuncPtr("glCompressedTexImage1DARB")); diff --git a/src/osg/Texture2DArray.cpp b/src/osg/Texture2DArray.cpp index ec77b6009..ef345317d 100644 --- a/src/osg/Texture2DArray.cpp +++ b/src/osg/Texture2DArray.cpp @@ -455,6 +455,7 @@ void Texture2DArray::applyTexImage2DArray_subload(State& state, Image* image, GL } glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking()); + glPixelStorei(GL_UNPACK_ROW_LENGTH,image->getRowLength()); bool useHardwareMipmapGeneration = !image->isMipmap() && _useHardwareMipMapGeneration && texExtensions->isGenerateMipMapSupported(); diff --git a/src/osg/Texture3D.cpp b/src/osg/Texture3D.cpp index 84e46cfa7..5e6121452 100644 --- a/src/osg/Texture3D.cpp +++ b/src/osg/Texture3D.cpp @@ -380,6 +380,7 @@ void Texture3D::applyTexImage3D(GLenum target, Image* image, State& state, GLsiz image->ensureValidSizeForTexturing(extensions->maxTexture3DSize()); glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking()); + glPixelStorei(GL_UNPACK_ROW_LENGTH,image->getRowLength()); bool useHardwareMipMapGeneration = !image->isMipmap() && _useHardwareMipMapGeneration && texExtensions->isGenerateMipMapSupported(); diff --git a/src/osg/TextureRectangle.cpp b/src/osg/TextureRectangle.cpp index 5c7ed1065..5df5a88e0 100644 --- a/src/osg/TextureRectangle.cpp +++ b/src/osg/TextureRectangle.cpp @@ -312,6 +312,7 @@ void TextureRectangle::applyTexImage_load(GLenum target, Image* image, State& st computeInternalFormat(); glPixelStorei(GL_UNPACK_ALIGNMENT, image->getPacking()); + glPixelStorei(GL_UNPACK_ROW_LENGTH,image->getRowLength()); bool useClientStorage = extensions->isClientStorageSupported() && getClientStorageHint(); if (useClientStorage) @@ -392,6 +393,8 @@ void TextureRectangle::applyTexImage_subload(GLenum target, Image* image, State& computeInternalFormat(); glPixelStorei(GL_UNPACK_ALIGNMENT, image->getPacking()); + unsigned int rowLength = image->getRowLength(); + #ifdef DO_TIMING osg::Timer_t start_tick = osg::Timer::instance()->tick(); @@ -403,11 +406,13 @@ void TextureRectangle::applyTexImage_subload(GLenum target, Image* image, State& { state.bindPixelBufferObject(pbo); dataPtr = reinterpret_cast(pbo->getOffset(image->getBufferIndex())); + rowLength = 0; #ifdef DO_TIMING OSG_NOTICE<<"after PBO "<delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<isCompressedTexSubImage2DSupported()) { diff --git a/src/osgDB/OutputStream.cpp b/src/osgDB/OutputStream.cpp index f51f6e5f1..e72dada23 100644 --- a/src/osgDB/OutputStream.cpp +++ b/src/osgDB/OutputStream.cpp @@ -369,15 +369,33 @@ void OutputStream::writeImage( const osg::Image* img ) // _data unsigned int size = img->getTotalSizeInBytesIncludingMipmaps(); - writeSize(size); writeCharArray( (char*)img->data(), size ); + writeSize(size); + + for(osg::Image::DataIterator img_itr(img); img_itr.valid(); ++img_itr) + { + writeCharArray( (char*)img_itr.data(), img_itr.size() ); + } // _mipmapData - const osg::Image::MipmapDataType& levels = img->getMipmapLevels(); - writeSize(levels.size()); - for ( osg::Image::MipmapDataType::const_iterator itr=levels.begin(); - itr!=levels.end(); ++itr ) + unsigned int numMipmaps = img->getNumMipmapLevels()-1; + writeSize(numMipmaps); + int s = img->s(); + int t = img->t(); + int r = img->r(); + unsigned int offset = 0; + for (unsigned int i=0; igetPixelFormat(),img->getDataType(),img->getPacking()); + offset += size; + + *this << offset; + + s >>= 1; + t >>= 1; + r >>= 1; + if (s<1) s=1; + if (t<1) t=1; + if (r<1) r=1; } } break; diff --git a/src/osgPlugins/Inventor/ConvertFromInventor.cpp b/src/osgPlugins/Inventor/ConvertFromInventor.cpp index b98d0d12a..ec7ca7e53 100644 --- a/src/osgPlugins/Inventor/ConvertFromInventor.cpp +++ b/src/osgPlugins/Inventor/ConvertFromInventor.cpp @@ -1093,12 +1093,21 @@ static osgDB::ReaderWriter::Options* createOptions() static osg::Image* loadImage(const char *fileName, osgDB::ReaderWriter::Options *options) { - osg::Image *osgImage = osgDB::readImageFile(fileName, options); + osg::ref_ptr osgImage = osgDB::readImageFile(fileName, options); if (!osgImage) + { OSG_WARN << NOTIFY_HEADER << "Could not read texture file '" << fileName << "'."; + return 0; + } - return osgImage; + if (!osgImage->isDataContiguous()) + { + OSG_WARN << NOTIFY_HEADER << "Inventor cannot handle non contiguous image data found in texture file '" << fileName << "'."; + return 0; + } + + return osgImage.release(); } SbBool SoTexture2Osg::readInstance(SoInput *in, unsigned short flags) diff --git a/src/osgPlugins/Inventor/ReaderWriterIV.cpp b/src/osgPlugins/Inventor/ReaderWriterIV.cpp index a2cf4459d..301b5781b 100644 --- a/src/osgPlugins/Inventor/ReaderWriterIV.cpp +++ b/src/osgPlugins/Inventor/ReaderWriterIV.cpp @@ -142,7 +142,7 @@ ReaderWriterIV::readNodeFromSoInput(SoInput &input, if (fileName.length()) { OSG_NOTICE << "osgDB::ReaderWriterIV::readNode() " - << "File " << fileName.data() + << "File " << fileName << " loaded successfully." << std::endl; } else @@ -154,7 +154,7 @@ ReaderWriterIV::readNodeFromSoInput(SoInput &input, if (fileName.length()) { OSG_WARN << "osgDB::ReaderWriterIV::readNode() " - << "Failed to load file " << fileName.data() + << "Failed to load file " << fileName << "." << std::endl; } else diff --git a/src/osgPlugins/bmp/ReaderWriterBMP.cpp b/src/osgPlugins/bmp/ReaderWriterBMP.cpp index 934d57c12..b89ea3a77 100644 --- a/src/osgPlugins/bmp/ReaderWriterBMP.cpp +++ b/src/osgPlugins/bmp/ReaderWriterBMP.cpp @@ -527,7 +527,7 @@ static bool bmp_save(const osg::Image& img, std::ostream& fout) std::vector rowBuffer(bytesPerRowAlign); for (int y = 0; y < img.t(); ++y) { - const unsigned char* imgp = img.data() + img.s() * y * channelsPerPixel; + const unsigned char* imgp = img.data(0, y); for (int x = 0; x < img.s(); ++x) { // RGB -> BGR diff --git a/src/osgPlugins/dds/ReaderWriterDDS.cpp b/src/osgPlugins/dds/ReaderWriterDDS.cpp index 5a459eb20..30d00f746 100644 --- a/src/osgPlugins/dds/ReaderWriterDDS.cpp +++ b/src/osgPlugins/dds/ReaderWriterDDS.cpp @@ -878,8 +878,6 @@ bool WriteDDSFile(const osg::Image *img, std::ostream& fout) return false; } - int size = img->getTotalSizeInBytes(); - // set even more flags if( !img->isMipmap() ) { @@ -896,8 +894,6 @@ bool WriteDDSFile(const osg::Image *img, std::ostream& fout) ddsd.dwMipMapCount = img->getNumMipmapLevels(); - size = img->getTotalSizeInBytesIncludingMipmaps(); - OSG_INFO<<"writing out with mipmaps ddsd.dwMipMapCount"<(&ddsd), sizeof(ddsd)); /* write file header */ - fout.write(reinterpret_cast(img->data()), size ); + + for(osg::Image::DataIterator itr(img); itr.valid(); ++itr) + { + fout.write(reinterpret_cast(itr.data()), itr.size() ); + } // Check for correct saving if ( fout.fail() ) diff --git a/src/osgPlugins/exr/ReaderWriterEXR.cpp b/src/osgPlugins/exr/ReaderWriterEXR.cpp index eaf53e2dd..4e2f96018 100644 --- a/src/osgPlugins/exr/ReaderWriterEXR.cpp +++ b/src/osgPlugins/exr/ReaderWriterEXR.cpp @@ -276,9 +276,9 @@ protected: //If texture is half format if (dataType == GL_HALF_FLOAT_ARB) { - half* pOut = (half*) img.data(); for (long i = height-1; i >= 0; i--) { + half* pOut = (half*) img.data(0,i); for (long j = 0 ; j < width; j++) { outPixels[i][j].r = (*pOut); diff --git a/src/osgPlugins/hdr/hdrwriter.cpp b/src/osgPlugins/hdr/hdrwriter.cpp index 1644074c3..9c9a52a87 100644 --- a/src/osgPlugins/hdr/hdrwriter.cpp +++ b/src/osgPlugins/hdr/hdrwriter.cpp @@ -36,20 +36,16 @@ #include -bool HDRWriter::writeRLE(const osg::Image *img, std::ostream& fout) -{ - return writePixelsRLE(fout,(float*) img->data(), img->s(), img->t()); -} - bool HDRWriter::writeRAW(const osg::Image *img, std::ostream& fout) { - return writePixelsRAW(fout,(unsigned char*) img->data(), img->s() * img->t()); + bool result = true; + for(int row=0; result && rowt(); ++row) + { + result = writePixelsRAW(fout,(unsigned char*) img->data(0, row), img->s()); + } + return result; } - - - - /* number of floats per pixel */ #define RGBE_DATA_SIZE 3 @@ -86,21 +82,26 @@ bool HDRWriter::writeHeader(const osg::Image *img, std::ostream& fout) /* simple write routine that does not use run length encoding */ /* These routines can be made faster by allocating a larger buffer and fread-ing and fwrite-ing the data in larger chunks */ -bool HDRWriter::writePixelsNoRLE( std::ostream& fout, float* data, int numpixels) +bool HDRWriter::writeNoRLE( std::ostream& fout, const osg::Image* img) { unsigned char rgbe[4]; - while (numpixels-- > 0) + for(int row=0; rowt(); ++row) { - float2rgbe( + float* data = (float*)img->data(0,row); + for(int column=0; columns(); ++column) + { + float2rgbe( rgbe, data[R], data[G], data[B] ); - data += RGBE_DATA_SIZE; - fout.write(reinterpret_cast(rgbe), sizeof(rgbe)); //img->getTotalSizeInBytesIncludingMipmaps() + data += RGBE_DATA_SIZE; + fout.write(reinterpret_cast(rgbe), sizeof(rgbe)); + } } + return true; } @@ -183,23 +184,27 @@ bool HDRWriter::writeBytesRLE(std::ostream& fout, unsigned char *data, int numby #undef MINRUNLENGTH } -bool HDRWriter::writePixelsRLE( std::ostream& fout, float* data, int scanline_width, int num_scanlines ) - +bool HDRWriter::writeRLE( const osg::Image* img, std::ostream& fout) { + int scanline_width = img->s(); + int num_scanlines = img->t(); + unsigned char rgbe[4]; unsigned char *buffer; if ((scanline_width < MINELEN)||(scanline_width > MAXELEN)) // run length encoding is not allowed so write flat - return writePixelsNoRLE(fout,data,scanline_width*num_scanlines); + return writeNoRLE(fout,img); buffer = (unsigned char *)malloc(sizeof(unsigned char)*4*scanline_width); if (buffer == NULL) // no buffer space so write flat - return writePixelsNoRLE(fout,data,scanline_width*num_scanlines); + return writeNoRLE(fout,img); - while(num_scanlines-- > 0) + for(int row = 0; rowdata(0, row); + rgbe[0] = 2; rgbe[1] = 2; rgbe[2] = scanline_width >> 8; diff --git a/src/osgPlugins/hdr/hdrwriter.h b/src/osgPlugins/hdr/hdrwriter.h index 8374ba9c5..9aeda1b1a 100644 --- a/src/osgPlugins/hdr/hdrwriter.h +++ b/src/osgPlugins/hdr/hdrwriter.h @@ -39,13 +39,12 @@ public: protected: // can read or write pixels in chunks of any size including single pixels - static bool writePixelsNoRLE( std::ostream& fout, float* data, int numpixels); + static bool writeNoRLE( std::ostream& fout, const osg::Image* image); static bool writePixelsRAW( std::ostream& fout, unsigned char* data, int numpixels); // read or write run length encoded files // must be called to read or write whole scanlines static bool writeBytesRLE(std::ostream& fout, unsigned char *data, int numbytes); - static bool writePixelsRLE( std::ostream& fout, float* data, int scanline_width, int num_scanlines ); // inline conversions inline static void float2rgbe(unsigned char rgbe[4], float red, float green, float blue); diff --git a/src/osgPlugins/imageio/ReaderWriterImageIO.cpp b/src/osgPlugins/imageio/ReaderWriterImageIO.cpp index 26b1b5c8d..f1489bc2c 100644 --- a/src/osgPlugins/imageio/ReaderWriterImageIO.cpp +++ b/src/osgPlugins/imageio/ReaderWriterImageIO.cpp @@ -1199,6 +1199,11 @@ public: WriteResult writeImageStream(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const { + if (!osg_image.isDataContiguous()) + { + return WriteResult::FILE_NOT_HANDLED; + } + WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromDataStream(fout, the_options); @@ -1235,6 +1240,12 @@ public: WriteResult writeImageFile(const osg::Image& osg_image, const std::string& full_file_name, const osgDB::ReaderWriter::Options* the_options) const { + if (!osg_image.isDataContiguous()) + { + return WriteResult::FILE_NOT_HANDLED; + } + + WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; // Call ImageIO to load the image. CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromFile(full_file_name.c_str(), the_options); @@ -1268,6 +1279,12 @@ public: std::string ext = osgDB::getFileExtension(file_name); if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; + if (!osg_image.isDataContiguous()) + { + return WriteResult::FILE_NOT_HANDLED; + } + + WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; #if 1 // FIXME: Something may need to provide a proper writable location for the files. std::string full_file_name; diff --git a/src/osgPlugins/ive/Image.cpp b/src/osgPlugins/ive/Image.cpp index d716bd325..c09f096a2 100644 --- a/src/osgPlugins/ive/Image.cpp +++ b/src/osgPlugins/ive/Image.cpp @@ -72,7 +72,10 @@ void Image::write(DataOutputStream* out) unsigned int size = getTotalSizeInBytesIncludingMipmaps(); out->writeInt(size); // Write the data - out->writeCharArray((char*)data(), size); + for(osg::Image::DataIterator itr(this); itr.valid(); ++itr) + { + out->writeCharArray((char*)itr.data(), itr.size()); + } } } diff --git a/src/osgPlugins/jp2/ReaderWriterJP2.cpp b/src/osgPlugins/jp2/ReaderWriterJP2.cpp index 1fe658fa5..6078d8078 100644 --- a/src/osgPlugins/jp2/ReaderWriterJP2.cpp +++ b/src/osgPlugins/jp2/ReaderWriterJP2.cpp @@ -353,6 +353,12 @@ class ReaderWriterJP2 : public osgDB::ReaderWriter std::string ext = osgDB::getFileExtension(fileName); if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; + if (!img.isDataContiguous()) + { + OSG_WARN<<"Warning: Writing of image data, that is non contiguous, is not supported by JPEG2000 plugin."<getPacking()); + glPixelStorei(GL_UNPACK_ROW_LENGTH, img->getRowLength()); x = place[i][0] + xi * img->s(); if( i == Center || i == UpperLeft || i == UpperRight || i == UpperCenter) y += yi * img->t(); diff --git a/src/osgPlugins/nvtt/NVTTImageProcessor.cpp b/src/osgPlugins/nvtt/NVTTImageProcessor.cpp index a98127220..0fe95a2c8 100644 --- a/src/osgPlugins/nvtt/NVTTImageProcessor.cpp +++ b/src/osgPlugins/nvtt/NVTTImageProcessor.cpp @@ -46,10 +46,10 @@ protected: }; // Convert RGBA to BGRA : nvtt only accepts BGRA pixel format - void convertRGBAToBGRA( std::vector& outputData, const unsigned char* inputData ); + void convertRGBAToBGRA( std::vector& outputData, const osg::Image& image ); // Convert RGB to BGRA : nvtt only accepts BGRA pixel format - void convertRGBToBGRA( std::vector& outputData, const unsigned char* inputData ); + void convertRGBToBGRA( std::vector& outputData, const osg::Image& image ); }; @@ -175,27 +175,38 @@ bool NVTTProcessor::OSGImageOutputHandler::writeData(const void * data, int size } // Convert RGBA to BGRA : nvtt only accepts BGRA pixel format -void NVTTProcessor::convertRGBAToBGRA( std::vector& outputData, const unsigned char* inputData ) +void NVTTProcessor::convertRGBAToBGRA( std::vector& outputData, const osg::Image& image ) { - for (unsigned n=0; n& outputData, const unsigned char* inputData ) +void NVTTProcessor::convertRGBToBGRA( std::vector& outputData, const osg::Image& image ) { - unsigned int numberOfPixels = outputData.size()/4; - for (unsigned n=0; n imageData( image.s() * image.t() * 4 ); if (image.getPixelFormat() == GL_RGB) { - convertRGBToBGRA( imageData, image.data() ); + convertRGBToBGRA( imageData, image ); } else { - convertRGBAToBGRA( imageData, image.data() ); + convertRGBAToBGRA( imageData, image ); } inputOptions.setMipmapData(&imageData[0],image.s(),image.t()); diff --git a/src/osgPlugins/pov/ReaderWriterPOV.cpp b/src/osgPlugins/pov/ReaderWriterPOV.cpp index 6873b255b..4ca9129fc 100644 --- a/src/osgPlugins/pov/ReaderWriterPOV.cpp +++ b/src/osgPlugins/pov/ReaderWriterPOV.cpp @@ -101,8 +101,7 @@ ReaderWriterPOV::writeNode( const Node& node, const string& fileName, string ext = osgDB::getLowerCaseFileExtension( fileName ); if( !acceptsExtension( ext ) ) return WriteResult::FILE_NOT_HANDLED; - notify( NOTICE ) << "ReaderWriterPOV::writeNode() Writing file " - << fileName.data() << endl; + notify( NOTICE ) << "ReaderWriterPOV::writeNode() Writing file " << fileName << endl; osgDB::ofstream fout( fileName.c_str(), ios::out | ios::trunc ); if( !fout ) diff --git a/src/osgPlugins/rgb/ReaderWriterRGB.cpp b/src/osgPlugins/rgb/ReaderWriterRGB.cpp index 7d23ebd64..1125d48de 100644 --- a/src/osgPlugins/rgb/ReaderWriterRGB.cpp +++ b/src/osgPlugins/rgb/ReaderWriterRGB.cpp @@ -660,11 +660,33 @@ class ReaderWriterRGB : public osgDB::ReaderWriter virtual WriteResult writeImage(const osg::Image& img,std::ostream& fout,const osgDB::ReaderWriter::Options*) const { + if (img.isCompressed()) + { + OSG_NOTICE<<"Warning: RGB plugin does not supporting writing compressed imagery."<_ready) - { - imageStream->allocateImage(width,height,1,pixelFormat,GL_UNSIGNED_BYTE,1); - imageStream->setInternalTextureFormat(GL_RGBA); - } - - osg::Timer_t start_tick = osg::Timer::instance()->tick(); - - memcpy(imageStream->data(),data,imageStream->getTotalSizeInBytes()); - - OSG_INFO<<"image memcpy size="<getTotalSizeInBytes()<<" time="<delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<dirty(); - #else - imageStream->setImage(width,height,1, + imageStream->setImage(width,height,1, GL_RGB, pixelFormat,GL_UNSIGNED_BYTE, (unsigned char *)data, osg::Image::NO_DELETE, 1); - #endif + imageStream->_ready = true; } diff --git a/src/osgText/Glyph.cpp b/src/osgText/Glyph.cpp index ab0b1b975..8732de49e 100644 --- a/src/osgText/Glyph.cpp +++ b/src/osgText/Glyph.cpp @@ -474,6 +474,7 @@ void Glyph::subload() const } glPixelStorei(GL_UNPACK_ALIGNMENT,getPacking()); + glPixelStorei(GL_UNPACK_ROW_LENGTH,getRowLength()); glTexSubImage2D(GL_TEXTURE_2D,0, _texturePosX,_texturePosY,