Added sharedImage library

This commit is contained in:
Anonymous
2014-01-14 11:00:06 -07:00
parent 9f0f8a8059
commit 44a0133745
27 changed files with 3316 additions and 0 deletions
+1
View File
@@ -7,6 +7,7 @@ add_subdirectory(sharedFoundation)
add_subdirectory(sharedFoundationTypes)
add_subdirectory(sharedFractal)
add_subdirectory(sharedGame)
add_subdirectory(sharedImage)
add_subdirectory(sharedLog)
add_subdirectory(sharedMath)
add_subdirectory(sharedMathArchive)
@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 2.8)
project(sharedImage)
if(WIN32)
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public)
add_subdirectory(src)
@@ -0,0 +1 @@
#include "../../src/shared/ConfigSharedImage.h"
@@ -0,0 +1 @@
#include "../../src/shared/FirstSharedImage.h"
@@ -0,0 +1 @@
#include "../../src/shared/Image.h"
@@ -0,0 +1 @@
#include "../../src/shared/ImageFormat.h"
@@ -0,0 +1 @@
#include "../../src/shared/ImageFormatList.h"
@@ -0,0 +1 @@
#include "../../src/shared/ImageManipulation.h"
@@ -0,0 +1 @@
#include "../../src/shared/SetupSharedImage.h"
@@ -0,0 +1 @@
#include "../../src/shared/TargaFormat.h"
@@ -0,0 +1,43 @@
set(SHARED_SOURCES
shared/FirstSharedImage.h
shared/ConfigSharedImage.cpp
shared/ConfigSharedImage.h
shared/Image.cpp
shared/ImageFormat.cpp
shared/ImageFormat.h
shared/ImageFormatList.cpp
shared/ImageFormatList.h
shared/Image.h
shared/ImageManipulation.cpp
shared/ImageManipulation.h
shared/SetupSharedImage.cpp
shared/SetupSharedImage.h
shared/TargaFormat.cpp
shared/TargaFormat.h
)
if(WIN32)
set(PLATFORM_SOURCES
win32/FirstSharedImage.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
else()
set(PLATFORM_SOURCES "")
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/shared
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
)
add_library(sharedImage STATIC
${SHARED_SOURCES}
${PLATFORM_SOURCES}
)
@@ -0,0 +1,42 @@
// ======================================================================
//
// ConfigSharedImage.cpp
// copyright 2004 Sony Online Entertainment
//
// ======================================================================
#include "sharedImage/FirstSharedImage.h"
#include "sharedImage/ConfigSharedImage.h"
#include "sharedFoundation/ConfigFile.h"
// ======================================================================
#define KEY_BOOL(a,b) (ms_ ## a = ConfigFile::getKeyBool("SharedImage", #a, (b)))
// ======================================================================
namespace ConfigSharedImageNamespace
{
bool ms_sample;
}
using namespace ConfigSharedImageNamespace;
// ======================================================================
void ConfigSharedImage::install()
{
KEY_BOOL(sample, false);
}
// ----------------------------------------------------------------------
bool ConfigSharedImage::getSample()
{
return ms_sample;
}
// ======================================================================
@@ -0,0 +1,24 @@
// ======================================================================
//
// ConfigSharedImage.h
// Copyright 2004, Sony Online Entertainment Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_ConfigSharedImage_H
#define INCLUDED_ConfigSharedImage_H
// ======================================================================
class ConfigSharedImage
{
public:
static void install();
static bool getSample();
};
// ======================================================================
#endif
@@ -0,0 +1,17 @@
// ======================================================================
//
// FirstImage.h
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_FirstImage_H
#define INCLUDED_FirstImage_H
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
// ======================================================================
#endif
@@ -0,0 +1,299 @@
// ======================================================================
//
// Image.cpp
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedImage/FirstSharedImage.h"
#include "sharedImage/Image.h"
#include "sharedFoundation/Crc.h"
// ======================================================================
// lint supression
// ======================================================================
//lint -e1734 // info -- had difficulty compiling template function // maybe bug in lint?
// ======================================================================
// class Image non-static member functions
// ======================================================================
Image::Image()
: m_width(0),
m_height(0),
m_bitsPerPixel(0),
m_bytesPerPixel(0),
m_stride(0),
m_redMask(0),
m_greenMask(0),
m_blueMask(0),
m_alphaMask(0),
m_ownBuffer(true),
m_buffer(0),
m_bufferSize(0),
m_readOnly(false),
m_isLocked(false),
m_formatDirty(true),
m_format(PF_nonStandard)
{
}
// ----------------------------------------------------------------------
Image::Image(uint8 *pixelBuffer, int pixelBufferSize, int width, int height, int bitsPerPixel, int bytesPerPixel, int strideInBytes, uint redMask, uint greenMask, uint blueMask, uint alphaMask)
: m_width(width),
m_height(height),
m_bitsPerPixel(bitsPerPixel),
m_bytesPerPixel(bytesPerPixel),
m_stride(strideInBytes),
m_redMask(redMask),
m_greenMask(greenMask),
m_blueMask(blueMask),
m_alphaMask(alphaMask),
m_ownBuffer(false),
m_buffer(pixelBuffer),
m_bufferSize(pixelBufferSize),
m_readOnly(false),
m_isLocked(false),
m_formatDirty(true),
m_format(PF_nonStandard)
{
}
// ----------------------------------------------------------------------
Image::~Image()
{
if (m_ownBuffer)
delete [] m_buffer;
else
m_buffer = 0;
}
// ----------------------------------------------------------------------
void Image::setDimensions(int width, int height, int bitsPerPixel, int bytesPerPixel)
{
VALIDATE_RANGE_INCLUSIVE_INCLUSIVE(1, bitsPerPixel, 32);
VALIDATE_RANGE_INCLUSIVE_INCLUSIVE(1, bytesPerPixel, 4);
DEBUG_FATAL( ((static_cast<uint>(bitsPerPixel)+7)>>3) > static_cast<uint>(bytesPerPixel), ("invalid bytesPerPixel set, %d bytes with %d bits\n", bytesPerPixel, bitsPerPixel));
FATAL(m_isLocked, ("image is locked"));
//-- calculate default stride
const int stride = bytesPerPixel * width;
//-- set the dimensions
setDimensions(width, height, bitsPerPixel, bytesPerPixel, stride);
}
// ----------------------------------------------------------------------
void Image::setDimensions(int width, int height, int bitsPerPixel, int bytesPerPixel, int strideInBytes)
{
VALIDATE_RANGE_INCLUSIVE_INCLUSIVE(1, bitsPerPixel, 32);
VALIDATE_RANGE_INCLUSIVE_INCLUSIVE(1, bytesPerPixel, 4);
DEBUG_FATAL( ((static_cast<uint>(bitsPerPixel)+7)>>3) > static_cast<uint>(bytesPerPixel), ("invalid bytesPerPixel set, %d bytes with %d bits\n", bytesPerPixel, bitsPerPixel));
FATAL(m_isLocked, ("image is locked"));
//-- save image dimensions
m_width = width;
m_height = height;
m_bitsPerPixel = bitsPerPixel;
m_bytesPerPixel = bytesPerPixel;
m_stride = strideInBytes;
//-- calculate buffer size
m_bufferSize = strideInBytes * height;
if (strideInBytes < 0)
m_bufferSize = -m_bufferSize;
FATAL(m_bufferSize < 0, ("bad buffer size [%d], width=[%d], height=[%d], stride=[%d]", m_bufferSize, width, height, strideInBytes));
//-- create the buffer
delete [] m_buffer;
m_buffer = new uint8[static_cast<uint>(m_bufferSize)];
//-- format is now dirty
m_formatDirty = true;
}
// ----------------------------------------------------------------------
void Image::setPixelInformation(uint redMask, uint greenMask, uint blueMask, uint alphaMask)
{
FATAL(m_isLocked, ("image is locked"));
m_redMask = redMask;
m_greenMask = greenMask;
m_blueMask = blueMask;
m_alphaMask = alphaMask;
//-- format info now is dirty
m_formatDirty = true;
}
// ----------------------------------------------------------------------
uint8 *Image::lock(bool optional)
{
//-- check for error conditions
if (optional)
{
// bail out gracefully on errors
if (m_isLocked)
{
REPORT_LOG(true, ("tried to lock() already locked image\n"));
return m_buffer;
}
if (m_readOnly)
{
REPORT_LOG(true, ("tried to lock() read-only image\n"));
return 0;
}
}
else
{
FATAL(m_isLocked, ("tried to lock() already locked image\n"));
FATAL(m_readOnly, ("tried to lock() read-only image\n"));
}
//-- lock it
m_isLocked = true;
return m_buffer;
}
// ----------------------------------------------------------------------
const uint8 *Image::lockReadOnly(bool optional) const
{
//-- check for error conditions
if (optional)
{
// bail out gracefully on errors
if (m_isLocked)
{
REPORT_LOG(true, ("tried to lockReadOnly() already locked image\n"));
return m_buffer;
}
}
else
{
FATAL(m_isLocked, ("tried to lockReadOnly() already locked image\n"));
}
//-- lock it
m_isLocked = true;
return m_buffer;
}
// ----------------------------------------------------------------------
void Image::unlock() const
{
FATAL(!m_isLocked, ("image not locked"));
m_isLocked = false;
return;
}
// ----------------------------------------------------------------------
uint32 Image::calculateCrc() const
{
FATAL(!m_buffer, ("no buffer"));
return Crc::calculate(m_buffer, m_bufferSize);
}
// ----------------------------------------------------------------------
Image::PixelFormat Image::calculatePixelFormat() const
{
const int redShiftCount = GetFirstBitSet(m_redMask);
const int greenShiftCount = GetFirstBitSet(m_greenMask);
const int blueShiftCount = GetFirstBitSet(m_blueMask);
const int alphaShiftCount = GetFirstBitSet(m_alphaMask);
const int redBitCount = GetBitCount(m_redMask);
const int greenBitCount = GetBitCount(m_greenMask);
const int blueBitCount = GetBitCount(m_blueMask);
const int alphaBitCount = GetBitCount(m_alphaMask);
if ((blueShiftCount < greenShiftCount) && (greenShiftCount < redShiftCount))
{
// bgr layout
if (!m_alphaMask)
{
if ((redBitCount == 8) && (greenBitCount == 8) && (blueBitCount == 8))
return PF_bgr_888;
else
return PF_nonStandard;
}
else
{
if (alphaShiftCount > redShiftCount)
{
if ((redBitCount == 8) && (greenBitCount == 8) && (blueBitCount == 8) && (alphaBitCount == 8))
return PF_bgra_8888;
else
return PF_nonStandard;
}
else if (alphaShiftCount < blueShiftCount)
{
if ((redBitCount == 8) && (greenBitCount == 8) && (blueBitCount == 8) && (alphaBitCount == 8))
return PF_abgr_8888;
else
return PF_nonStandard;
}
else
{
// don't know where this alpha is. non-standard
return PF_nonStandard;
}
}
}
else if ((redShiftCount < greenShiftCount) && (greenShiftCount < blueShiftCount))
{
// rgb layout
if (!m_alphaMask)
{
if ((redBitCount == 8) && (greenBitCount == 8) && (blueBitCount == 8))
return PF_rgb_888;
else
return PF_nonStandard;
}
else
{
if (alphaShiftCount > blueShiftCount)
{
if ((redBitCount == 8) && (greenBitCount == 8) && (blueBitCount == 8) && (alphaBitCount == 8))
return PF_rgba_8888;
else
return PF_nonStandard;
}
else if (alphaShiftCount < redShiftCount)
{
if ((redBitCount == 8) && (greenBitCount == 8) && (blueBitCount == 8) && (alphaBitCount == 8))
return PF_argb_8888;
else
return PF_nonStandard;
}
else
{
// don't know where this alpha is. non-standard
return PF_nonStandard;
}
}
}
else if(m_redMask == 0 && m_greenMask == 0 && m_blueMask == 0 && m_alphaMask == 0 && m_bitsPerPixel == 8)
{
return PF_w_8; // 8bit greyscale bitmap
}
else
{
return PF_nonStandard;
}
}
// ======================================================================
@@ -0,0 +1,339 @@
// ======================================================================
//
// Image.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_Image_H
#define INCLUDED_Image_H
// ======================================================================
class Image
{
public:
/**
* Memory layout of pixels starting with component at most significant bit of first byte
* of a pixel in memory.
*
* For x86, this is the highest bit of the least significant byte. For big-endian
* architecture, this is the highest bit of the most-significant byte of a pixel.
*/
enum PixelFormat
{
PF_bgra_8888,
PF_bgr_888,
PF_abgr_8888,
PF_rgba_8888,
PF_rgb_888,
PF_argb_8888,
PF_w_8, //8bit greyscale bitmap
PF_nonStandard
};
static inline void setPixel(uint8 *&o_pixel, PixelFormat pixelFormat, uint8 red, uint8 green, uint8 blue, uint8 alpha=255);
static inline void getPixel(uint8 &red, uint8 &green, uint8 &blue, uint8 &alpha, const uint8 *&i_pixel, PixelFormat pixelFormat);
static inline void copyPixel(uint8 *&o_pixel, PixelFormat destPixelFormat, const uint8 *&i_pixel, PixelFormat sourcePixelFormat);
public:
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class UnlockGuard
{
public:
UnlockGuard(const Image *x) : image(x) {}
~UnlockGuard() { if (image) image->unlock(); }
private:
UnlockGuard &operator=(const UnlockGuard &);
const Image *const image;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Image();
Image(uint8 *pixelBuffer, int pixelBufferSize, int width, int height, int bitsPerPixel, int bytesPerPixel, int strideInBytes, uint redMask, uint greenMask, uint blueMask, uint alphaMask);
~Image();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// image construction interface
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void setDimensions(int width, int height, int bitsPerPixel, int bytesPerPixel);
void setDimensions(int width, int height, int bitsPerPixel, int bytesPerPixel, int strideInBytes);
void setPixelInformation(uint redMask, uint greenMask, uint blueMask, uint alphaMask);
uint8 *lock(bool optional = false);
void setReadOnly();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// image query/read interface
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int getWidth() const;
int getHeight() const;
int getBitsPerPixel() const;
int getBytesPerPixel() const;
int getStride() const;
int getBufferSize() const;
uint getRedMask() const;
uint getGreenMask() const;
uint getBlueMask() const;
uint getAlphaMask() const;
const uint8 *lockReadOnly(bool optional = false) const;
uint32 calculateCrc() const;
PixelFormat getPixelFormat() const;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// common interface
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void unlock() const;
private:
PixelFormat calculatePixelFormat() const;
private:
int m_width;
int m_height;
int m_bitsPerPixel;
int m_bytesPerPixel;
int m_stride;
uint m_redMask;
uint m_greenMask;
uint m_blueMask;
uint m_alphaMask;
bool m_ownBuffer;
uint8 *m_buffer;
int m_bufferSize;
bool m_readOnly;
mutable bool m_isLocked;
mutable bool m_formatDirty;
mutable PixelFormat m_format;
};
// ======================================================================
inline void Image::setReadOnly()
{
m_readOnly = true;
}
// ----------------------------------------------------------------------
inline int Image::getWidth() const
{
return m_width;
}
// ----------------------------------------------------------------------
inline int Image::getHeight() const
{
return m_height;
}
// ----------------------------------------------------------------------
inline int Image::getBitsPerPixel() const
{
return m_bitsPerPixel;
}
// ----------------------------------------------------------------------
inline int Image::getBytesPerPixel() const
{
return m_bytesPerPixel;
}
// ----------------------------------------------------------------------
inline int Image::getStride() const
{
return m_stride;
}
// ----------------------------------------------------------------------
inline int Image::getBufferSize() const
{
return m_bufferSize;
}
// ----------------------------------------------------------------------
inline uint Image::getRedMask() const
{
return m_redMask;
}
// ----------------------------------------------------------------------
inline uint Image::getGreenMask() const
{
return m_greenMask;
}
// ----------------------------------------------------------------------
inline uint Image::getBlueMask() const
{
return m_blueMask;
}
// ----------------------------------------------------------------------
inline uint Image::getAlphaMask() const
{
return m_alphaMask;
}
// ----------------------------------------------------------------------
inline Image::PixelFormat Image::getPixelFormat() const
{
if (m_formatDirty)
{
m_format = calculatePixelFormat();
m_formatDirty = false;
}
return m_format;
}
// ----------------------------------------------------------------------
inline void Image::setPixel(uint8 *&o_pixel, PixelFormat pixelFormat, uint8 red, uint8 green, uint8 blue, uint8 alpha)
{
switch (pixelFormat)
{
case PF_bgra_8888:
o_pixel[0]=blue;
o_pixel[1]=green;
o_pixel[2]=red;
o_pixel[3]=alpha;
o_pixel+=4;
break;
case PF_bgr_888:
o_pixel[0]=blue;
o_pixel[1]=green;
o_pixel[2]=red;
o_pixel+=3;
break;
case PF_abgr_8888:
o_pixel[0]=alpha;
o_pixel[1]=blue;
o_pixel[2]=green;
o_pixel[3]=red;
o_pixel+=4;
break;
case PF_rgba_8888:
o_pixel[0]=red;
o_pixel[1]=green;
o_pixel[2]=blue;
o_pixel[3]=alpha;
o_pixel+=4;
break;
case PF_rgb_888:
o_pixel[0]=red;
o_pixel[1]=green;
o_pixel[2]=blue;
o_pixel+=3;
break;
case PF_argb_8888:
o_pixel[0]=alpha;
o_pixel[1]=red;
o_pixel[2]=green;
o_pixel[3]=blue;
o_pixel+=4;
break;
case PF_w_8:
o_pixel[0]=red;
o_pixel+=1;
break;
case PF_nonStandard:
break;
}
}
// ----------------------------------------------------------------------
inline void Image::getPixel(uint8 &red, uint8 &green, uint8 &blue, uint8 &alpha, const uint8 *&i_pixel, PixelFormat pixelFormat)
{
switch (pixelFormat)
{
case PF_bgra_8888:
blue =i_pixel[0];
green=i_pixel[1];
red =i_pixel[2];
alpha=i_pixel[3];
i_pixel+=4;
break;
case PF_bgr_888:
blue =i_pixel[0];
green=i_pixel[1];
red =i_pixel[2];
alpha=255;
i_pixel+=3;
break;
case PF_abgr_8888:
alpha=i_pixel[0];
blue =i_pixel[1];
green=i_pixel[2];
red =i_pixel[3];
i_pixel+=4;
break;
case PF_rgba_8888:
red =i_pixel[0];
green=i_pixel[1];
blue =i_pixel[2];
alpha=i_pixel[3];
i_pixel+=4;
break;
case PF_rgb_888:
red =i_pixel[0];
green=i_pixel[1];
blue =i_pixel[2];
alpha=255;
i_pixel+=3;
break;
case PF_argb_8888:
alpha=i_pixel[0];
red =i_pixel[1];
green=i_pixel[2];
blue =i_pixel[3];
i_pixel+=4;
break;
case PF_w_8:
red=blue=green=i_pixel[0];
alpha=255;
i_pixel+=1;
break;
case PF_nonStandard:
break;
}
}
// ----------------------------------------------------------------------
inline void Image::copyPixel(uint8 *&o_pixel, PixelFormat destPixelFormat, const uint8 *&i_pixel, PixelFormat sourcePixelFormat)
{
uint8 r,g,b,a;
getPixel(r,g,b,a,i_pixel,sourcePixelFormat);
setPixel(o_pixel, destPixelFormat, r,g,b,a);
}
// ======================================================================
#endif
@@ -0,0 +1,65 @@
// ======================================================================
//
// ImageFormat.cpp
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedImage/FirstSharedImage.h"
#include "sharedImage/ImageFormat.h"
#include "sharedFile/TreeFile.h"
// ======================================================================
bool ImageFormat::loadFileCreateBuffer(const char *filename, uint8 **buffer, int *bufferSize)
{
//-- validate args
NOT_NULL(filename);
NOT_NULL(buffer);
NOT_NULL(bufferSize);
if (!*filename)
{
REPORT_LOG(true, ("empty filename\n"));
return false;
}
//-- open file
AbstractFile *fileInterface = TreeFile::open(filename, AbstractFile::PriorityData, true);
if(!fileInterface)
{
REPORT_LOG(true, ("failed to open file [%s]\n", filename));
return false;
}
//-- create buffer
*bufferSize = fileInterface->length();
*buffer = NON_NULL(new uint8[static_cast<uint>(*bufferSize)]);
//-- load the buffer
const int readBytes = fileInterface->read(*buffer, *bufferSize);
delete fileInterface;
if (readBytes != *bufferSize)
{
REPORT_LOG(true, ("error: reported file size = %d, we read %d\n", *bufferSize, readBytes));
return false;
}
//-- no errors
return true;
}
// ======================================================================
ImageFormat::ImageFormat()
{
}
// ----------------------------------------------------------------------
ImageFormat::~ImageFormat()
{
}
// ======================================================================
@@ -0,0 +1,43 @@
// ======================================================================
//
// ImageFormat.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef IMAGE_FORMAT
#define IMAGE_FORMAT
// ======================================================================
class Image;
// ======================================================================
class ImageFormat
{
public:
ImageFormat();
virtual ~ImageFormat();
virtual const char *getName() const = 0;
virtual bool isValidImage(const char *filename) const = 0;
virtual bool loadImage(const char *filename, Image **image) const = 0;
virtual int getCommonExtensionCount() const = 0;
virtual const char *getCommonExtension(int index) const = 0;
protected:
static bool loadFileCreateBuffer(const char *filename, uint8 **buffer, int *bufferSize);
private:
// disabled
ImageFormat(const ImageFormat&);
ImageFormat &operator =(const ImageFormat&);
};
// ======================================================================
#endif
@@ -0,0 +1,255 @@
// ======================================================================
//
// ImageFormatList.cpp
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedImage/FirstSharedImage.h"
#include "sharedImage/ImageFormatList.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedImage/Image.h"
#include "sharedImage/ImageFormat.h"
#include <algorithm>
#include <map>
#include <string>
#include <vector>
// ======================================================================
bool ImageFormatList::ms_installed;
ImageFormatList::ImageFormatVector *ImageFormatList::ms_imageFormats;
ImageFormatList::ExtensionMap *ImageFormatList::ms_extensionMap;
// ======================================================================
void ImageFormatList::install()
{
DEBUG_FATAL(ms_installed, ("ImageFormatList already installed"));
ms_installed = true;
ExitChain::add(remove, "ImageFormatList");
ms_imageFormats = new ImageFormatVector();
ms_extensionMap = new ExtensionMap();
}
// ----------------------------------------------------------------------
void ImageFormatList::remove()
{
DEBUG_FATAL(!ms_installed, ("ImageFormatList not installed"));
delete ms_extensionMap;
ms_extensionMap = 0;
// we don't own the image formats, so don't try to delete them
delete ms_imageFormats;
ms_imageFormats = 0;
ms_installed = false;
}
// ----------------------------------------------------------------------
void ImageFormatList::addImageFormat(const ImageFormat *imageFormat)
{
DEBUG_FATAL(!ms_installed, ("ImageFormatList not installed"));
NOT_NULL(ms_extensionMap);
NOT_NULL(ms_imageFormats);
NOT_NULL(imageFormat);
#ifdef _DEBUG
//-- make sure image format isn't already installed
const ImageFormatVector::const_iterator it = std::find(ms_imageFormats->begin(), ms_imageFormats->end(), imageFormat);
DEBUG_FATAL(it != ms_imageFormats->end(), ("imageFormat [0x%08x, (%s)] already installed", imageFormat->getName()));
#endif
//-- add image format to list of image formats
ms_imageFormats->push_back(imageFormat);
//-- add image format to extension map (allows us to try a format by file extension first)
const int extensionCount = imageFormat->getCommonExtensionCount();
for (int i = 0; i < extensionCount; ++i)
{
//-- get lowercase extension
std::string extension = imageFormat->getCommonExtension(i);
IGNORE_RETURN(std::transform(extension.begin(), extension.end(), extension.begin(), tolower));
//-- map extension to this image format
std::pair<ExtensionMap::iterator, bool> result = ms_extensionMap->insert(std::make_pair(extension, imageFormat));
UNREF(result);
DEBUG_REPORT_LOG(!result.second, ("image format [%s] has conflicting default extension [%s] with [%s]\n", imageFormat->getName(), extension.c_str(), (*result.first).second->getName()));
}
}
// ----------------------------------------------------------------------
void ImageFormatList::removeImageFormat(const ImageFormat *imageFormat)
{
DEBUG_FATAL(!ms_installed, ("ImageFormatList not installed"));
NOT_NULL(ms_extensionMap);
NOT_NULL(ms_imageFormats);
NOT_NULL(imageFormat);
//-- remove image format from extension map
{
ExtensionMap::iterator it;
ExtensionMap::const_iterator itEnd;
do
{
it = ms_extensionMap->begin();
itEnd = ms_extensionMap->end();
for (; it != itEnd; ++it)
{
if ((*it).second == imageFormat)
{
// found one, remove it
ms_extensionMap->erase(it);
// we invalidate the iterator once we modify the container, so restart search
break;
}
}
}
while (it != itEnd);
}
//-- remove image format from image format list
{
// find the image format
ImageFormatVector::iterator it = std::find(ms_imageFormats->begin(), ms_imageFormats->end(), imageFormat);
DEBUG_FATAL(it == ms_imageFormats->end(), ("failed to find image format specified for removal"));
// remove it
// we don't own the formats, so don't erase it
if (it != ms_imageFormats->end())
IGNORE_RETURN(ms_imageFormats->erase(it));
}
}
// ----------------------------------------------------------------------
int ImageFormatList::getImageFormatCount()
{
DEBUG_FATAL(!ms_installed, ("ImageFormatList not installed"));
NOT_NULL(ms_imageFormats);
return static_cast<int>(ms_imageFormats->size());
}
// ----------------------------------------------------------------------
const ImageFormat *ImageFormatList::getImageFormat(int index)
{
DEBUG_FATAL(!ms_installed, ("ImageFormatList not installed"));
NOT_NULL(ms_imageFormats);
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, static_cast<int>(ms_imageFormats->size()));
return (*ms_imageFormats)[static_cast<size_t>(index)];
}
// ----------------------------------------------------------------------
Image *ImageFormatList::loadImage(const char *filename, bool readOnly)
{
DEBUG_FATAL(!ms_installed, ("ImageFormatList not installed"));
NOT_NULL(filename);
//-- first try to find format by the extension of the filename
const char *extensionDot = strrchr(filename, '.');
if (extensionDot)
{
// convert extension to lower case
std::string extension(extensionDot+1);
IGNORE_RETURN(std::transform(extension.begin(), extension.end(), extension.begin(), tolower));
// see if we have a file format for this extension
NOT_NULL(ms_extensionMap);
const ExtensionMap::const_iterator it = ms_extensionMap->find(extension);
if (it != ms_extensionMap->end())
{
// found a file format that thinks it knows how to open this file by its extension
const ImageFormat *const imageFormat = (*it).second;
NOT_NULL(imageFormat);
Image *image = 0;
const bool loadSuccess = imageFormat->loadImage(filename, &image);
DEBUG_REPORT_LOG(!loadSuccess, ("default image format [%s] thinks image [%s] is invalid, trying alternate formats\n", imageFormat->getName(), filename));
if (loadSuccess)
{
// loaded the image
NOT_NULL(image);
if (readOnly)
image->setReadOnly();
return image;
}
}
}
// didn't find an image format that knows how to load by extension, so let's
// try them all. file might be saved as a non-standard extension.
//-- find the first format that thinks it can load the format
{
NOT_NULL(ms_imageFormats);
const size_t count = ms_imageFormats->size();
for (size_t i = 0; i < count; ++i)
{
const ImageFormat *const imageFormat = (*ms_imageFormats)[i];
if (imageFormat->isValidImage(filename))
{
// image format thinks it can load this
Image *image = 0;
const bool loadSuccess = imageFormat->loadImage(filename, &image);
DEBUG_REPORT_LOG(!loadSuccess, ("image format [%s] thought it could load [%s] but failed, trying others\n", imageFormat->getName(), filename));
if (loadSuccess)
{
// loaded the image
NOT_NULL(image);
if (readOnly)
image->setReadOnly();
return image;
}
}
}
}
//-- failed
return 0;
}
// ----------------------------------------------------------------------
Image *ImageFormatList::loadImage(const char *filename, int formatIndex, bool readOnly)
{
DEBUG_FATAL(!ms_installed, ("ImageFormatList not installed"));
//-- get the image format
const ImageFormat *const imageFormat = getImageFormat(formatIndex);
NOT_NULL(imageFormat);
//-- load the image
Image *image = 0;
const bool loadSuccess = imageFormat->loadImage(filename, &image);
DEBUG_REPORT_LOG(!loadSuccess, ("image format [%s] (format specified by user) failed to load [%s]\n", imageFormat->getName(), filename));
if (loadSuccess)
{
// loaded the image
NOT_NULL(image);
if (readOnly)
image->setReadOnly();
return image;
}
else
{
// failed to load image
return 0;
}
}
// ======================================================================
@@ -0,0 +1,53 @@
// ======================================================================
//
// ImageFormatList.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_ImageFormatList_H
#define INCLUDED_ImageFormatList_H
// ======================================================================
class Image;
class ImageFormat;
// ======================================================================
class ImageFormatList
{
public:
static void install();
static void addImageFormat(const ImageFormat *imageFormat);
static void removeImageFormat(const ImageFormat *imageFormat);
static int getImageFormatCount();
static const ImageFormat *getImageFormat(int index);
static Image *loadImage(const char *filename, bool readOnly = true);
static Image *loadImage(const char *filename, int formatIndex, bool readOnly = true);
private:
static void remove();
private:
typedef stdvector<const ImageFormat*>::fwd ImageFormatVector;
typedef stdmap<std::string, const ImageFormat*>::fwd ExtensionMap;
private:
static bool ms_installed;
static ImageFormatVector *ms_imageFormats;
static ExtensionMap *ms_extensionMap;
};
// ======================================================================
#endif
@@ -0,0 +1,532 @@
// ======================================================================
//
// ImageManipulation.cpp
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedImage/FirstSharedImage.h"
#include "sharedImage/ImageManipulation.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedImage/Image.h"
// ======================================================================
bool ImageManipulation::ms_installed;
ImageManipulation::NextMipmapFunction ImageManipulation::ms_nextMipmapFunction;
ImageManipulation::ConvertFormatFunction ImageManipulation::ms_convertFormatFunction;
ImageManipulation::CopyFunction ImageManipulation::ms_copyIgnoreAlphaFunction;
ImageManipulation::CopyFunction ImageManipulation::ms_copyRespectAlphaFunction;
ImageManipulation::BlendFunction ImageManipulation::ms_blendFunction;
ImageManipulation::BlendTwoFunction ImageManipulation::ms_blendTwoFunction;
// ======================================================================
namespace ImageManipulationNamespace
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<typename PixelTraits>
struct DefaultNextMipmapFunction
{
static void nextMipmapFunction(const Image &sourceImage, Image &destImage);
static void nextMipmapFunction_EqualWidth(const Image &sourceImage, Image &destImage);
static void nextMipmapFunction_EqualHeight(const Image &sourceImage, Image &destImage);
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<const int redIndex, const int greenIndex, const int blueIndex>
struct PixelTraitsThreeByOne
{
static int getPixelStride();
static void copyWithPowerOfTwoDivide(const uint8 *sourcePixel, uint8 *destPixel, uint8 powerOfTwoDivide);
static void addWithPowerOfTwoDivide(const uint8 *sourcePixel, uint8 *destPixel, uint8 powerOfTwoDivide);
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<const int redIndex, const int greenIndex, const int blueIndex, const int alphaIndex>
struct PixelTraitsFourByOne
{
static int getPixelStride();
static void copyWithPowerOfTwoDivide(const uint8 *sourcePixel, uint8 *destPixel, uint8 powerOfTwoDivide);
static void addWithPowerOfTwoDivide(const uint8 *sourcePixel, uint8 *destPixel, uint8 powerOfTwoDivide);
};
}
using namespace ImageManipulationNamespace;
// ======================================================================
template<typename PixelTraits>
void ImageManipulationNamespace::DefaultNextMipmapFunction<PixelTraits>::nextMipmapFunction(const Image &sourceImage, Image &destImage)
{
const uint8 *const sourceBuffer = sourceImage.lockReadOnly();
const uint8 *sourceLine = sourceBuffer;
const int sourceStride = sourceImage.getStride();
const int destHeight = destImage.getHeight();
const int destWidth = destImage.getWidth();
uint8 *const destBuffer = destImage.lock();
uint8 *destLine = destBuffer;
const int destStride = destImage.getStride();
// The strategy we follow in this algorithm attempts to optimize cache coherency.
// Each dest pixel is written with a simple 2x2 box filter over the source pixels.
// Each source pixel weights at 25%. So that we always read linearly from the
// source data, we write each dest line in two passes. The first pass writes in
// the pixel contribution to the pixel from the first source line. The
// second pass writes in the contribution from the second source line.
for (int destY = 0; destY < destHeight; ++destY)
{
//-- read first source line, applying 25% of each source pixel into dest pixel
const uint8 *sourcePixel = sourceLine;
uint8 *destPixel = destLine;
{
for (int destX = 0; destX < destWidth; ++destX)
{
//-- handle source upper left (first pixel gets copied in)
PixelTraits::copyWithPowerOfTwoDivide(sourcePixel, destPixel, 2);
sourcePixel += PixelTraits::getPixelStride();
//-- handle source upper right
PixelTraits::addWithPowerOfTwoDivide(sourcePixel, destPixel, 2);
sourcePixel += PixelTraits::getPixelStride();
//-- move on to next dest pixel
destPixel += PixelTraits::getPixelStride();
}
}
//-- read second source line, applying 25% of each source pixel into dest pixel
sourceLine += sourceStride;
sourcePixel = sourceLine;
destPixel = destLine;
{
for (int destX = 0; destX < destWidth; ++destX)
{
//-- handle source lower left
PixelTraits::addWithPowerOfTwoDivide(sourcePixel, destPixel, 2);
sourcePixel += PixelTraits::getPixelStride();
//-- handle source lower right
PixelTraits::addWithPowerOfTwoDivide(sourcePixel, destPixel, 2);
sourcePixel += PixelTraits::getPixelStride();
//-- move on to next dest pixel
destPixel += PixelTraits::getPixelStride();
}
}
//-- increment source and dest line pointers
destLine += destStride;
sourceLine += sourceStride;
}
//-- cleanup
destImage.unlock();
sourceImage.unlock();
}
// ----------------------------------------------------------------------
/**
* This function generates the next smaller mipmap in the Y direction but
* preserves the image in the x direction.
*
* This function would be used when we are mipmapping a 1x8 down to a 1x4.
* The X contribution to color is 50% for the current pixel.
*/
template<typename PixelTraits>
void ImageManipulationNamespace::DefaultNextMipmapFunction<PixelTraits>::nextMipmapFunction_EqualWidth(const Image &sourceImage, Image &destImage)
{
DEBUG_FATAL(sourceImage.getWidth() != destImage.getWidth(), ("This function only makes sense when source width [%d] is the same as dest width [%d].", sourceImage.getWidth(), destImage.getWidth()));
const uint8 *const sourceBuffer = sourceImage.lockReadOnly();
const uint8 *sourceLine = sourceBuffer;
const int sourceStride = sourceImage.getStride();
const int destHeight = destImage.getHeight();
const int destWidth = destImage.getWidth();
uint8 *const destBuffer = destImage.lock();
uint8 *destLine = destBuffer;
const int destStride = destImage.getStride();
// The strategy we follow in this algorithm attempts to optimize cache coherency.
// Each dest pixel is written with a simple 1x2 box filter over the source pixels.
// Each source pixel weights at 50%. So that we always read linearly from the
// source data, we write each dest line in two passes. The first pass writes in
// the pixel contribution to the pixel from the first source line. The
// second pass writes in the contribution from the second source line.
for (int destY = 0; destY < destHeight; ++destY)
{
//-- read first source line, applying 50% of each source pixel into dest pixel
const uint8 *sourcePixel = sourceLine;
uint8 *destPixel = destLine;
{
for (int destX = 0; destX < destWidth; ++destX)
{
//-- handle upper pixel (first pixel gets copied in)
PixelTraits::copyWithPowerOfTwoDivide(sourcePixel, destPixel, 1);
//-- move on to next pixel
sourcePixel += PixelTraits::getPixelStride();
destPixel += PixelTraits::getPixelStride();
}
}
//-- read second source line, applying 50% of each source pixel into dest pixel
sourceLine += sourceStride;
sourcePixel = sourceLine;
destPixel = destLine;
{
for (int destX = 0; destX < destWidth; ++destX)
{
//-- handle source lower pixel
PixelTraits::addWithPowerOfTwoDivide(sourcePixel, destPixel, 1);
//-- move on to next dest pixel
sourcePixel += PixelTraits::getPixelStride();
destPixel += PixelTraits::getPixelStride();
}
}
//-- increment source and dest line pointers
destLine += destStride;
sourceLine += sourceStride;
}
//-- cleanup
destImage.unlock();
sourceImage.unlock();
}
// ----------------------------------------------------------------------
/**
* This function generates the next smaller mipmap in the X direction but
* preserves the image in the Y direction.
*
* This function would be used when we are mipmapping an 8x1 down to a 4x1.
* The Y contribution to color is 50% for the current pixel.
*/
template<typename PixelTraits>
void ImageManipulationNamespace::DefaultNextMipmapFunction<PixelTraits>::nextMipmapFunction_EqualHeight(const Image &sourceImage, Image &destImage)
{
DEBUG_FATAL(sourceImage.getHeight() != destImage.getHeight(), ("This function only makes sense when source height [%d] is the same as dest height [%d].", sourceImage.getHeight(), destImage.getHeight()));
const uint8 *const sourceBuffer = sourceImage.lockReadOnly();
const uint8 *sourceLine = sourceBuffer;
const int sourceStride = sourceImage.getStride();
const int destHeight = destImage.getHeight();
const int destWidth = destImage.getWidth();
uint8 *const destBuffer = destImage.lock();
uint8 *destLine = destBuffer;
const int destStride = destImage.getStride();
// The strategy we follow in this algorithm attempts to optimize cache coherency.
// Each dest pixel is written with a simple 2x1 box filter over the source pixels.
// Each source pixel weights at 50%.
for (int destY = 0; destY < destHeight; ++destY)
{
//-- read first source line, applying 50% of each source pixel into dest pixel
const uint8 *sourcePixel = sourceLine;
uint8 *destPixel = destLine;
{
for (int destX = 0; destX < destWidth; ++destX)
{
//-- handle source left (first pixel gets copied in)
PixelTraits::copyWithPowerOfTwoDivide(sourcePixel, destPixel, 1);
sourcePixel += PixelTraits::getPixelStride();
//-- handle source right
PixelTraits::addWithPowerOfTwoDivide(sourcePixel, destPixel, 1);
sourcePixel += PixelTraits::getPixelStride();
//-- move on to next dest pixel
destPixel += PixelTraits::getPixelStride();
}
}
//-- increment source and dest line pointers
destLine += destStride;
sourceLine += sourceStride;
}
//-- cleanup
destImage.unlock();
sourceImage.unlock();
}
// ======================================================================
// template class PixelTraitsThreeByOne
// ======================================================================
template<const int redIndex, const int greenIndex, const int blueIndex>
inline int ImageManipulationNamespace::PixelTraitsThreeByOne<redIndex, greenIndex, blueIndex>::getPixelStride()
{
return 3;
}
// ----------------------------------------------------------------------
template<const int redIndex, const int greenIndex, const int blueIndex>
inline void ImageManipulationNamespace::PixelTraitsThreeByOne<redIndex, greenIndex, blueIndex>::copyWithPowerOfTwoDivide(const uint8 *sourcePixel, uint8 *destPixel, uint8 powerOfTwoDivide)
{
destPixel[0] = static_cast<uint8>(sourcePixel[0] >> powerOfTwoDivide);
destPixel[1] = static_cast<uint8>(sourcePixel[1] >> powerOfTwoDivide);
destPixel[2] = static_cast<uint8>(sourcePixel[2] >> powerOfTwoDivide);
}
// ----------------------------------------------------------------------
template<const int redIndex, const int greenIndex, const int blueIndex>
inline void ImageManipulationNamespace::PixelTraitsThreeByOne<redIndex, greenIndex, blueIndex>::addWithPowerOfTwoDivide(const uint8 *sourcePixel, uint8 *destPixel, uint8 powerOfTwoDivide)
{
destPixel[0] = static_cast<uint8>(destPixel[0] + static_cast<uint8>(sourcePixel[0] >> powerOfTwoDivide));
destPixel[1] = static_cast<uint8>(destPixel[1] + static_cast<uint8>(sourcePixel[1] >> powerOfTwoDivide));
destPixel[2] = static_cast<uint8>(destPixel[2] + static_cast<uint8>(sourcePixel[2] >> powerOfTwoDivide));
}
// ======================================================================
// template class PixelTraitsFourByOne
// ======================================================================
template<const int redIndex, const int greenIndex, const int blueIndex, const int alphaIndex>
inline int ImageManipulationNamespace::PixelTraitsFourByOne<redIndex, greenIndex, blueIndex, alphaIndex>::getPixelStride()
{
return 4;
}
// ----------------------------------------------------------------------
template<const int redIndex, const int greenIndex, const int blueIndex, const int alphaIndex>
inline void ImageManipulationNamespace::PixelTraitsFourByOne<redIndex, greenIndex, blueIndex, alphaIndex>::copyWithPowerOfTwoDivide(const uint8 *sourcePixel, uint8 *destPixel, uint8 powerOfTwoDivide)
{
destPixel[0] = static_cast<uint8>(sourcePixel[0] >> powerOfTwoDivide);
destPixel[1] = static_cast<uint8>(sourcePixel[1] >> powerOfTwoDivide);
destPixel[2] = static_cast<uint8>(sourcePixel[2] >> powerOfTwoDivide);
destPixel[3] = static_cast<uint8>(sourcePixel[3] >> powerOfTwoDivide);
}
// ----------------------------------------------------------------------
template<const int redIndex, const int greenIndex, const int blueIndex, const int alphaIndex>
inline void ImageManipulationNamespace::PixelTraitsFourByOne<redIndex, greenIndex, blueIndex, alphaIndex>::addWithPowerOfTwoDivide(const uint8 *sourcePixel, uint8 *destPixel, uint8 powerOfTwoDivide)
{
destPixel[0] = static_cast<uint8>(destPixel[0] + static_cast<uint8>(sourcePixel[0] >> powerOfTwoDivide));
destPixel[1] = static_cast<uint8>(destPixel[1] + static_cast<uint8>(sourcePixel[1] >> powerOfTwoDivide));
destPixel[2] = static_cast<uint8>(destPixel[2] + static_cast<uint8>(sourcePixel[2] >> powerOfTwoDivide));
destPixel[3] = static_cast<uint8>(destPixel[3] + static_cast<uint8>(sourcePixel[3] >> powerOfTwoDivide));
}
// ======================================================================
// struct ImageManipulation::InstallData
// ======================================================================
ImageManipulation::InstallData::InstallData()
: m_nextMipmapFunction(0),
m_convertFormatFunction(0),
m_copyIgnoreAlphaFunction(0),
m_copyRespectAlphaFunction(0),
m_blendFunction(0),
m_blendTwoFunction(0)
{
}
// ======================================================================
// class ImageManipulation
// ======================================================================
void ImageManipulation::install(const InstallData &installData)
{
DEBUG_FATAL(ms_installed, ("ImageManipulation already installed"));
ms_installed = true;
ExitChain::add(remove, "ImageManipulation");
if (installData.m_nextMipmapFunction)
ms_nextMipmapFunction = installData.m_nextMipmapFunction;
else
ms_nextMipmapFunction = defaultNextMipmapFunction;
//-- make sure we've got valid function pointers for all
NOT_NULL(ms_nextMipmapFunction);
#if 0
NOT_NULL(ms_convertFormatFunction);
NOT_NULL(ms_copyIgnoreAlphaFunction);
NOT_NULL(ms_copyRespectAlphaFunction);
NOT_NULL(ms_blendFunction);
NOT_NULL(ms_blendTwoFunction);
#endif
}
// ----------------------------------------------------------------------
void ImageManipulation::remove()
{
DEBUG_FATAL(!ms_installed, ("ImageManipulation not installed"));
ms_nextMipmapFunction = 0;
ms_convertFormatFunction = 0;
ms_copyIgnoreAlphaFunction = 0;
ms_copyRespectAlphaFunction = 0;
ms_blendFunction = 0;
ms_blendTwoFunction = 0;
}
// ----------------------------------------------------------------------
void ImageManipulation::defaultNextMipmapFunction(const Image &sourceImage, Image &destImage)
{
const Image::PixelFormat pixelFormat = sourceImage.getPixelFormat();
DEBUG_FATAL(pixelFormat != destImage.getPixelFormat(), ("source and dest image have different pixel layout"));
DEBUG_FATAL(pixelFormat == Image::PF_nonStandard, ("cannot handle non-standard pixel layouts"));
DEBUG_FATAL(!IsPowerOfTwo(sourceImage.getWidth()), ("source width not power of two %d", sourceImage.getWidth()));
DEBUG_FATAL(!IsPowerOfTwo(sourceImage.getHeight()), ("source height not power of two %d", sourceImage.getHeight()));
const int destWidth = destImage.getWidth();
const int destHeight = destImage.getHeight();
const int sourceWidth = sourceImage.getWidth();
const int sourceHeight = sourceImage.getHeight();
DEBUG_FATAL(destWidth < 1, ("destImage width invalid [%d].", destWidth));
DEBUG_FATAL(sourceWidth < 1, ("sourceImage width invalid [%d].", sourceWidth));
DEBUG_FATAL(destHeight < 1, ("destImage height invalid [%d].", destHeight));
DEBUG_FATAL(sourceHeight < 1, ("sourceImage height invalid [%d].", sourceHeight));
VALIDATE_RANGE_INCLUSIVE_INCLUSIVE(sourceWidth / 2, destWidth, sourceWidth);
VALIDATE_RANGE_INCLUSIVE_INCLUSIVE(sourceHeight / 2, destHeight, sourceHeight);
//-- select the proper templated function
NextMipmapFunction workerFunction = 0;
if ((destWidth == sourceWidth / 2) && (destHeight == sourceHeight / 2))
{
// Mipmap down in both x and y direction.
switch (pixelFormat)
{
case Image::PF_bgr_888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsThreeByOne<2, 1, 0> >::nextMipmapFunction;
break;
case Image::PF_rgb_888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsThreeByOne<0, 1, 2> >::nextMipmapFunction;
break;
case Image::PF_bgra_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<2, 1, 0, 3> >::nextMipmapFunction;
break;
case Image::PF_abgr_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<3, 2, 1, 0> >::nextMipmapFunction;
break;
case Image::PF_rgba_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<0, 1, 2, 3> >::nextMipmapFunction;
break;
case Image::PF_argb_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<1, 2, 3, 0> >::nextMipmapFunction;
break;
case Image::PF_nonStandard:
default:
FATAL(true, ("unsupported format for conversion"));
}
}
else if ((destWidth == sourceWidth) && (destHeight == sourceHeight / 2))
{
// Mipmap down in y, preserve x direction.
switch (pixelFormat)
{
case Image::PF_bgr_888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsThreeByOne<2, 1, 0> >::nextMipmapFunction_EqualWidth;
break;
case Image::PF_rgb_888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsThreeByOne<0, 1, 2> >::nextMipmapFunction_EqualWidth;
break;
case Image::PF_bgra_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<2, 1, 0, 3> >::nextMipmapFunction_EqualWidth;
break;
case Image::PF_abgr_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<3, 2, 1, 0> >::nextMipmapFunction_EqualWidth;
break;
case Image::PF_rgba_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<0, 1, 2, 3> >::nextMipmapFunction_EqualWidth;
break;
case Image::PF_argb_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<1, 2, 3, 0> >::nextMipmapFunction_EqualWidth;
break;
case Image::PF_nonStandard:
default:
FATAL(true, ("unsupported format for conversion"));
}
}
else if ((destWidth == sourceWidth / 2) && (destHeight == sourceHeight))
{
// Mipmap down in y, preserve x direction.
switch (pixelFormat)
{
case Image::PF_bgr_888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsThreeByOne<2, 1, 0> >::nextMipmapFunction_EqualHeight;
break;
case Image::PF_rgb_888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsThreeByOne<0, 1, 2> >::nextMipmapFunction_EqualHeight;
break;
case Image::PF_bgra_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<2, 1, 0, 3> >::nextMipmapFunction_EqualHeight;
break;
case Image::PF_abgr_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<3, 2, 1, 0> >::nextMipmapFunction_EqualHeight;
break;
case Image::PF_rgba_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<0, 1, 2, 3> >::nextMipmapFunction_EqualHeight;
break;
case Image::PF_argb_8888:
workerFunction = DefaultNextMipmapFunction<PixelTraitsFourByOne<1, 2, 3, 0> >::nextMipmapFunction_EqualHeight;
break;
case Image::PF_nonStandard:
default:
FATAL(true, ("unsupported format for conversion"));
}
}
else
FATAL(true, ("Unexpected error: mipmap generation failing [source w=%d,h=%d], [dest w=%d,h=%d].", sourceWidth, sourceHeight, destWidth, destHeight));
NOT_NULL(workerFunction);
//-- call the function
(*workerFunction)(sourceImage, destImage);
}
// ======================================================================
@@ -0,0 +1,118 @@
// ======================================================================
//
// ImageManipulation.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_ImageManipulation_H
#define INCLUDED_ImageManipulation_H
// ======================================================================
class Image;
// ======================================================================
/**
* This class encapsulates functionality to manipulate pre-existing Images.
*
* This class provides an interface for manipulating images. This includes
* generating mipmap levels and converting from one format to another.
* This functionality was not included as part of class Image because all
* these functions deal with multiple images. Perhaps more importantly,
* each one of these functions can be implemented in multiple ways on a
* single platform dependent on the processor (e.g. Intel: SSE or CPU ALU).
*/
class ImageManipulation
{
public:
typedef void (*NextMipmapFunction)(const Image &sourceImage, Image &destImage);
typedef void (*ConvertFormatFunction)(const Image &sourceImage, Image &destImage);
typedef void (*CopyFunction)(const Image &sourceImage, int sourceX, int sourceY, int width, int height, Image &destImage, int destX, int destY);
typedef void (*BlendFunction)(float sourceBlendFactor, const Image &sourceImage, int sourceX, int sourceY, int width, int height, Image &destImage, int destX, int destY);
typedef void (*BlendTwoFunction)(float firstSourceBlendFactor, float resultToDestBlendFactor, const Image &sourceImage1, const Image &sourceImage2, int sourceX, int sourceY, int width, int height, Image &destImage, int destX, int destY);
struct InstallData
{
public:
InstallData();
public:
NextMipmapFunction m_nextMipmapFunction;
ConvertFormatFunction m_convertFormatFunction;
CopyFunction m_copyIgnoreAlphaFunction;
CopyFunction m_copyRespectAlphaFunction;
BlendFunction m_blendFunction;
BlendTwoFunction m_blendTwoFunction;
};
public:
static void install(const InstallData &installData);
static void generateNextSmallerMipmap(const Image &sourceImage, Image &destImage);
#if 0
static void convertFormatSameSize(const Image &sourceImage, Image &destImage);
// these functions require same pixel format. they do not stretch or compress pixels.
static void copyIgnoreAlpha(const Image &sourceImage, int sourceX, int sourceY, int width, int height, Image &destImage, int destX, int destY);
static void copyRespectAlpha(const Image &sourceImage, int sourceX, int sourceY, int width, int height, Image &destImage, int destX, int destY);
// these two always respect alpha
static void blend(float sourceBlendFactor, const Image &sourceImage, int sourceX, int sourceY, int width, int height, Image &destImage, int destX, int destY);
static void blendTwo(float firstSourceBlendFactor, float resultToDestBlendFactor, const Image &sourceImage1, const Image &sourceImage2, int sourceX, int sourceY, int width, int height, Image &destImage, int destX, int destY);
#endif
private:
static void remove();
static void defaultNextMipmapFunction(const Image &sourceImage, Image &destImage);
private:
static bool ms_installed;
static NextMipmapFunction ms_nextMipmapFunction;
static ConvertFormatFunction ms_convertFormatFunction;
static CopyFunction ms_copyIgnoreAlphaFunction;
static CopyFunction ms_copyRespectAlphaFunction;
static BlendFunction ms_blendFunction;
static BlendTwoFunction ms_blendTwoFunction;
};
// ======================================================================
/**
* Generate the next smaller mipmap level from sourceImage and place in
* destImage.
*
* sourceImage and destImage must be the same pixel format.
*
* sourceImage width and height must be a power of two, with no length
* less than 1.
*
* for now, assume we always preserve texture length aspect ratio.
* thus, we do not support generating the next mipmap level down from
* an 8x1 texture since we cannot have a length less than one.
*
* sourceImage and destImage are unlocked upon entry. they will be
* unlocked upon exit.
*/
inline void ImageManipulation::generateNextSmallerMipmap(const Image &sourceImage, Image &destImage)
{
DEBUG_FATAL(!ms_installed, ("ImageManipulation not installed"));
(*ms_nextMipmapFunction)(sourceImage, destImage);
}
// ======================================================================
#endif
@@ -0,0 +1,72 @@
// ======================================================================
//
// SetupSharedImage.cpp
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedImage/FirstSharedImage.h"
#include "sharedImage/SetupSharedImage.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedImage/ConfigSharedImage.h"
#include "sharedImage/ImageFormatList.h"
#include "sharedImage/ImageManipulation.h"
#include "sharedImage/TargaFormat.h"
#include "sharedDebug/InstallTimer.h"
// ======================================================================
bool SetupSharedImage::ms_installed;
TargaFormat *SetupSharedImage::ms_targaFormat;
// ======================================================================
void SetupSharedImage::install(const Data &data)
{
InstallTimer const installTimer("SetupSharedImage::install");
ConfigSharedImage::install();
DEBUG_FATAL(ms_installed, ("SetupSharedImage already installed"));
ImageFormatList::install();
ImageManipulation::InstallData imInstallData;
// -TRF- have ImagePlatform install platform-specific handlers into imInstallData here
ImageManipulation::install(imInstallData);
ms_installed = true;
ExitChain::add(remove, "SetupSharedImage");
// add support for specified formats
if (data.m_supportTarga)
{
ms_targaFormat = new TargaFormat();
ImageFormatList::addImageFormat(ms_targaFormat);
}
}
// ----------------------------------------------------------------------
void SetupSharedImage::remove()
{
DEBUG_FATAL(!ms_installed, ("SetupSharedImage not installed"));
// remove supported formats
if (ms_targaFormat)
{
ImageFormatList::removeImageFormat(ms_targaFormat);
delete ms_targaFormat;
ms_targaFormat = 0;
}
}
// ----------------------------------------------------------------------
void SetupSharedImage::setupDefaultData(Data &data)
{
data.m_supportTarga = true;
}
// ======================================================================
@@ -0,0 +1,43 @@
// ======================================================================
//
// SetupSharedImage.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef INCLUDED_SetupSharedImage_H
#define INCLUDED_SetupSharedImage_H
// ======================================================================
class TargaFormat;
// ======================================================================
class SetupSharedImage
{
public:
struct Data
{
bool m_supportTarga;
};
public:
static void setupDefaultData(Data &data);
static void install(const Data &data);
private:
static void remove();
private:
static bool ms_installed;
static TargaFormat *ms_targaFormat;
};
// ======================================================================
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,48 @@
// ======================================================================
//
// TargaFormat.h
// copyright 2001 Sony Online Entertainment
//
// ======================================================================
#ifndef TARGA_FORMAT_H
#define TARGA_FORMAT_H
// ======================================================================
#include "sharedImage/ImageFormat.h"
#include "sharedImage/Image.h"
// ======================================================================
namespace TargaHeaderNamespace
{
struct TargaHeader;
}
class TargaFormat: public ImageFormat
{
public:
TargaFormat();
virtual ~TargaFormat();
virtual const char *getName() const;
virtual bool isValidImage(const char *filename) const;
virtual bool loadImage(const char *filename, Image **image) const;
bool loadImageReformat(const char *filename, Image **image, Image::PixelFormat format) const;
virtual bool saveImage(const Image &image, const char *filename);
virtual int getCommonExtensionCount() const;
virtual const char *getCommonExtension(int index) const;
private:
// disabled
TargaFormat(const TargaFormat&);
TargaFormat &operator =(const TargaFormat&);
};
// ======================================================================
#endif
@@ -0,0 +1,8 @@
// ======================================================================
//
// FirstImage.cpp
// copyright (c) 2001 Sony Online Entertainment
//
// ======================================================================
#include "sharedImage/FirstSharedImage.h"