Skip to content

Commit

Permalink
Refactor: Moved image file interpretation to resource/image.cpp
Browse files Browse the repository at this point in the history
Plus some minor cleanup.
  • Loading branch information
danij-deng committed Mar 1, 2013
1 parent 740c378 commit d8530d9
Show file tree
Hide file tree
Showing 4 changed files with 236 additions and 225 deletions.
4 changes: 0 additions & 4 deletions doomsday/client/include/de_graphics.h
Expand Up @@ -34,8 +34,4 @@
# include "gl/gl_texmanager.h"
#endif

#include "resource/pcx.h"
#include "resource/tga.h"
#include "resource/hq2x.h"

#endif /* LIBDENG_GRAPHICS */
41 changes: 21 additions & 20 deletions doomsday/client/src/gl/gl_tex.cpp
Expand Up @@ -1505,31 +1505,31 @@ void SharpenPixels(uint8_t* pixels, int width, int height, int comps)
/**
* @return @c true, if the given color is either (0,255,255) or (255,0,255).
*/
static __inline boolean ColorKey(uint8_t* color)
static inline bool isKeyedColor(uint8_t *color)
{
assert(color);
DENG2_ASSERT(color);
return color[CB] == 0xff && ((color[CR] == 0xff && color[CG] == 0) ||
(color[CR] == 0 && color[CG] == 0xff));
}

/**
* Buffer must be RGBA. Doesn't touch the non-keyed pixels.
*/
static void DoColorKeying(uint8_t* rgbaBuf, int width)
static void doColorKeying(uint8_t *rgbaBuf, int width)
{
assert(rgbaBuf);
{ int i;
for(i = 0; i < width; ++i, rgbaBuf += 4)
DENG2_ASSERT(rgbaBuf);

for(int i = 0; i < width; ++i, rgbaBuf += 4)
{
if(!ColorKey(rgbaBuf))
continue;
if(!isKeyedColor(rgbaBuf)) continue;

rgbaBuf[3] = rgbaBuf[2] = rgbaBuf[1] = rgbaBuf[0] = 0;
}}
}
}

uint8_t* ApplyColorKeying(uint8_t* buf, int width, int height, int pixelSize)
uint8_t *ApplyColorKeying(uint8_t *buf, int width, int height, int pixelSize)
{
assert(buf);
DENG2_ASSERT(buf);

if(width <= 0 || height <= 0)
return buf;
Expand All @@ -1538,29 +1538,30 @@ uint8_t* ApplyColorKeying(uint8_t* buf, int width, int height, int pixelSize)
// required number of color components.
if(pixelSize < 4)
{
const long numpels = width * height;
uint8_t* ckdest = (uint8_t *) M_Malloc(4 * numpels);
uint8_t* in, *out;
long const numpels = width * height;
uint8_t *ckdest = (uint8_t *) M_Malloc(4 * numpels);
uint8_t *in, *out;
long i;

for(in = buf, out = ckdest, i = 0; i < numpels; ++i, in += pixelSize, out += 4)
{
if(ColorKey(in))
if(isKeyedColor(in))
{
memset(out, 0, 4); // Totally black.
std::memset(out, 0, 4); // Totally black.
continue;
}

memcpy(out, in, 3); // The color itself.
std::memcpy(out, in, 3); // The color itself.
out[CA] = 255; // Opaque.
}
return ckdest;
}

// We can do the keying in-buffer.
// This preserves the alpha values of non-keyed pixels.
{ int i;
for(i = 0; i < height; ++i)
DoColorKeying(buf + 4 * i * width, height);
for(int i = 0; i < height; ++i)
{
doColorKeying(buf + 4 * i * width, height);
}
return buf;
}
157 changes: 1 addition & 156 deletions doomsday/client/src/gl/gl_texmanager.cpp
Expand Up @@ -41,6 +41,7 @@
#include "de_ui.h"

#include "def_main.h"
#include "resource/hq2x.h"

#include <QSize>
#include <de/ByteRefArray>
Expand All @@ -62,19 +63,6 @@ enum uploadcontentmethod_t
METHOD_DEFERRED
};

struct GraphicFileType
{
/// Symbolic name of the resource type.
String name;

/// Known file extension.
String ext;

bool (*interpretFunc)(de::FileHandle &hndl, String filePath, image_t &img);

char const *(*getLastErrorFunc)(); ///< Can be NULL.
};

