Index: /OpenSceneGraph/trunk/include/osg/BufferObject
===================================================================
--- /OpenSceneGraph/trunk/include/osg/BufferObject (revision 12797)
+++ /OpenSceneGraph/trunk/include/osg/BufferObject (revision 12912)
@@ -621,4 +621,13 @@
         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(); }
Index: /OpenSceneGraph/trunk/include/osg/PrimitiveSet
===================================================================
--- /OpenSceneGraph/trunk/include/osg/PrimitiveSet (revision 12360)
+++ /OpenSceneGraph/trunk/include/osg/PrimitiveSet (revision 12912)
@@ -198,4 +198,8 @@
         
         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; }
Index: /OpenSceneGraph/trunk/include/osg/Image
===================================================================
--- /OpenSceneGraph/trunk/include/osg/Image (revision 12842)
+++ /OpenSceneGraph/trunk/include/osg/Image (revision 12912)
@@ -115,4 +115,7 @@
         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(); }
@@ -158,5 +161,5 @@
                       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.
@@ -214,4 +217,7 @@
         /** 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);
@@ -242,7 +248,15 @@
         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; }
@@ -254,15 +268,18 @@
         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();
         }
         
@@ -270,6 +287,42 @@
         {
             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.*/
@@ -302,7 +355,9 @@
         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);
@@ -342,10 +397,4 @@
         }
 
