From Sukender, "Added vertical flipping to the writer depending on the Image::getOrigin() value (= flip the image when Image::BOTTOM_LEFT). Most of the time this will not change DDS writing (= no v-flip), as it seems images are rarely "BOTTOM_LEFT". To skip this behaviour, the "ddsNoAutoFlipWrite" option was added.

I also moved a few lines of code about "dds_flip" option, and made options reading more like in other ReaderWriters."
This commit is contained in:
Robert Osfield
2013-05-28 11:46:01 +00:00
parent 53fd801088
commit 492459e4dc

View File

@@ -431,7 +431,7 @@ static unsigned int ComputeImageSizeInBytes
return size;
}
osg::Image* ReadDDSFile(std::istream& _istream)
osg::Image* ReadDDSFile(std::istream& _istream, bool flipDDSRead)
{
DDSURFACEDESC2 ddsd;
@@ -1032,12 +1032,25 @@ osg::Image* ReadDDSFile(std::istream& _istream)
if (mipmap_offsets.size()>0) osgImage->setMipmapLevels(mipmap_offsets);
if (flipDDSRead) {
osgImage->setOrigin(osg::Image::BOTTOM_LEFT);
if (!isDXTC || ((s>4 && s%4==0 && t>4 && t%4==0) || s<4)) // Flip may crash (access violation) or fail for non %4 dimensions (except for s<4). Tested with revision trunk 2013-02-22.
{
osgImage->flipVertical();
}
else
{
OSG_WARN << "ReadDDSFile warning: Vertical flip was skipped. Image dimensions have to be multiple of 4." << std::endl;
}
}
// Return Image.
return osgImage.release();
}
bool WriteDDSFile(const osg::Image *img, std::ostream& fout)
bool WriteDDSFile(const osg::Image *img, std::ostream& fout, bool autoFlipDDSWrite)
{
bool isDXTC(false);
// Initialize ddsd structure and its members
DDSURFACEDESC2 ddsd;
@@ -1175,6 +1188,7 @@ bool WriteDDSFile(const osg::Image *img, std::ostream& fout)
//Compressed
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
{
isDXTC = true;
ddpf.dwFourCC = FOURCC_DXT1;
PF_flags |= (DDPF_ALPHAPIXELS | DDPF_FOURCC);
ddsd.dwLinearSize = imageSize;
@@ -1183,6 +1197,7 @@ bool WriteDDSFile(const osg::Image *img, std::ostream& fout)
break;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
{
isDXTC = true;
ddpf.dwFourCC = FOURCC_DXT3;
PF_flags |= (DDPF_ALPHAPIXELS | DDPF_FOURCC);
ddsd.dwLinearSize = imageSize;
@@ -1191,6 +1206,7 @@ bool WriteDDSFile(const osg::Image *img, std::ostream& fout)
break;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
{
isDXTC = true;
ddpf.dwFourCC = FOURCC_DXT5;
PF_flags |= (DDPF_ALPHAPIXELS | DDPF_FOURCC);
ddsd.dwLinearSize = imageSize;
@@ -1199,6 +1215,7 @@ bool WriteDDSFile(const osg::Image *img, std::ostream& fout)
break;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
{
isDXTC = true;
ddpf.dwFourCC = FOURCC_DXT1;
PF_flags |= DDPF_FOURCC; /* No alpha here */
ddsd.dwLinearSize = imageSize;
@@ -1247,9 +1264,9 @@ bool WriteDDSFile(const osg::Image *img, std::ostream& fout)
OSG_INFO<<"no mipmaps to write out."<<std::endl;
} else if( img->getPacking() > 1 ) {
//} else if( img->getPacking() > 1 ) {
OSG_WARN<<"Warning: mipmaps not written. DDS requires packing == 1."<<std::endl;
// OSG_WARN<<"Warning: mipmaps not written. DDS requires packing == 1."<<std::endl;
} else { // image contains mipmaps and has 1 byte alignment
@@ -1270,11 +1287,32 @@ bool WriteDDSFile(const osg::Image *img, std::ostream& fout)
ddsd.ddpfPixelFormat = ddpf;
ddsd.ddsCaps = ddsCaps;
osg::ref_ptr<const osg::Image> source;
if (autoFlipDDSWrite && img->getOrigin() == osg::Image::BOTTOM_LEFT)
{
osg::ref_ptr<osg::Image> copy( new osg::Image(*img,osg::CopyOp::DEEP_COPY_ALL) );
const int s(copy->s());
const int t(copy->t());
if (!isDXTC || ((s>4 && s%4==0 && t>4 && t%4==0) || s<4)) // Flip may crash (access violation) or fail for non %4 dimensions (except for s<4). Tested with revision trunk 2013-02-22.
{
copy->flipVertical();
}
else
{
OSG_WARN << "WriteDDSFile warning: Vertical flip was skipped. Image dimensions have to be multiple of 4." << std::endl;
}
source = copy;
}
else
{
source = img;
}
// Write DDS file
fout.write("DDS ", 4); /* write FOURCC */
fout.write(reinterpret_cast<char*>(&ddsd), sizeof(ddsd)); /* write file header */
for(osg::Image::DataIterator itr(img); itr.valid(); ++itr)
for(osg::Image::DataIterator itr(source.get()); itr.valid(); ++itr)
{
fout.write(reinterpret_cast<const char*>(itr.data()), itr.size() );
}
@@ -1298,7 +1336,8 @@ public:
supportsOption("dds_dxt1_rgb","Set the pixel format of DXT1 encoded images to be RGB variant of DXT1");
supportsOption("dds_dxt1_rgba","Set the pixel format of DXT1 encoded images to be RGBA variant of DXT1");
supportsOption("dds_dxt1_detect_rgba","For DXT1 encode images set the pixel format according to presence of transparent pixels");
supportsOption("dds_flip","Flip the image about the horizontl axis");
supportsOption("dds_flip","Flip the image about the horizontal axis");
supportsOption("ddsNoAutoFlipWrite", "(Write option) Avoid automatically flipping the image vertically when writing, depending on the origin (Image::getOrigin()).");
}
virtual const char* className() const
@@ -1334,23 +1373,39 @@ public:
virtual ReadResult readImage(std::istream& fin, const Options* options) const
{
osg::Image* osgImage = ReadDDSFile(fin);
bool dds_flip(false);
bool dds_dxt1_rgba(false);
bool dds_dxt1_rgb(false);
bool dds_dxt1_detect_rgba(false);
if (options)
{
std::istringstream iss(options->getOptionString());
std::string opt;
while (iss >> opt)
{
if (opt == "dds_flip") dds_flip = true;
if (opt == "dds_dxt1_rgba") dds_dxt1_rgba = true;
if (opt == "dds_dxt1_rgb") dds_dxt1_rgb = true;
if (opt == "dds_dxt1_detect_rgba") dds_dxt1_detect_rgba = true;
}
}
osg::Image* osgImage = ReadDDSFile(fin, dds_flip);
if (osgImage==NULL) return ReadResult::FILE_NOT_HANDLED;
if (osgImage->getPixelFormat()==GL_COMPRESSED_RGB_S3TC_DXT1_EXT ||
osgImage->getPixelFormat()==GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
{
if (options && options->getOptionString().find("dds_dxt1_rgba")!=std::string::npos)
if (dds_dxt1_rgba)
{
osgImage->setPixelFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
osgImage->setInternalTextureFormat(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
}
else if (options && options->getOptionString().find("dds_dxt1_rgb")!=std::string::npos)
else if (dds_dxt1_rgb)
{
osgImage->setPixelFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
osgImage->setInternalTextureFormat(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
}
else if (options && options->getOptionString().find("dds_dxt1_detect_rgba")!=std::string::npos)
else if (dds_dxt1_detect_rgba)
{
// check to see if DXT1c (RGB_S3TC_DXT1) format image might actually be
// a DXT1a format image
@@ -1375,11 +1430,6 @@ public:
}
}
if (options && options->getOptionString().find("dds_flip")!=std::string::npos)
{
osgImage->flipVertical();
}
return osgImage;
}
@@ -1411,9 +1461,10 @@ public:
return writeImage(image,fout,options);
}
virtual WriteResult writeImage(const osg::Image& image,std::ostream& fout,const Options*) const
virtual WriteResult writeImage(const osg::Image& image,std::ostream& fout,const Options* options) const
{
bool success = WriteDDSFile(&image, fout);
bool noAutoFlipDDSWrite = options && options->getOptionString().find("ddsNoAutoFlipWrite")!=std::string::npos;
bool success = WriteDDSFile(&image, fout, !noAutoFlipDDSWrite);
if(success)
return WriteResult::FILE_SAVED;