Skip to content
Permalink
Browse files

cp Bitmap::SaveGrayScale

  • Loading branch information...
rt
rt committed Apr 27, 2019
1 parent 8fcb659 commit 74c6b47a9c774bd32f4cc729c7f52369026842f4
Showing with 46 additions and 19 deletions.
  1. +8 −9 rts/Lua/LuaOpenGL.cpp
  2. +34 −8 rts/Rendering/Textures/Bitmap.cpp
  3. +4 −2 rts/Rendering/Textures/Bitmap.h
@@ -4287,7 +4287,7 @@ int LuaOpenGL::SaveImage(lua_State* L)
return 0;
}

GLenum curReadBuffer = 0;
GLenum curReadBuffer = 0;
GLenum tgtReadBuffer = 0;

bool alpha = false;
@@ -4322,17 +4322,16 @@ int LuaOpenGL::SaveImage(lua_State* L)
CBitmap bitmap;
bitmap.Alloc(width, height);

glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.GetRawMem());

if (yflip)
bitmap.ReverseYAxis();

if (!gs16b) {
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.GetRawMem());
if (yflip)
bitmap.ReverseYAxis();
lua_pushboolean(L, bitmap.Save(filename, !alpha));
} else {
// single channel only!
glReadPixels(x, y, width, height, GL_LUMINANCE, GL_FLOAT, bitmap.GetRawMem());
if (yflip)
bitmap.ReverseYAxis();
lua_pushboolean(L, bitmap.SaveFloat(filename));
// always saves as 16-bit image
lua_pushboolean(L, bitmap.SaveGrayScale(filename));
}

if (tgtReadBuffer != 0)
@@ -727,27 +727,53 @@ bool CBitmap::Save(std::string const& filename, bool opaque, bool logged) const
}


bool CBitmap::SaveGrayScale(const std::string& filename) const
{
if (compressed)
return false;

CBitmap bmp = *this;

for (uint8_t* mem = bmp.GetRawMem(); mem != nullptr; mem = nullptr) {
// approximate luminance
bmp.MakeGrayScale();

// convert RGBA tuples to normalized FLT32 values expected by SaveFloat; GBA are destroyed
for (int y = 0; y < ysize; ++y) {
for (int x = 0; x < xsize; ++x) {
*reinterpret_cast<float*>(&mem[(y * xsize + x) * 4]) = static_cast<float>(mem[(y * xsize + x) * 4 + 0] / 255.0f);
}
}

// save FLT32 data in 16-bit ushort format
return (bmp.SaveFloat(filename));
}

return false;
}


bool CBitmap::SaveFloat(std::string const& filename) const
{
// small hack: we read the RGBA pack as a single FLT32 value!
// must have four channels; each RGBA tuple is reinterpreted as a single FLT32 value
if (GetMemSize() == 0 || channels != 4)
return false;

std::lock_guard<spring::mutex> lck(texMemPool.GetMutex());

// seems IL_ORIGIN_SET only works in ilLoad and not in ilTexImage nor in ilSaveImage
// so we need to flip the image ourselves
const uint8_t* mem = GetRawMem();
const float* memf = reinterpret_cast<const float*>(&mem[0]);
const uint8_t* u8mem = GetRawMem();
const float* f32mem = reinterpret_cast<const float*>(&u8mem[0]);

uint16_t* buf = reinterpret_cast<uint16_t*>(texMemPool.AllocRaw(xsize * ysize * sizeof(uint16_t)));
uint16_t* u16mem = reinterpret_cast<uint16_t*>(texMemPool.AllocRaw(xsize * ysize * sizeof(uint16_t)));

for (int y = 0; y < ysize; ++y) {
for (int x = 0; x < xsize; ++x) {
const int bi = x + (xsize * ((ysize - 1) - y));
const int mi = x + (xsize * ( y));
const uint16_t us = memf[mi] * 0xFFFF; // convert float 0..1 to ushort
buf[bi] = us;
const uint16_t us = f32mem[mi] * 0xFFFF; // convert float 0..1 to ushort
u16mem[bi] = us;
}
}

@@ -759,9 +785,9 @@ bool CBitmap::SaveFloat(std::string const& filename) const
ilBindImage(imageID);
// note: DevIL only generates a 16bit grayscale PNG when format is IL_UNSIGNED_SHORT!
// IL_FLOAT is converted to RGB with 8bit colordepth!
ilTexImage(xsize, ysize, 1, 1, IL_LUMINANCE, IL_UNSIGNED_SHORT, buf);
ilTexImage(xsize, ysize, 1, 1, IL_LUMINANCE, IL_UNSIGNED_SHORT, u16mem);

texMemPool.FreeRaw(reinterpret_cast<uint8_t*>(buf), xsize * ysize * sizeof(uint16_t));
texMemPool.FreeRaw(reinterpret_cast<uint8_t*>(u16mem), xsize * ysize * sizeof(uint16_t));


const std::string& fsImageExt = FileSystem::GetExtension(filename);
@@ -39,8 +39,10 @@ class CBitmap {
bool Load(std::string const& filename, uint8_t defaultAlpha = 255);
/// Load data from a gray-scale file on the VFS
bool LoadGrayscale(std::string const& filename);
bool Save(std::string const& filename, bool opaque = true, bool logged = false) const;
bool SaveFloat(std::string const& filename) const;

bool Save(const std::string& filename, bool opaque = true, bool logged = false) const;
bool SaveGrayScale(const std::string& filename) const;
bool SaveFloat(const std::string& filename) const;

bool Empty() const { return (memIdx == size_t(-1)); } // implies size=0

0 comments on commit 74c6b47

Please sign in to comment.
You can’t perform that action at this time.