-        /*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;
@@ -400,4 +449,5 @@
 
         int _s, _t, _r;
+        int _rowLength;
         GLint _internalTextureFormat;
         GLenum _pixelFormat;
Index: /OpenSceneGraph/trunk/include/osg/Array
===================================================================
--- /OpenSceneGraph/trunk/include/osg/Array (revision 12608)
+++ /OpenSceneGraph/trunk/include/osg/Array (revision 12912)
@@ -105,4 +105,8 @@
         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;
Index: /OpenSceneGraph/trunk/src/osg/Texture.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osg/Texture.cpp (revision 12727)
+++ /OpenSceneGraph/trunk/src/osg/Texture.cpp (revision 12912)
@@ -1843,4 +1843,5 @@
 
     glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
+    unsigned int rowLength = image->getRowLength();
 
     bool useClientStorage = extensions->isClientStorageSupported() && getClientStorageHint();
@@ -1892,4 +1893,5 @@
         PixelStorageModes psm;
         psm.pack_alignment = image->getPacking();
+        psm.pack_row_length = image->getRowLength();
         psm.unpack_alignment = image->getPacking();
 
@@ -1900,4 +1902,5 @@
                         dataPtr);
 
+        rowLength = 0;
     }
 
@@ -1911,4 +1914,5 @@
         state.bindPixelBufferObject(pbo);
         dataPtr = reinterpret_cast<unsigned char*>(pbo->getOffset(image->getBufferIndex()));
+        rowLength = 0;
 #ifdef DO_TIMING
         OSG_NOTICE<<"after PBO "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
@@ -1919,4 +1923,6 @@
         pbo = 0;
     }
+
+    glPixelStorei(GL_UNPACK_ROW_LENGTH,rowLength);
 
     if( !mipmappingRequired || useHardwareMipMapGeneration)
@@ -2109,4 +2115,5 @@
     
     glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
+    unsigned int rowLength = image->getRowLength();
     
     unsigned char* dataPtr = (unsigned char*)image->data();
@@ -2148,4 +2155,6 @@
                       inwidth,inheight,image->getDataType(),
                       dataPtr);
+
+        rowLength = 0;
     }
 
@@ -2160,4 +2169,5 @@
         state.bindPixelBufferObject(pbo);
         dataPtr = reinterpret_cast<unsigned char*>(pbo->getOffset(image->getBufferIndex()));
+        rowLength = 0;
 #ifdef DO_TIMING
         OSG_NOTICE<<"after PBO "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
@@ -2168,4 +2178,6 @@
         pbo = 0;
     }
+
+    glPixelStorei(GL_UNPACK_ROW_LENGTH,rowLength);
 
     if( !mipmappingRequired || useHardwareMipMapGeneration)
Index: /OpenSceneGraph/trunk/src/osg/BufferObject.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osg/BufferObject.cpp (revision 12522)
+++ /OpenSceneGraph/trunk/src/osg/BufferObject.cpp (revision 12912)
@@ -205,5 +205,19 @@
             entry.modifiedCount = entry.dataSource->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="<<offset<<", size="<<img_itr.size()<<", data="<<(void*)img_itr.data()<<std::endl;
+                    _extensions->glBufferSubData(_profile._target, (GLintptrARB)offset, (GLsizeiptrARB)img_itr.size(), img_itr.data());
+                    offset += img_itr.size();
+                }
+            }
+            else
+            {            
+                _extensions->glBufferSubData(_profile._target, (GLintptrARB)entry.offset, (GLsizeiptrARB)entry.dataSize, entry.dataSource->getDataPointer());
+            }
 
         }
Index: /OpenSceneGraph/trunk/src/osg/Image.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osg/Image.cpp (revision 12842)
+++ /OpenSceneGraph/trunk/src/osg/Image.cpp (revision 12912)
@@ -49,4 +49,155 @@
 }
 
+Image::DataIterator::DataIterator(const Image* image):
+    _image(image),
+    _rowNum(0),
+    _imageNum(0),
+    _mipmapNum(0),
+    _currentPtr(0),
+    _currentSize(0)
+{
+    assign();
+}
+
+Image::DataIterator::DataIterator(const DataIterator& ri):
+    _image(ri._image),
+    _rowNum(ri._rowNum),
+    _imageNum(ri._imageNum),
+    _mipmapNum(ri._mipmapNum),
+    _currentPtr(0),
+    _currentSize(0)
+{
+    assign();
+}
+
+void Image::DataIterator::operator ++ ()
+{
+    if (!_image || _image->isDataContiguous())
+    {
+        // for contiguous image data we never need more than one block of data
+        _currentPtr = 0;
+        _currentSize = 0;
+        return;
+    }
+
+    if (_image->isMipmap())
+    {
+        // advance to next row
+        ++_rowNum;
+
+        if (_rowNum>=_image->t())
+        {
+            // moved over end of current image so move to next
+            _rowNum = 0;
+            ++_imageNum;
+
+            if (_imageNum>=_image->r())
+            {
+                // move to next mipmap
+                _imageNum = 0;
+                ++_mipmapNum;
+
+                if (_mipmapNum>=_image->getNumMipmapLevels())
+                {
+                    _currentPtr = 0;
+                    _currentSize = 0;
+                    return;
+                }
+            }
+        }
+    }
+    else
+    {
+        // advance to next row
+        ++_rowNum;
+        
+        if (_rowNum>=_image->t())
+        {
+            // moved over end of current image so move to next
+            _rowNum = 0;
+            ++_imageNum;
+
+            if (_imageNum>=_image->r())
+            {
+                // we've moved off the end of the osg::Image so reset to null
+                _currentPtr = 0;
+                _currentSize = 0;
+                return;
+            }
+        }
+    }
+   
+    assign();
+}
+
+void Image::DataIterator::assign()
+{
+    //OSG_NOTICE<<"DataIterator::assign A"<<std::endl;
+    if (!_image)
+    {
+        _currentPtr = 0;
+        _currentSize = 0;
+        return;
+    }
+    
+    //OSG_NOTICE<<"DataIterator::assign B"<<std::endl;
+
+    if (_image->isDataContiguous())
+    {
+        _currentPtr = _image->data();
+        _currentSize = _image->getTotalSizeInBytesIncludingMipmaps();
+
+        //OSG_NOTICE<<"   _currentPtr="<<(void*)_currentPtr<<std::endl;
+        //OSG_NOTICE<<"   _currentSize="<<_currentSize<<std::endl;
+
+        return;
+    }
+    
+    //OSG_NOTICE<<"DataIterator::assign C"<<std::endl;
+
+    if (_image->isMipmap())
+    {
+        //OSG_NOTICE<<"DataIterator::assign D"<<std::endl;
+
+        if (_mipmapNum>=_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"<<std::endl;
+
+        if (_imageNum>=_image->r() || _rowNum>=_image->t())
+        {
+            _currentPtr = 0;
+            _currentSize = 0;
+            return;
+        }
+
+        //OSG_NOTICE<<"DataIterator::assign F"<<std::endl;
+
+        _currentPtr = _image->data(0, _rowNum, _imageNum);
+        _currentSize = _image->getRowSizeInBytes();
+        return;
+    }
+}
+
+
 Image::Image()
     :BufferData(),
@@ -55,4 +206,5 @@
     _origin(BOTTOM_LEFT),
     _s(0), _t(0), _r(0),
+    _rowLength(0),
     _internalTextureFormat(0),
     _pixelFormat(0),
@@ -72,4 +224,5 @@
     _origin(image._origin),
     _s(image._s), _t(image._t), _r(image._r),
+    _rowLength(0),
     _internalTextureFormat(image._internalTextureFormat),
     _pixelFormat(image._pixelFormat),
@@ -85,5 +238,10 @@
         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();
+        }
     }
 }
@@ -511,4 +669,32 @@
 }
 
+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)
 {
@@ -518,4 +704,14 @@
     //OSG_INFO << "width="<<width<<" pixelSize="<<pixelSize<<"  width in bit="<<widthInBits<<" packingInBits="<<packingInBits<<" widthInBits%packingInBits="<<widthInBits%packingInBits<<std::endl;
     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)
+        );
 }
 
@@ -582,49 +778,19 @@
     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<1) s=1;
+        if (t<1) t=1;
+        if (r<1) r=1;
    }
-   
-   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;
-   }
-
-   // OSG_INFO<<"sizeOfLastMipMap="<<sizeOfLastMipMap<<"\ts="<<s<<"\tt="<<t<<"\tr"<<r<<std::endl;                  
-
-   return maxValue+sizeOfLastMipMap;
-
+
+   return totalSize;
 }
 
@@ -686,4 +852,5 @@
         _dataType = type;
         _packing = packing;
+        _rowLength = 0;
         
         // preserve internalTextureFormat if already set, otherwise
@@ -701,4 +868,5 @@
         _dataType = 0;
         _packing = 0;
+        _rowLength = 0;
         
         // commenting out reset of _internalTextureFormat as we are changing
@@ -715,5 +883,6 @@
                      unsigned char *data,
                      AllocationMode mode,
-                     int packing)
+                     int packing,
+                     int rowLength)
 {
     _mipmapData.clear();
@@ -730,4 +899,5 @@
 
     _packing = packing;
+    _rowLength = rowLength;
         
     dirty();
@@ -741,4 +911,5 @@
 
     glPixelStorei(GL_PACK_ALIGNMENT,_packing);
+    glPixelStorei(GL_PACK_ROW_LENGTH,_rowLength);
 
     glReadPixels(x,y,width,height,format,type,_data);
@@ -776,4 +947,5 @@
     GLint depth;
     GLint packing;
+    GLint rowLength;
 
     GLint numMipMaps = 0;
@@ -857,4 +1029,6 @@
         glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing);
         glPixelStorei(GL_PACK_ALIGNMENT, packing);
+        glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowLength);
+        glPixelStorei(GL_PACK_ROW_LENGTH, rowLength);
 
         _data = data;
@@ -869,5 +1043,6 @@
         _allocationMode=USE_NEW_DELETE;
         _packing = packing;
-        
+        _rowLength = rowLength;
+
         for(i=0;i<numMipMaps;++i)
         {
@@ -887,4 +1062,6 @@
         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;
@@ -928,4 +1105,5 @@
         _allocationMode=USE_NEW_DELETE;
         _packing = packing;
+        _rowLength = rowLength;
         
         for(i=0;i<numMipMaps;++i)
@@ -970,4 +1148,5 @@
     PixelStorageModes psm;
     psm.pack_alignment = _packing;
+    psm.pack_row_length = _rowLength;
     psm.unpack_alignment = _packing;
 
@@ -988,4 +1167,5 @@
         _s = s;
         _t = t;
+        _rowLength = 0;
         _dataType = newDataType;
         setData(newData,USE_NEW_DELETE);
@@ -1035,6 +1215,7 @@
     PixelStorageModes psm;
     psm.pack_alignment = _packing;
-    psm.pack_row_length = _s;
-    psm.unpack_alignment = _packing;
+    psm.pack_row_length = _rowLength!=0 ? _rowLength : _s;
+    psm.unpack_alignment = source->getPacking();
+    psm.unpack_row_length = source->getRowLength();
 
     GLint status = gluScaleImage(&psm, _pixelFormat,
@@ -1048,6 +1229,4 @@
         data_destination);
 
-    glPixelStorei(GL_PACK_ROW_LENGTH,0);
-
     if (status!=0)
     {
@@ -1068,10 +1247,12 @@
     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;
@@ -1098,15 +1279,18 @@
 }
 
-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(top<bottom)
     {
-        for(unsigned int i=0;i<rowSize;++i, ++top,++bottom)
-        {
-            unsigned char temp=*top;
-            *top = *bottom;
-            *bottom = temp;
-        }
-        bottom -= 2*rowSize;
+        unsigned char* t = top;
+        unsigned char* b = bottom;
+        for(unsigned int i=0;i<rowSize;++i, ++t,++b)
+        {
+            unsigned char temp=*t;
+            *t = *b;
+            *b = temp;
+        }
+        top += rowStep;
+        bottom -= rowStep;
     }
 }
@@ -1126,4 +1310,7 @@
         return;
     }
+
+    unsigned int rowSize = getRowSizeInBytes();
+    unsigned int rowStep = getRowStepInBytes();
 
     if (_mipmapData.empty())
@@ -1136,10 +1323,8 @@
             {
                 // its not a compressed image, so implement flip oursleves.
-                
-                unsigned int rowSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing);
                 unsigned char* top = data(0,0,r);
-                unsigned char* bottom = top + (_t-1)*rowSize;
+                unsigned char* bottom = top + (_t-1)*rowStep;
                     
-                flipImageVertical(top, bottom, rowSize);
+                flipImageVertical(top, bottom, rowSize, rowStep);
             }
         }
@@ -1150,9 +1335,8 @@
         {
             // its not a compressed image, so implement flip oursleves.
-            unsigned int rowSize = computeRowWidthInBytes(_s,_pixelFormat,_dataType,_packing);
             unsigned char* top = data(0,0,0);
-            unsigned char* bottom = top + (_t-1)*rowSize;
-
-            flipImageVertical(top, bottom, rowSize);
+            unsigned char* bottom = top + (_t-1)*rowStep;
+
+            flipImageVertical(top, bottom, rowSize, rowStep);
         }
 
@@ -1170,9 +1354,8 @@
             {
                 // its not a compressed image, so implement flip oursleves.
-                unsigned int rowSize = computeRowWidthInBytes(s,_pixelFormat,_dataType,_packing);
                 unsigned char* top = _data+_mipmapData[i];
-                unsigned char* bottom = top + (t-1)*rowSize;
-
-                flipImageVertical(top, bottom, rowSize);
+                unsigned char* bottom = top + (t-1)*rowStep;
+
+                flipImageVertical(top, bottom, rowSize, rowStep);
             }
        }
@@ -1201,15 +1384,18 @@
     }
 
-    unsigned int sizeOfSlice = getImageSizeInBytes();
-
-    int r_top = 0;
-    int r_bottom = _r-1;
-    for(; r_top<r_bottom; ++r_top,--r_bottom)
-    {
-        unsigned char* top_slice = data(0,0,r_top);
-        unsigned char* bottom_slice = data(0,0,r_bottom);
-        for(unsigned int i=0; i<sizeOfSlice; ++i, ++top_slice, ++bottom_slice)
-        {
-            std::swap(*top_slice, *bottom_slice);
+    unsigned int sizeOfRow = getRowSizeInBytes();
+
+    int r_front = 0;
+    int r_back = _r-1;
+    for(; r_front<r_back; ++r_front,--r_back)
+    {
+        for(int row=0; row<_t; ++row)
+        {        
+            unsigned char* front = data(0, row, r_front);
+            unsigned char* back = data(0, row, r_back);
+            for(unsigned int i=0; i<sizeOfRow; ++i, ++front, ++back)
+            {
+                std::swap(*front, *back);
+            }
         }
     }
@@ -1426,5 +1612,6 @@
             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);
Index: /OpenSceneGraph/trunk/src/osg/Texture1D.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osg/Texture1D.cpp (revision 11817)
+++ /OpenSceneGraph/trunk/src/osg/Texture1D.cpp (revision 12912)
@@ -287,4 +287,5 @@
 
     glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
+    glPixelStorei(GL_UNPACK_ROW_LENGTH,image->getRowLength());
 
     static MyCompressedTexImage1DArbProc glCompressedTexImage1D_ptr = 
Index: /OpenSceneGraph/trunk/src/osg/TextureRectangle.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osg/TextureRectangle.cpp (revision 11808)
+++ /OpenSceneGraph/trunk/src/osg/TextureRectangle.cpp (revision 12912)
@@ -313,4 +313,5 @@
 
     glPixelStorei(GL_UNPACK_ALIGNMENT, image->getPacking());
+    glPixelStorei(GL_UNPACK_ROW_LENGTH,image->getRowLength());
 
     bool useClientStorage = extensions->isClientStorageSupported() && getClientStorageHint();
@@ -393,4 +394,6 @@
 
     glPixelStorei(GL_UNPACK_ALIGNMENT, image->getPacking());
+    unsigned int rowLength = image->getRowLength();
+    
 
 #ifdef DO_TIMING
@@ -404,9 +407,11 @@
         state.bindPixelBufferObject(pbo);
         dataPtr = reinterpret_cast<unsigned char*>(pbo->getOffset(image->getBufferIndex()));
+        rowLength = 0;
 #ifdef DO_TIMING
         OSG_NOTICE<<"after PBO "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
 #endif
     }
-    
+
+    glPixelStorei(GL_UNPACK_ROW_LENGTH,rowLength);
 
     if(isCompressedInternalFormat(_internalFormat) && extensions->isCompressedTexSubImage2DSupported())
Index: /OpenSceneGraph/trunk/src/osg/Texture3D.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osg/Texture3D.cpp (revision 11881)
+++ /OpenSceneGraph/trunk/src/osg/Texture3D.cpp (revision 12912)
@@ -381,4 +381,5 @@
 
     glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
+    glPixelStorei(GL_UNPACK_ROW_LENGTH,image->getRowLength());
 
     bool useHardwareMipMapGeneration = !image->isMipmap() && _useHardwareMipMapGeneration && texExtensions->isGenerateMipMapSupported();
Index: /OpenSceneGraph/trunk/src/osg/Texture2DArray.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osg/Texture2DArray.cpp (revision 12292)
+++ /OpenSceneGraph/trunk/src/osg/Texture2DArray.cpp (revision 12912)
@@ -456,4 +456,5 @@
     
     glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
+    glPixelStorei(GL_UNPACK_ROW_LENGTH,image->getRowLength());
 
     bool useHardwareMipmapGeneration = 
Index: /OpenSceneGraph/trunk/src/osg/DrawPixels.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osg/DrawPixels.cpp (revision 11472)
+++ /OpenSceneGraph/trunk/src/osg/DrawPixels.cpp (revision 12912)
@@ -97,4 +97,5 @@
     {
         const GLvoid* pixels = _image->data(_offsetX,_offsetY);
+        glPixelStorei(GL_UNPACK_ALIGNMENT,_image->getPacking());
         glPixelStorei(GL_UNPACK_ROW_LENGTH,_image->s());
         glDrawPixels(_width,_height,
@@ -106,4 +107,6 @@
     else
     {
+        glPixelStorei(GL_UNPACK_ALIGNMENT,_image->getPacking());
+        glPixelStorei(GL_UNPACK_ROW_LENGTH,0);
         glDrawPixels(_image->s(), _image->t(),
                      (GLenum)_image->getPixelFormat(),
Index: /OpenSceneGraph/trunk/src/osgPlugins/jpeg/ReaderWriterJPEG.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/jpeg/ReaderWriterJPEG.cpp (revision 12545)
+++ /OpenSceneGraph/trunk/src/osgPlugins/jpeg/ReaderWriterJPEG.cpp (revision 12912)
@@ -648,4 +648,10 @@
         WriteResult::WriteStatus write_JPEG_file (std::ostream &fout, const osg::Image &img, int quality = 100) const
         {
+            if (!img.isDataContiguous())
+            {
+                OSG_WARN<<"Warning: Writing of image data, that is non contiguous, is not supported by JPEG plugin."<<std::endl;
+                return WriteResult::ERROR_IN_WRITING_FILE;
+            }
+
             int image_width = img.s();
             int image_height = img.t();
Index: /OpenSceneGraph/trunk/src/osgPlugins/jp2/ReaderWriterJP2.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/jp2/ReaderWriterJP2.cpp (revision 12597)
+++ /OpenSceneGraph/trunk/src/osgPlugins/jp2/ReaderWriterJP2.cpp (revision 12912)
@@ -354,4 +354,10 @@
             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."<<std::endl;
+                return WriteResult::ERROR_IN_WRITING_FILE;
+            }
+
             jas_image_cmptparm_t cmptparms[4];
             jas_image_cmptparm_t *cmptparm;
@@ -430,4 +436,10 @@
         WriteResult writeImage(const osg::Image& img, std::ostream& fout, const Options* options) const
         {
+            if (!img.isDataContiguous())
+            {
+                OSG_WARN<<"Warning: Writing of image data, that is non contiguous, is not supported by JPEG2000 plugin."<<std::endl;
+                return WriteResult::ERROR_IN_WRITING_FILE;
+            }
+
             jas_image_cmptparm_t cmptparms[4];
             jas_image_cmptparm_t *cmptparm;
Index: /OpenSceneGraph/trunk/src/osgPlugins/nvtt/NVTTImageProcessor.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/nvtt/NVTTImageProcessor.cpp (revision 12292)
+++ /OpenSceneGraph/trunk/src/osgPlugins/nvtt/NVTTImageProcessor.cpp (revision 12912)
@@ -47,8 +47,8 @@
 
     // Convert RGBA to BGRA : nvtt only accepts BGRA pixel format
-    void convertRGBAToBGRA( std::vector<unsigned char>& outputData, const unsigned char* inputData );
+    void convertRGBAToBGRA( std::vector<unsigned char>& outputData, const osg::Image& image );
 
     // Convert RGB to BGRA : nvtt only accepts BGRA pixel format
-    void convertRGBToBGRA( std::vector<unsigned char>& outputData, const unsigned char* inputData );
+    void convertRGBToBGRA( std::vector<unsigned char>& outputData, const osg::Image& image );
 
 };
@@ -176,25 +176,36 @@
 
 // Convert RGBA to BGRA : nvtt only accepts BGRA pixel format
-void NVTTProcessor::convertRGBAToBGRA( std::vector<unsigned char>& outputData, const unsigned char* inputData )
-{
-    for (unsigned n=0; n<outputData.size(); n += 4)
-    {
-        outputData[n] = inputData[n+2];
-        outputData[n+1] = inputData[n+1];
-        outputData[n+2] = inputData[n];
-        outputData[n+3] = inputData[n+3];
+void NVTTProcessor::convertRGBAToBGRA( std::vector<unsigned char>& outputData, const osg::Image& image )
+{
+    unsigned int n=0;
+    for(int row=0; row<image.t(); ++row)
+    {
+        const unsigned char* data = image.data(0,row);
+        for(int column=0; column<image.s(); ++column)
+        {
+            outputData[n] = data[column*4+2];
+            outputData[n+1] = data[column*4+1];
+            outputData[n+2] = data[column*4+n];
+            outputData[n+3] = data[column*4+3];
+            n+=4;
+        }
     }
 }
 
 // Convert RGB to BGRA : nvtt only accepts BGRA pixel format
-void NVTTProcessor::convertRGBToBGRA( std::vector<unsigned char>& outputData, const unsigned char* inputData )
-{
-    unsigned int numberOfPixels = outputData.size()/4;
-    for (unsigned n=0; n<numberOfPixels; n++)
-    {
-        outputData[4*n] = inputData[3*n+2];
-        outputData[4*n+1] = inputData[3*n+1];
-        outputData[4*n+2] = inputData[3*n];
-        outputData[4*n+3] = 255;
+void NVTTProcessor::convertRGBToBGRA( std::vector<unsigned char>& outputData, const osg::Image& image )
+{
+    unsigned int n=0;
+    for(int row=0; row<image.t(); ++row)
+    {
+        const unsigned char* data = image.data(0,row);
+        for(int column=0; column<image.s(); ++column)
+        {
+            outputData[n] = data[column*3+2];
+            outputData[n+1] = data[column*3+1];
+            outputData[n+2] = data[column*3+n];
+            outputData[n+3] = 255;
+            n+=4;
+        }
     }
 }
@@ -228,9 +239,9 @@
     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());
Index: /OpenSceneGraph/trunk/src/osgPlugins/exr/ReaderWriterEXR.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/exr/ReaderWriterEXR.cpp (revision 12292)
+++ /OpenSceneGraph/trunk/src/osgPlugins/exr/ReaderWriterEXR.cpp (revision 12912)
@@ -277,7 +277,7 @@
          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++)
                  {
Index: /OpenSceneGraph/trunk/src/osgPlugins/Inventor/ReaderWriterIV.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/Inventor/ReaderWriterIV.cpp (revision 12577)
+++ /OpenSceneGraph/trunk/src/osgPlugins/Inventor/ReaderWriterIV.cpp (revision 12912)
@@ -143,5 +143,5 @@
         {
             OSG_NOTICE << "osgDB::ReaderWriterIV::readNode() "
-                      << "File " << fileName.data()
+                      << "File " << fileName
                       << " loaded successfully." << std::endl;
         }
@@ -155,5 +155,5 @@
         {
             OSG_WARN << "osgDB::ReaderWriterIV::readNode() "
-                      << "Failed to load file " << fileName.data()
+                      << "Failed to load file " << fileName
                       << "." << std::endl;
         }
Index: /OpenSceneGraph/trunk/src/osgPlugins/Inventor/ConvertFromInventor.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/Inventor/ConvertFromInventor.cpp (revision 12625)
+++ /OpenSceneGraph/trunk/src/osgPlugins/Inventor/ConvertFromInventor.cpp (revision 12912)
@@ -1094,10 +1094,19 @@
 static osg::Image* loadImage(const char *fileName, osgDB::ReaderWriter::Options *options)
 {
-    osg::Image *osgImage = osgDB::readImageFile(fileName, options);
+    osg::ref_ptr<osg::Image> osgImage = osgDB::readImageFile(fileName, options);
 
     if (!osgImage)
+    {
         OSG_WARN << NOTIFY_HEADER << "Could not read texture file '" << fileName << "'.";
-
-    return osgImage;
+        return 0;
+    }
+
+    if (!osgImage->isDataContiguous())
+    {
+        OSG_WARN << NOTIFY_HEADER << "Inventor cannot handle non contiguous image data found in texture file '" << fileName << "'.";
+        return 0;
+    }
+
+    return osgImage.release();
 }
 
Index: /OpenSceneGraph/trunk/src/osgPlugins/rgb/ReaderWriterRGB.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/rgb/ReaderWriterRGB.cpp (revision 11563)
+++ /OpenSceneGraph/trunk/src/osgPlugins/rgb/ReaderWriterRGB.cpp (revision 12912)
@@ -661,4 +661,15 @@
         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."<<std::endl;
+                return WriteResult::ERROR_IN_WRITING_FILE;
+            }
+            if (!img.isDataContiguous())
+            {
+                OSG_NOTICE<<"Warning: RGB plugin does not supporting writing non contiguous imagery."<<std::endl;
+                return WriteResult::ERROR_IN_WRITING_FILE;
+            }
+            
             return writeRGBStream(img,fout,"");
         }
@@ -666,4 +677,15 @@
         virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options*) const
         {
+            if (img.isCompressed())
+            {
+                OSG_NOTICE<<"Warning: RGB plugin does not supporting writing compressed imagery."<<std::endl;
+                return WriteResult::ERROR_IN_WRITING_FILE;
+            }
+            if (!img.isDataContiguous())
+            {
+                OSG_NOTICE<<"Warning: RGB plugin does not supporting writing non contiguous imagery."<<std::endl;
+                return WriteResult::ERROR_IN_WRITING_FILE;
+            }
+
             std::string ext = osgDB::getFileExtension(fileName);
             if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
Index: /OpenSceneGraph/trunk/src/osgPlugins/tga/ReaderWriterTGA.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/tga/ReaderWriterTGA.cpp (revision 12574)
+++ /OpenSceneGraph/trunk/src/osgPlugins/tga/ReaderWriterTGA.cpp (revision 12912)
@@ -546,4 +546,6 @@
         bool saveTGAStream(const osg::Image& image, std::ostream& fout) const
         {
+            if (!image.data()) return false;
+
             // At present, I will only save the image to unmapped RGB format
             // Other data types can be added soon with different options
@@ -554,6 +556,4 @@
             int numPerPixel = image.computeNumComponents(pixelFormat);
             int pixelMultiplier = (image.getDataType()==GL_FLOAT ? 255 : 1);
-            const unsigned char* data = image.data();
-            if ( !data ) return false;
             
             // Headers
@@ -582,5 +582,5 @@
             for (int y=0; y<height; ++y)
             {
-                const unsigned char* ptr = data + y * width * numPerPixel;
+                const unsigned char* ptr = image.data(0,y);
                 for (int x=0; x<width; ++x)
                 {
Index: /OpenSceneGraph/trunk/src/osgPlugins/xine/ReaderWriterXine.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/xine/ReaderWriterXine.cpp (revision 12262)
+++ /OpenSceneGraph/trunk/src/osgPlugins/xine/ReaderWriterXine.cpp (revision 12912)
@@ -193,21 +193,5 @@
             GLenum pixelFormat = GL_BGRA;
 
-        #if 0   
-            if (!imageStream->_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="<<imageStream->getTotalSizeInBytes()<<" time="<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
-
-
-            imageStream->dirty();
-        #else
-             imageStream->setImage(width,height,1,
+            imageStream->setImage(width,height,1,
                               GL_RGB,
                               pixelFormat,GL_UNSIGNED_BYTE,
@@ -215,5 +199,5 @@
                               osg::Image::NO_DELETE,
                               1);
-        #endif
+
             imageStream->_ready = true;
         }
Index: /OpenSceneGraph/trunk/src/osgPlugins/pov/ReaderWriterPOV.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/pov/ReaderWriterPOV.cpp (revision 12292)
+++ /OpenSceneGraph/trunk/src/osgPlugins/pov/ReaderWriterPOV.cpp (revision 12912)
@@ -102,6 +102,5 @@
    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 );
Index: /OpenSceneGraph/trunk/src/osgPlugins/imageio/ReaderWriterImageIO.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/imageio/ReaderWriterImageIO.cpp (revision 12789)
+++ /OpenSceneGraph/trunk/src/osgPlugins/imageio/ReaderWriterImageIO.cpp (revision 12912)
@@ -1200,4 +1200,9 @@
     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;
 
@@ -1236,4 +1241,10 @@
     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.
@@ -1269,4 +1280,10 @@
         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.
Index: /OpenSceneGraph/trunk/src/osgPlugins/dds/ReaderWriterDDS.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/dds/ReaderWriterDDS.cpp (revision 12597)
+++ /OpenSceneGraph/trunk/src/osgPlugins/dds/ReaderWriterDDS.cpp (revision 12912)
@@ -879,6 +879,4 @@
     }
 
-    int size = img->getTotalSizeInBytes();
-
     // set even more flags
     if( !img->isMipmap() ) {
@@ -896,6 +894,4 @@
         
         ddsd.dwMipMapCount = img->getNumMipmapLevels();
-
-        size = img->getTotalSizeInBytesIncludingMipmaps();
 
         OSG_INFO<<"writing out with mipmaps ddsd.dwMipMapCount"<<ddsd.dwMipMapCount<<std::endl;
@@ -914,5 +910,9 @@
     fout.write("DDS ", 4); /* write FOURCC */
     fout.write(reinterpret_cast<char*>(&ddsd), sizeof(ddsd)); /* write file header */
