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.
This commit is contained in:
@@ -204,7 +204,21 @@ void GLBufferObject::compileBuffer()
|
||||
// OSG_NOTICE<<"GLBufferObject::compileBuffer(..) downloading BufferEntry "<<&entry<<std::endl;
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ void DrawPixels::drawImplementation(RenderInfo&) const
|
||||
if (_useSubImage)
|
||||
{
|
||||
const GLvoid* pixels = _image->data(_offsetX,_offsetY);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,_image->getPacking());
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,_image->s());
|
||||
glDrawPixels(_width,_height,
|
||||
(GLenum)_image->getPixelFormat(),
|
||||
@@ -105,6 +106,8 @@ void DrawPixels::drawImplementation(RenderInfo&) const
|
||||
}
|
||||
else
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,_image->getPacking());
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,0);
|
||||
glDrawPixels(_image->s(), _image->t(),
|
||||
(GLenum)_image->getPixelFormat(),
|
||||
(GLenum)_image->getDataType(),
|
||||
|
||||
@@ -48,12 +48,164 @@ void Image::UpdateCallback::operator () (osg::StateAttribute* attr, osg::NodeVis
|
||||
}
|
||||
}
|
||||
|
||||
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(),
|
||||
_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="<<sizeOfLastMipMap<<"\ts="<<s<<"\tt="<<t<<"\tr"<<r<<std::endl;
|
||||
|
||||
return maxValue+sizeOfLastMipMap;
|
||||
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
|
||||
@@ -685,6 +851,7 @@ void Image::allocateImage(int s,int t,int r,
|
||||
_pixelFormat = format;
|
||||
_dataType = type;
|
||||
_packing = packing;
|
||||
_rowLength = 0;
|
||||
|
||||
// preserve internalTextureFormat if already set, otherwise
|
||||
// use the pixelFormat as the source for the format.
|
||||
@@ -700,6 +867,7 @@ void Image::allocateImage(int s,int t,int r,
|
||||
_pixelFormat = 0;
|
||||
_dataType = 0;
|
||||
_packing = 0;
|
||||
_rowLength = 0;
|
||||
|
||||
// commenting out reset of _internalTextureFormat as we are changing
|
||||
// policy so that allocateImage honours previous settings of _internalTextureFormat.
|
||||
@@ -714,7 +882,8 @@ void Image::setImage(int s,int t,int r,
|
||||
GLenum format,GLenum type,
|
||||
unsigned char *data,
|
||||
AllocationMode mode,
|
||||
int packing)
|
||||
int packing,
|
||||
int rowLength)
|
||||
{
|
||||
_mipmapData.clear();
|
||||
|
||||
@@ -729,6 +898,7 @@ void Image::setImage(int s,int t,int r,
|
||||
setData(data,mode);
|
||||
|
||||
_packing = packing;
|
||||
_rowLength = rowLength;
|
||||
|
||||
dirty();
|
||||
|
||||
@@ -740,6 +910,7 @@ void Image::readPixels(int x,int y,int width,int height,
|
||||
allocateImage(width,height,1,format,type);
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT,_packing);
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH,_rowLength);
|
||||
|
||||
glReadPixels(x,y,width,height,format,type,_data);
|
||||
}
|
||||
@@ -775,6 +946,7 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps
|
||||
GLint height;
|
||||
GLint depth;
|
||||
GLint packing;
|
||||
GLint rowLength;
|
||||
|
||||
GLint numMipMaps = 0;
|
||||
if (copyMipMapsIfAvailable)
|
||||
@@ -856,6 +1028,8 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps
|
||||
glGetTexLevelParameteriv(textureMode, 0, GL_TEXTURE_DEPTH, &depth);
|
||||
glGetIntegerv(GL_UNPACK_ALIGNMENT, &packing);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, packing);
|
||||
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowLength);
|
||||
glPixelStorei(GL_PACK_ROW_LENGTH, rowLength);
|
||||
|
||||
_data = data;
|
||||
_s = width;
|
||||
@@ -868,7 +1042,8 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps
|
||||
_mipmapData = mipMapData;
|
||||
_allocationMode=USE_NEW_DELETE;
|
||||
_packing = packing;
|
||||
|
||||
_rowLength = rowLength;
|
||||
|
||||
for(i=0;i<numMipMaps;++i)
|
||||
{
|
||||
extensions->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;i<numMipMaps;++i)
|
||||
{
|
||||
@@ -969,6 +1147,7 @@ void Image::scaleImage(int s,int t,int r, GLenum newDataType)
|
||||
|
||||
PixelStorageModes psm;
|
||||
psm.pack_alignment = _packing;
|
||||
psm.pack_row_length = _rowLength;
|
||||
psm.unpack_alignment = _packing;
|
||||
|
||||
GLint status = gluScaleImage(&psm, _pixelFormat,
|
||||
@@ -987,6 +1166,7 @@ void Image::scaleImage(int s,int t,int r, GLenum newDataType)
|
||||
// free old image.
|
||||
_s = s;
|
||||
_t = t;
|
||||
_rowLength = 0;
|
||||
_dataType = newDataType;
|
||||
setData(newData,USE_NEW_DELETE);
|
||||
}
|
||||
@@ -1034,8 +1214,9 @@ void Image::copySubImage(int s_offset, int t_offset, int r_offset, const osg::Im
|
||||
|
||||
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,
|
||||
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(top<bottom)
|
||||
{
|
||||
for(unsigned int i=0;i<rowSize;++i, ++top,++bottom)
|
||||
unsigned char* t = top;
|
||||
unsigned char* b = bottom;
|
||||
for(unsigned int i=0;i<rowSize;++i, ++t,++b)
|
||||
{
|
||||
unsigned char temp=*top;
|
||||
*top = *bottom;
|
||||
*bottom = temp;
|
||||
unsigned char temp=*t;
|
||||
*t = *b;
|
||||
*b = temp;
|
||||
}
|
||||
bottom -= 2*rowSize;
|
||||
top += rowStep;
|
||||
bottom -= rowStep;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1126,6 +1310,9 @@ void Image::flipVertical()
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int rowSize = getRowSizeInBytes();
|
||||
unsigned int rowStep = getRowStepInBytes();
|
||||
|
||||
if (_mipmapData.empty())
|
||||
{
|
||||
// no mipmaps,
|
||||
@@ -1135,12 +1322,10 @@ void Image::flipVertical()
|
||||
if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,data(0,0,r)))
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1149,11 +1334,10 @@ void Image::flipVertical()
|
||||
if (!dxtc_tool::VerticalFlip(_s,_t,_pixelFormat,_data))
|
||||
{
|
||||
// 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;
|
||||
unsigned char* bottom = top + (_t-1)*rowStep;
|
||||
|
||||
flipImageVertical(top, bottom, rowSize);
|
||||
flipImageVertical(top, bottom, rowSize, rowStep);
|
||||
}
|
||||
|
||||
int s = _s;
|
||||
@@ -1169,11 +1353,10 @@ void Image::flipVertical()
|
||||
if (!dxtc_tool::VerticalFlip(s,t,_pixelFormat,_data+_mipmapData[i]))
|
||||
{
|
||||
// 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;
|
||||
unsigned char* bottom = top + (t-1)*rowStep;
|
||||
|
||||
flipImageVertical(top, bottom, rowSize);
|
||||
flipImageVertical(top, bottom, rowSize, rowStep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1200,17 +1383,20 @@ void Image::flipDepth()
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int sizeOfSlice = getImageSizeInBytes();
|
||||
unsigned int sizeOfRow = getRowSizeInBytes();
|
||||
|
||||
int r_top = 0;
|
||||
int r_bottom = _r-1;
|
||||
for(; r_top<r_bottom; ++r_top,--r_bottom)
|
||||
int r_front = 0;
|
||||
int r_back = _r-1;
|
||||
for(; r_front<r_back; ++r_front,--r_back)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1425,7 +1611,8 @@ Geode* osg::createGeodeForImage(osg::Image* image,float s,float t)
|
||||
dstate->setMode(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);
|
||||
|
||||
|
||||
@@ -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<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
|
||||
@@ -1919,6 +1923,8 @@ void Texture::applyTexImage2D_load(State& state, GLenum target, const Image* ima
|
||||
pbo = 0;
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,rowLength);
|
||||
|
||||
if( !mipmappingRequired || useHardwareMipMapGeneration)
|
||||
{
|
||||
|
||||
@@ -2108,6 +2114,7 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image*
|
||||
bool compressed_image = isCompressedInternalFormat((GLenum)image->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<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
|
||||
@@ -2168,6 +2178,8 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image*
|
||||
pbo = 0;
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,rowLength);
|
||||
|
||||
if( !mipmappingRequired || useHardwareMipMapGeneration)
|
||||
{
|
||||
|
||||
|
||||
@@ -286,6 +286,7 @@ void Texture1D::applyTexImage1D(GLenum target, Image* image, State& state, GLsiz
|
||||
}
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,image->getPacking());
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH,image->getRowLength());
|
||||
|
||||
static MyCompressedTexImage1DArbProc glCompressedTexImage1D_ptr =
|
||||
convertPointerType<MyCompressedTexImage1DArbProc, void*>(getGLExtensionFuncPtr("glCompressedTexImage1DARB"));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<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())
|
||||
{
|
||||
|
||||
@@ -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; 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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -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<osg::Image> 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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -527,7 +527,7 @@ static bool bmp_save(const osg::Image& img, std::ostream& fout)
|
||||
std::vector<unsigned char> 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
|
||||
|
||||
@@ -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.dwMipMapCount<<std::endl;
|
||||
}
|
||||
|
||||
@@ -913,7 +909,11 @@ bool WriteDDSFile(const osg::Image *img, std::ostream& fout)
|
||||
// Write DDS file
|
||||
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
|
||||
if ( fout.fail() )
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -36,20 +36,16 @@
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
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 */
|
||||
#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; row<img->t(); ++row)
|
||||
{
|
||||
float2rgbe(
|
||||
float* data = (float*)img->data(0,row);
|
||||
for(int column=0; column<img->s(); ++column)
|
||||
{
|
||||
float2rgbe(
|
||||
rgbe,
|
||||
data[R],
|
||||
data[G],
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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; row<num_scanlines; ++row)
|
||||
{
|
||||
float* data = (float*) img->data(0, row);
|
||||
|
||||
rgbe[0] = 2;
|
||||
rgbe[1] = 2;
|
||||
rgbe[2] = scanline_width >> 8;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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."<<std::endl;
|
||||
return WriteResult::ERROR_IN_WRITING_FILE;
|
||||
}
|
||||
|
||||
jas_image_cmptparm_t cmptparms[4];
|
||||
jas_image_cmptparm_t *cmptparm;
|
||||
|
||||
@@ -429,6 +435,12 @@ class ReaderWriterJP2 : public osgDB::ReaderWriter
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -647,6 +647,12 @@ class ReaderWriterJPEG : public osgDB::ReaderWriter
|
||||
|
||||
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();
|
||||
if ( (image_width == 0) || (image_height == 0) )
|
||||
|
||||
@@ -152,6 +152,8 @@ class Logos: public osg::Drawable
|
||||
for( p = _logos[i].begin(); p != _logos[i].end(); p++ )
|
||||
{
|
||||
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)
|
||||
y += yi * img->t();
|
||||
|
||||
@@ -46,10 +46,10 @@ protected:
|
||||
};
|
||||
|
||||
// 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 );
|
||||
|
||||
};
|
||||
|
||||
@@ -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<unsigned char>& outputData, const unsigned char* inputData )
|
||||
void NVTTProcessor::convertRGBAToBGRA( std::vector<unsigned char>& outputData, const osg::Image& image )
|
||||
{
|
||||
for (unsigned n=0; n<outputData.size(); n += 4)
|
||||
unsigned int n=0;
|
||||
for(int row=0; row<image.t(); ++row)
|
||||
{
|
||||
outputData[n] = inputData[n+2];
|
||||
outputData[n+1] = inputData[n+1];
|
||||
outputData[n+2] = inputData[n];
|
||||
outputData[n+3] = inputData[n+3];
|
||||
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 )
|
||||
void NVTTProcessor::convertRGBToBGRA( std::vector<unsigned char>& outputData, const osg::Image& image )
|
||||
{
|
||||
unsigned int numberOfPixels = outputData.size()/4;
|
||||
for (unsigned n=0; n<numberOfPixels; n++)
|
||||
unsigned int n=0;
|
||||
for(int row=0; row<image.t(); ++row)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,11 +238,11 @@ void NVTTProcessor::process( osg::Image& image, nvtt::Format format, bool genera
|
||||
std::vector<unsigned char> 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());
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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."<<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,"");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -545,6 +545,8 @@ class ReaderWriterTGA : public osgDB::ReaderWriter
|
||||
|
||||
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
|
||||
// The format description can be found at:
|
||||
@@ -553,8 +555,6 @@ class ReaderWriterTGA : public osgDB::ReaderWriter
|
||||
int width = image.s(), height = image.t();
|
||||
int numPerPixel = image.computeNumComponents(pixelFormat);
|
||||
int pixelMultiplier = (image.getDataType()==GL_FLOAT ? 255 : 1);
|
||||
const unsigned char* data = image.data();
|
||||
if ( !data ) return false;
|
||||
|
||||
// Headers
|
||||
fout.put(0); // Identification field size
|
||||
@@ -581,7 +581,7 @@ class ReaderWriterTGA : public osgDB::ReaderWriter
|
||||
// Data
|
||||
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)
|
||||
{
|
||||
int off = x * numPerPixel;
|
||||
|
||||
@@ -192,29 +192,13 @@ class XineImageStream : public osg::ImageStream
|
||||
|
||||
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,
|
||||
(unsigned char *)data,
|
||||
osg::Image::NO_DELETE,
|
||||
1);
|
||||
#endif
|
||||
|
||||
imageStream->_ready = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user