struct texturevariantspecificationlist_node_t
{
texturevariantspecificationlist_node_t *next;
Expand All @@ -94,11 +82,6 @@ void GL_DoUpdateTexParams();

static int hashDetailVariantSpecification(detailvariantspecification_t const &spec);

static bool interpretPcx(de::FileHandle &hndl, String filePath, image_t &img);
static bool interpretPng(de::FileHandle &hndl, String filePath, image_t &img);
static bool interpretJpg(de::FileHandle &hndl, String filePath, image_t &img);
static bool interpretTga(de::FileHandle &hndl, String filePath, image_t &img);

static TexSource loadExternalTexture(image_t &image, String searchPath, String optionalSuffix = "");

static TexSource loadFlat(image_t &image, de::FileHandle &file);
Expand Down Expand Up @@ -141,15 +124,6 @@ DGLuint sysFlareTextures[NUM_SYSFLARE_TEXTURES];

static boolean initedOk = false; // Init done.

// Graphic resource types.
static GraphicFileType const graphicTypes[] = {
{ "PNG", "png", interpretPng, 0 },
{ "JPG", "jpg", interpretJpg, 0 }, // TODO: add alternate "jpeg" extension
{ "TGA", "tga", interpretTga, TGA_LastError },
{ "PCX", "pcx", interpretPcx, PCX_LastError },
{ "", "", 0, 0 } // Terminate.
};

static variantspecificationlist_t *variantSpecs;

/// @c TST_DETAIL type specifications are stored separately into a set of
Expand Down Expand Up @@ -1312,135 +1286,6 @@ void GL_PruneTextureVariantSpecifications()
#endif
}

static bool interpretPcx(de::FileHandle &hndl, String /*filePath*/, image_t &img)
{
Image_Init(&img);
img.pixels = PCX_Load(reinterpret_cast<filehandle_s *>(&hndl),
&img.size.width, &img.size.height, &img.pixelSize);
return (0 != img.pixels);
}

static bool interpretJpg(de::FileHandle &hndl, String /*filePath*/, image_t &img)
{
return Image_LoadFromFileWithFormat(&img, "JPG", reinterpret_cast<filehandle_s *>(&hndl));
}

static bool interpretPng(de::FileHandle &hndl, String /*filePath*/, image_t &img)
{
/*
Image_Init(&img);
img.pixels = PNG_Load(reinterpret_cast<filehandle_s *>(&hndl),
&img.size.width, &img.size.height, &img.pixelSize);
return (0 != img.pixels);
*/
return Image_LoadFromFileWithFormat(&img, "PNG", reinterpret_cast<filehandle_s *>(&hndl));
}

static bool interpretTga(de::FileHandle &hndl, String /*filePath*/, image_t &img)
{
Image_Init(&img);
img.pixels = TGA_Load(reinterpret_cast<filehandle_s *>(&hndl),
&img.size.width, &img.size.height, &img.pixelSize);
return (0 != img.pixels);
}

GraphicFileType const *guessGraphicFileTypeFromFileName(String fileName)
{
// The path must have an extension for this.
String ext = fileName.fileNameExtension();
if(!ext.isEmpty())
{
for(int i = 0; !graphicTypes[i].ext.isEmpty(); ++i)
{
GraphicFileType const &type = graphicTypes[i];
if(!ext.compareWithoutCase(type.ext))
{
return &type;
}
}
}
return 0; // Unknown.
}

static void interpretGraphic(de::FileHandle &hndl, String filePath, image_t &img)
{
// Firstly try the interpreter for the guessed resource types.
GraphicFileType const *rtypeGuess = guessGraphicFileTypeFromFileName(filePath);
if(rtypeGuess)
{
rtypeGuess->interpretFunc(hndl, filePath, img);
}

// If not yet interpreted - try each recognisable format in order.
if(!img.pixels)
{
// Try each recognisable format instead.
/// @todo Order here should be determined by the resource locator.
for(int i = 0; !graphicTypes[i].name.isEmpty(); ++i)
{
GraphicFileType const *graphicType = &graphicTypes[i];

// Already tried this?
if(graphicType == rtypeGuess) continue;

graphicTypes[i].interpretFunc(hndl, filePath, img);
if(img.pixels) break;
}
}
}

/// @return @c true if the file name in @a path ends with the "color key" suffix.
static inline bool isColorKeyed(String path)
{
return path.fileNameWithoutExtension().endsWith("-ck", Qt::CaseInsensitive);
}

uint8_t *Image_LoadFromFile(image_t *img, filehandle_s *_file)
{
DENG_ASSERT(img && _file);
de::FileHandle &file = reinterpret_cast<de::FileHandle &>(*_file);
LOG_AS("Image_LoadFromFile");

String filePath = file.file().composePath();

Image_Init(img);
interpretGraphic(file, filePath, *img);

// Still not interpreted?
if(!img->pixels)
{
LOG_VERBOSE("\"%s\" unrecognized, trying fallback loader...")
<< NativePath(filePath).pretty();
return NULL; // Not a recognised format. It may still be loadable, however.
}

// How about some color-keying?
if(isColorKeyed(filePath))
{
uint8_t *out = ApplyColorKeying(img->pixels, img->size.width, img->size.height, img->pixelSize);
if(out != img->pixels)
{
// Had to allocate a larger buffer, free the old and attach the new.
M_Free(img->pixels);
img->pixels = out;
}

// Color keying is done; now we have 4 bytes per pixel.
img->pixelSize = 4;
}

// Any alpha pixels?
if(Image_HasAlpha(img))
{
img->flags |= IMGF_IS_MASKED;
}

LOG_VERBOSE("\"%s\" (%ix%i)")
<< NativePath(filePath).pretty() << img->size.width << img->size.height;

return img->pixels;
}

uint8_t *GL_LoadImage(image_t &image, String nativePath)
{
try
Expand Down

0 comments on commit d8530d9

Please sign in to comment.