mirror of
https://github.com/SWG-Source/src.git
synced 2026-08-04 04:16:02 -04:00
Added sharedImage library
This commit is contained in:
@@ -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"
|
||||
Reference in New Issue
Block a user