mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 23:23:52 +00:00
ESSImporter image conversions port to osg::Image
This commit is contained in:
parent
2eec0caca0
commit
364b785e8f
3 changed files with 95 additions and 35 deletions
|
@ -5,6 +5,8 @@
|
||||||
#include <OgreImage.h>
|
#include <OgreImage.h>
|
||||||
#include <OgreColourValue.h>
|
#include <OgreColourValue.h>
|
||||||
|
|
||||||
|
#include <osgDB/WriteFile>
|
||||||
|
|
||||||
#include <components/esm/creaturestate.hpp>
|
#include <components/esm/creaturestate.hpp>
|
||||||
#include <components/esm/containerstate.hpp>
|
#include <components/esm/containerstate.hpp>
|
||||||
|
|
||||||
|
@ -15,12 +17,14 @@
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
void convertImage(char* data, int size, int width, int height, Ogre::PixelFormat pf, const std::string& out)
|
void convertImage(char* data, int size, int width, int height, GLenum pf, const std::string& out)
|
||||||
{
|
{
|
||||||
Ogre::Image screenshot;
|
osg::ref_ptr<osg::Image> image (new osg::Image);
|
||||||
Ogre::DataStreamPtr stream (new Ogre::MemoryDataStream(data, size));
|
image->allocateImage(width, height, 1, pf, GL_UNSIGNED_BYTE);
|
||||||
screenshot.loadRawData(stream, width, height, 1, pf);
|
memcpy(image->data(), data, size);
|
||||||
screenshot.save(out);
|
image->flipVertical();
|
||||||
|
|
||||||
|
osgDB::writeImageFile(*image, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,17 +75,20 @@ namespace ESSImport
|
||||||
data.resize(esm.getSubSize());
|
data.resize(esm.getSubSize());
|
||||||
esm.getExact(&data[0], data.size());
|
esm.getExact(&data[0], data.size());
|
||||||
|
|
||||||
Ogre::DataStreamPtr stream (new Ogre::MemoryDataStream(&data[0], data.size()));
|
mGlobalMapImage = new osg::Image;
|
||||||
mGlobalMapImage.loadRawData(stream, maph.size, maph.size, 1, Ogre::PF_BYTE_RGB);
|
mGlobalMapImage->allocateImage(maph.size, maph.size, 1, GL_RGB, GL_UNSIGNED_BYTE);
|
||||||
|
memcpy(mGlobalMapImage->data(), &data[0], data.size());
|
||||||
|
|
||||||
// to match openmw size
|
// to match openmw size
|
||||||
mGlobalMapImage.resize(maph.size*2, maph.size*2, Ogre::Image::FILTER_BILINEAR);
|
// FIXME: filtering?
|
||||||
|
mGlobalMapImage->scaleImage(maph.size*2, maph.size*2, 1, GL_UNSIGNED_BYTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConvertFMAP::write(ESM::ESMWriter &esm)
|
void ConvertFMAP::write(ESM::ESMWriter &esm)
|
||||||
{
|
{
|
||||||
int numcells = mGlobalMapImage.getWidth() / 18; // NB truncating, doesn't divide perfectly
|
int numcells = mGlobalMapImage->s() / 18; // NB truncating, doesn't divide perfectly
|
||||||
// with the 512x512 map the game has by default
|
// with the 512x512 map the game has by default
|
||||||
int cellSize = mGlobalMapImage.getWidth()/numcells;
|
int cellSize = mGlobalMapImage->s()/numcells;
|
||||||
|
|
||||||
// Note the upper left corner of the (0,0) cell should be at (width/2, height/2)
|
// Note the upper left corner of the (0,0) cell should be at (width/2, height/2)
|
||||||
|
|
||||||
|
@ -90,12 +97,14 @@ namespace ESSImport
|
||||||
mContext->mGlobalMapState.mBounds.mMinY = -(numcells-1)/2;
|
mContext->mGlobalMapState.mBounds.mMinY = -(numcells-1)/2;
|
||||||
mContext->mGlobalMapState.mBounds.mMaxY = numcells/2;
|
mContext->mGlobalMapState.mBounds.mMaxY = numcells/2;
|
||||||
|
|
||||||
Ogre::Image image2;
|
osg::ref_ptr<osg::Image> image2 (new osg::Image);
|
||||||
std::vector<Ogre::uint8> data;
|
|
||||||
int width = cellSize*numcells;
|
int width = cellSize*numcells;
|
||||||
int height = cellSize*numcells;
|
int height = cellSize*numcells;
|
||||||
|
std::vector<unsigned char> data;
|
||||||
data.resize(width*height*4, 0);
|
data.resize(width*height*4, 0);
|
||||||
image2.loadDynamicImage(&data[0], width, height, Ogre::PF_BYTE_RGBA);
|
|
||||||
|
image2->allocateImage(width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||||
|
memcpy(image2->data(), &data[0], data.size());
|
||||||
|
|
||||||
for (std::set<std::pair<int, int> >::const_iterator it = mContext->mExploredCells.begin(); it != mContext->mExploredCells.end(); ++it)
|
for (std::set<std::pair<int, int> >::const_iterator it = mContext->mExploredCells.begin(); it != mContext->mExploredCells.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -108,8 +117,8 @@ namespace ESSImport
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int imageLeftSrc = mGlobalMapImage.getWidth()/2;
|
int imageLeftSrc = mGlobalMapImage->s()/2;
|
||||||
int imageTopSrc = mGlobalMapImage.getHeight()/2;
|
int imageTopSrc = mGlobalMapImage->t()/2;
|
||||||
imageLeftSrc += it->first * cellSize;
|
imageLeftSrc += it->first * cellSize;
|
||||||
imageTopSrc -= it->second * cellSize;
|
imageTopSrc -= it->second * cellSize;
|
||||||
int imageLeftDst = width/2;
|
int imageLeftDst = width/2;
|
||||||
|
@ -118,13 +127,31 @@ namespace ESSImport
|
||||||
imageTopDst -= it->second * cellSize;
|
imageTopDst -= it->second * cellSize;
|
||||||
for (int x=0; x<cellSize; ++x)
|
for (int x=0; x<cellSize; ++x)
|
||||||
for (int y=0; y<cellSize; ++y)
|
for (int y=0; y<cellSize; ++y)
|
||||||
image2.setColourAt(mGlobalMapImage.getColourAt(imageLeftSrc+x, imageTopSrc+y, 0)
|
{
|
||||||
, imageLeftDst+x, imageTopDst+y, 0);
|
unsigned int col = *(unsigned int*)mGlobalMapImage->data(imageLeftSrc+x, imageTopSrc+y, 0);
|
||||||
|
*(unsigned int*)image2->data(imageLeftDst+x, imageTopDst+y, 0) = col;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ogre::DataStreamPtr encoded = image2.encode("png");
|
std::stringstream ostream;
|
||||||
mContext->mGlobalMapState.mImageData.resize(encoded->size());
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("png");
|
||||||
encoded->read(&mContext->mGlobalMapState.mImageData[0], encoded->size());
|
if (!readerwriter)
|
||||||
|
{
|
||||||
|
std::cerr << "can't write global map image, no png readerwriter found" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
image2->flipVertical();
|
||||||
|
|
||||||
|
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image2, ostream);
|
||||||
|
if (!result.success())
|
||||||
|
{
|
||||||
|
std::cerr << "can't write global map image: " << result.message() << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string outData = ostream.str();
|
||||||
|
mContext->mGlobalMapState.mImageData = std::vector<char>(outData.begin(), outData.end());
|
||||||
|
|
||||||
esm.startRecord(ESM::REC_GMAP);
|
esm.startRecord(ESM::REC_GMAP);
|
||||||
mContext->mGlobalMapState.save(esm);
|
mContext->mGlobalMapState.save(esm);
|
||||||
|
@ -194,7 +221,7 @@ namespace ESSImport
|
||||||
std::ostringstream filename;
|
std::ostringstream filename;
|
||||||
filename << "fog_" << cell.mData.mX << "_" << cell.mData.mY << ".tga";
|
filename << "fog_" << cell.mData.mX << "_" << cell.mData.mY << ".tga";
|
||||||
|
|
||||||
convertImage((char*)&newcell.mFogOfWar[0], newcell.mFogOfWar.size()*4, 16, 16, Ogre::PF_BYTE_RGBA, filename.str());
|
convertImage((char*)&newcell.mFogOfWar[0], newcell.mFogOfWar.size()*4, 16, 16, GL_RGBA, filename.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#ifndef OPENMW_ESSIMPORT_CONVERTER_H
|
#ifndef OPENMW_ESSIMPORT_CONVERTER_H
|
||||||
#define OPENMW_ESSIMPORT_CONVERTER_H
|
#define OPENMW_ESSIMPORT_CONVERTER_H
|
||||||
|
|
||||||
#include <OgreImage.h>
|
#include <osg/Image>
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
@ -311,7 +312,7 @@ public:
|
||||||
virtual void write(ESM::ESMWriter &esm);
|
virtual void write(ESM::ESMWriter &esm);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ogre::Image mGlobalMapImage;
|
osg::ref_ptr<osg::Image> mGlobalMapImage;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConvertCell : public Converter
|
class ConvertCell : public Converter
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "importer.hpp"
|
#include "importer.hpp"
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
#include <OgreRoot.h>
|
#include <osgDB/ReadFile>
|
||||||
|
#include <osg/ImageUtils>
|
||||||
|
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
@ -32,13 +33,48 @@ namespace
|
||||||
|
|
||||||
void writeScreenshot(const ESM::Header& fileHeader, ESM::SavedGame& out)
|
void writeScreenshot(const ESM::Header& fileHeader, ESM::SavedGame& out)
|
||||||
{
|
{
|
||||||
Ogre::Image screenshot;
|
if (fileHeader.mSCRS.size() != 128*128*4)
|
||||||
std::vector<unsigned char> screenshotData = fileHeader.mSCRS; // MemoryDataStream doesn't work with const data :(
|
{
|
||||||
Ogre::DataStreamPtr screenshotStream (new Ogre::MemoryDataStream(&screenshotData[0], screenshotData.size()));
|
std::cerr << "unexpected screenshot size " << std::endl;
|
||||||
screenshot.loadRawData(screenshotStream, 128, 128, 1, Ogre::PF_BYTE_BGRA);
|
return;
|
||||||
Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
|
}
|
||||||
out.mScreenshot.resize(encoded->size());
|
|
||||||
encoded->read(&out.mScreenshot[0], encoded->size());
|
osg::ref_ptr<osg::Image> image (new osg::Image);
|
||||||
|
image->allocateImage(128, 128, 1, GL_RGB, GL_UNSIGNED_BYTE);
|
||||||
|
|
||||||
|
// need to convert pixel format from BGRA to RGB as the jpg readerwriter doesn't support it otherwise
|
||||||
|
std::vector<unsigned char>::const_iterator it = fileHeader.mSCRS.begin();
|
||||||
|
for (int y=0; y<128; ++y)
|
||||||
|
{
|
||||||
|
for (int x=0; x<128; ++x)
|
||||||
|
{
|
||||||
|
*(image->data(x,y)+2) = *it++;
|
||||||
|
*(image->data(x,y)+1) = *it++;
|
||||||
|
*image->data(x,y) = *it++;
|
||||||
|
it++; // skip alpha
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
image->flipVertical();
|
||||||
|
|
||||||
|
std::stringstream ostream;
|
||||||
|
|
||||||
|
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg");
|
||||||
|
if (!readerwriter)
|
||||||
|
{
|
||||||
|
std::cerr << "can't write screenshot: no jpg readerwriter found" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*image, ostream);
|
||||||
|
if (!result.success())
|
||||||
|
{
|
||||||
|
std::cerr << "can't write screenshot: " << result.message() << " code " << result.status() << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string data = ostream.str();
|
||||||
|
out.mScreenshot = std::vector<char>(data.begin(), data.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -203,10 +239,6 @@ namespace ESSImport
|
||||||
|
|
||||||
void Importer::run()
|
void Importer::run()
|
||||||
{
|
{
|
||||||
// construct Ogre::Root to gain access to image codecs
|
|
||||||
Ogre::LogManager logman;
|
|
||||||
Ogre::Root root;
|
|
||||||
|
|
||||||
ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding));
|
ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding));
|
||||||
ESM::ESMReader esm;
|
ESM::ESMReader esm;
|
||||||
esm.open(mEssFile);
|
esm.open(mEssFile);
|
||||||
|
|
Loading…
Reference in a new issue