-    fout.write(reinterpret_cast<const char*>(img->data()), size );
+
+    for(osg::Image::DataIterator itr(img); itr.valid(); ++itr)
+    {
+        fout.write(reinterpret_cast<const char*>(itr.data()), itr.size() );
+    }
 
     // Check for correct saving
Index: /OpenSceneGraph/trunk/src/osgPlugins/hdr/hdrwriter.h
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/hdr/hdrwriter.h (revision 12292)
+++ /OpenSceneGraph/trunk/src/osgPlugins/hdr/hdrwriter.h (revision 12912)
@@ -40,5 +40,5 @@
 
 // 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);
 
@@ -46,5 +46,4 @@
 // 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
Index: /OpenSceneGraph/trunk/src/osgPlugins/hdr/hdrwriter.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/hdr/hdrwriter.cpp (revision 12292)
+++ /OpenSceneGraph/trunk/src/osgPlugins/hdr/hdrwriter.cpp (revision 12912)
@@ -37,17 +37,13 @@
 
 
-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 && row<img->t(); ++row)
+    {
+        result = writePixelsRAW(fout,(unsigned char*) img->data(0, row), img->s());
+    }
+    return result;
+}
 
 /* number of floats per pixel */
@@ -87,11 +83,14 @@
 /* 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; row<img->t(); ++row)
   {
-    float2rgbe(
+    float* data = (float*)img->data(0,row);
+    for(int column=0; column<img->s(); ++column)
+    {
+      float2rgbe(
         rgbe,
         data[R],
@@ -99,7 +98,9 @@
         data[B]
         );
-    data += RGBE_DATA_SIZE;
-    fout.write(reinterpret_cast<const char*>(rgbe), sizeof(rgbe)); //img->getTotalSizeInBytesIncludingMipmaps()
+      data += RGBE_DATA_SIZE;
+      fout.write(reinterpret_cast<const char*>(rgbe), sizeof(rgbe));
+    }
   }
+
   return true;
 }
@@ -184,7 +185,9 @@
 }
 
-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;
@@ -192,13 +195,15 @@
     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);
-
-    while(num_scanlines-- > 0)
-    {
+        return writeNoRLE(fout,img);
+
+    for(int row = 0; row<num_scanlines; ++row)
+    {
+        float* data = (float*) img->data(0, row);
+        
         rgbe[0] = 2;
         rgbe[1] = 2;
Index: /OpenSceneGraph/trunk/src/osgPlugins/ive/Image.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/ive/Image.cpp (revision 11807)
+++ /OpenSceneGraph/trunk/src/osgPlugins/ive/Image.cpp (revision 12912)
@@ -73,5 +73,8 @@
         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());
+        }
     }
 
Index: /OpenSceneGraph/trunk/src/osgPlugins/logo/ReaderWriterLOGO.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/logo/ReaderWriterLOGO.cpp (revision 11516)
+++ /OpenSceneGraph/trunk/src/osgPlugins/logo/ReaderWriterLOGO.cpp (revision 12912)
@@ -153,4 +153,6 @@
                     {
                         osg::Image *img = (*p).get();
+                        glPixelStorei(GL_UNPACK_ALIGNMENT, img->getPacking());
+                        glPixelStorei(GL_UNPACK_ROW_LENGTH, img->getRowLength());
                         x = place[i][0] + xi * img->s();
                         if( i == Center || i == UpperLeft || i == UpperRight || i == UpperCenter)
Index: /OpenSceneGraph/trunk/src/osgPlugins/bmp/ReaderWriterBMP.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/bmp/ReaderWriterBMP.cpp (revision 12574)
+++ /OpenSceneGraph/trunk/src/osgPlugins/bmp/ReaderWriterBMP.cpp (revision 12912)
@@ -528,5 +528,5 @@
     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)
         {
Index: /OpenSceneGraph/trunk/src/osgText/Glyph.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgText/Glyph.cpp (revision 12407)
+++ /OpenSceneGraph/trunk/src/osgText/Glyph.cpp (revision 12912)
@@ -475,4 +475,5 @@
 
     glPixelStorei(GL_UNPACK_ALIGNMENT,getPacking());
+    glPixelStorei(GL_UNPACK_ROW_LENGTH,getRowLength());
 
     glTexSubImage2D(GL_TEXTURE_2D,0,
Index: /OpenSceneGraph/trunk/src/osgDB/OutputStream.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgDB/OutputStream.cpp (revision 12896)
+++ /OpenSceneGraph/trunk/src/osgDB/OutputStream.cpp (revision 12912)
@@ -370,13 +370,31 @@
                 // _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; i<numMipmaps; ++i)
                 {
-                    *this << *itr;
+                    unsigned int size = osg::Image::computeImageSizeInBytes(s,t,r,img->getPixelFormat(),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;                    
                 }
             }
Index: /OpenSceneGraph/trunk/examples/osgscreencapture/osgscreencapture.cpp
===================================================================
--- /OpenSceneGraph/trunk/examples/osgscreencapture/osgscreencapture.cpp (revision 12292)
+++ /OpenSceneGraph/trunk/examples/osgscreencapture/osgscreencapture.cpp (revision 12912)
@@ -385,4 +385,5 @@
     {
         memcpy(image->data(), src, image->getTotalSizeInBytes());
+        
         ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
     }
Index: /OpenSceneGraph/trunk/examples/osgphotoalbum/PhotoArchive.cpp
===================================================================
--- /OpenSceneGraph/trunk/examples/osgphotoalbum/PhotoArchive.cpp (revision 12577)
+++ /OpenSceneGraph/trunk/examples/osgphotoalbum/PhotoArchive.cpp (revision 12912)
@@ -223,4 +223,5 @@
             osg::PixelStorageModes psm;
             psm.pack_alignment = image->getPacking();
+            psm.pack_row_length = image->getRowLength();
             psm.unpack_alignment = image->getPacking();
 
@@ -290,4 +291,5 @@
             osg::PixelStorageModes psm;
             psm.pack_alignment = image->getPacking();
+            psm.pack_row_length = image->getRowLength();
             psm.unpack_alignment = image->getPacking();
 
Index: /OpenSceneGraph/trunk/examples/osgtexture2D/osgtexture2D.cpp
===================================================================
--- /OpenSceneGraph/trunk/examples/osgtexture2D/osgtexture2D.cpp (revision 9636)
+++ /OpenSceneGraph/trunk/examples/osgtexture2D/osgtexture2D.cpp (revision 12912)
@@ -537,6 +537,48 @@
     {
 
-        
+#if 1        
+        osg::ref_ptr<osg::Image> originalImage = osgDB::readImageFile("Images/dog_left_eye.jpg");
+
+        osg::ref_ptr<osg::Image> 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"<<std::endl;
+        for(osg::Image::DataIterator itr(originalImage.get()); itr.valid(); ++itr)
+        {
+            OSG_NOTICE<<"  "<<(void*)itr.data()<<", "<<itr.size()<<std::endl;
+        }
+
+        OSG_NOTICE<<"subImage iterator, size "<<subImage->s()<<", "<<subImage->t()<<std::endl;
+        unsigned int i=0;
+        for(osg::Image::DataIterator itr(subImage.get()); itr.valid(); ++itr, ++i)
+        {
+            OSG_NOTICE<<"  "<<i<<", "<<(void*)itr.data()<<", "<<itr.size()<<std::endl;
+
+            for(unsigned char* d=const_cast<unsigned char*>(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");
         
@@ -585,4 +627,5 @@
 protected:
 
+    
     typedef std::vector< osg::ref_ptr<osg::Image> > ImageList;
     typedef std::vector<std::string>                TextList;
