bluecore/corona/src/corona.h

729 lines
20 KiB
C++

/**
* Corona Image I/O Library
* Version 1.0.2
* (c) 2003 Chad Austin
*
* This API uses principles explained at
* http://aegisknight.org/cppinterface.html
*
* This code licensed under the terms of the zlib license. See
* license.txt.
*
*
* Note: When compiling this header in gcc, you may want to use the
* -Wno-non-virtual-dtor flag to get rid of those annoying "class has
* virtual functions but no virtual destructor" warnings.
*/
#ifndef CORONA_H
#define CORONA_H
#ifndef __cplusplus
#error Corona requires C++
#endif
#include <stddef.h>
// DLLs in Windows should use the standard calling convention
#ifndef COR_CALL
# if defined(WIN32) || defined(_WIN32)
# define COR_CALL __stdcall
# else
# define COR_CALL
# endif
#endif
// Export functions from the DLL
#ifndef COR_DECL
# if defined(WIN32) || defined(_WIN32)
# ifdef CORONA_EXPORTS
# define COR_DECL __declspec(dllexport)
# else
# define COR_DECL
# endif
# else
# define COR_DECL
# endif
#endif
// evil "identifier is too long in debug information" warning
#ifdef _MSC_VER
#pragma warning(disable : 4786)
#endif
#define COR_FUNCTION(ret) extern "C" COR_DECL ret COR_CALL
namespace corona {
/**
* File formats supported for reading or writing.
*/
enum FileFormat {
FF_AUTODETECT = 0x0100,
FF_PNG = 0x0101,
FF_JPEG = 0x0102,
FF_PCX = 0x0103,
FF_BMP = 0x0104,
FF_TGA = 0x0105,
FF_GIF = 0x0106,
};
/**
* Pixel format specifications. Pixel data can be packed in one of
* the following ways.
*/
enum PixelFormat {
PF_DONTCARE = 0x0200, /**< special format used when specifying a
desired pixel format */
PF_R8G8B8A8 = 0x0201, /**< RGBA, channels have eight bits of precision */
PF_R8G8B8 = 0x0202, /**< RGB, channels have eight bits of precision */
PF_I8 = 0x0203, /**< Palettized, 8-bit indices into palette */
PF_B8G8R8A8 = 0x0204, /**< BGRA, channels have eight bits of precision */
PF_B8G8R8 = 0x0205, /**< BGR, channels have eight bits of precision */
};
/**
* Axis specifications. The image can be flipped along the following
* axes.
*/
enum CoordinateAxis {
CA_X = 0x0001,
CA_Y = 0x0002,
};
/**
* A helper class for DLL-compatible interfaces. Derive your cross-DLL
* interfaces from this class.
*
* When deriving from this class, do not declare a virtual destructor
* on your interface.
*/
class DLLInterface {
private:
/**
* Destroy the object, freeing all associated memory. This is
* the same as a destructor.
*/
virtual void COR_CALL destroy() = 0;
public:
/**
* "delete image" should actually call image->destroy(), thus putting the
* burden of calling the destructor and freeing the memory on the image
* object, and thus on Corona's side of the DLL boundary.
*/
void operator delete(void* p) {
if (p) {
DLLInterface* i = static_cast<DLLInterface*>(p);
i->destroy();
}
}
};
/**
* A helper class for DLL-compatible interface implementations. Derive
* your implementations from DLLImplementation<YourInterface>.
*/
template<class Interface>
class DLLImplementation : public Interface {
public:
/**
* So the implementation can put its destruction logic in the destructor,
* as natural C++ code does.
*/
virtual ~DLLImplementation() { }
/**
* Call the destructor in a Win32 ABI-compatible way.
*/
virtual void COR_CALL destroy() {
delete this;
}
/**
* So destroy()'s "delete this" doesn't go into an infinite loop,
* calling the interface's operator delete, which calls destroy()...
*/
void operator delete(void* p) {
::operator delete(p);
}
};
/**
* An image object represents a rectangular collections of pixels.
* They have a width, a height, and a pixel format. Images cannot
* be resized.
*/
class Image : public DLLInterface {
public:
/**
* Get image width.
* @return image width
*/
virtual int COR_CALL getWidth() = 0;
/**
* Get image height.
* @return image height
*/
virtual int COR_CALL getHeight() = 0;
/**
* Get pixel format.
* @return pixel format
*/
virtual PixelFormat COR_CALL getFormat() = 0;
/**
* Get pixel buffer. The pixels are packed in the format defined
* by the image's pixel format.
*
* @return pointer to first element in pixel buffer
*/
virtual void* COR_CALL getPixels() = 0;
/**
* Get the palette. Pixels are packed in the format defined by
* getPaletteFormat().
*
* @return pointer to first palette entry
*/
virtual void* COR_CALL getPalette() = 0;
/**
* Get the number of entries in the palette.
*
* @return number of palette entries
*/
virtual int COR_CALL getPaletteSize() = 0;
/**
* Get the format of the colors in the palette.
*
* @return pixel format of palette entries
*/
virtual PixelFormat COR_CALL getPaletteFormat() = 0;
};
/**
* Represents a random-access file, usually stored on a disk. Files
* are always binary: that is, they do no end-of-line
* transformations. File objects are roughly analogous to ANSI C
* FILE* objects.
*/
class File : public DLLInterface {
public:
/**
* The different ways you can seek within a file.
*/
enum SeekMode {
BEGIN, /**< relative to the beginning of the file */
CURRENT, /**< relative to the current position in the file */
END /**< relative to the end of the file: position should
be negative*/
};
/**
* Read size bytes from the file, storing them in buffer.
*
* @param buffer buffer to read into
* @param size number of bytes to read
*
* @return number of bytes successfully read
*/
virtual int COR_CALL read(void* buffer, int size) = 0;
/**
* Write size bytes from buffer to the file.
*
* @param buffer buffer that contains the data to write
* @param size number of bytes to write
*
* @return number of bytes successfully written
*/
virtual int COR_CALL write(const void* buffer, int size) = 0;
/**
* Jump to a new position in the file, using the specified seek
* mode. Remember: if mode is END, the position must be negative,
* to seek backwards from the end of the file into its contents.
* If the seek fails, the current position is undefined.
*
* @param position position relative to the mode
* @param mode where to seek from in the file
*
* @return true on success, false otherwise
*/
virtual bool COR_CALL seek(int position, SeekMode mode) = 0;
/**
* Get current position within the file.
*
* @return current position
*/
virtual int COR_CALL tell() = 0;
};
/// Describes a file format that Corona supports.
class FileFormatDesc {
protected:
virtual ~FileFormatDesc() { }
public:
/// Actual FileFormat being described.
virtual FileFormat getFormat() = 0;
/// Short description of format, such as "PNG Files" or "JPEG Files"
virtual const char* getDescription() = 0;
/// @{
/// List of supported extensions, such as {"bmp", "rle", "dib"}
virtual size_t getExtensionCount() = 0;
virtual const char* getExtension(size_t i) = 0;
/// @}
};
/// PRIVATE API - for internal use only
namespace hidden {
// these are extern "C" so we don't mangle the names
// API information
COR_FUNCTION(const char*) CorGetVersion();
COR_FUNCTION(FileFormatDesc**) CorGetSupportedReadFormats();
COR_FUNCTION(FileFormatDesc**) CorGetSupportedWriteFormats();
// creation
COR_FUNCTION(Image*) CorCreateImage(
int width,
int height,
PixelFormat format);
COR_FUNCTION(Image*) CorCreateImageWithPixels(
int width,
int height,
PixelFormat format,
void* pixels);
COR_FUNCTION(Image*) CorCreatePalettizedImage(
int width,
int height,
PixelFormat format, // must be a palettized format
int palette_size,
PixelFormat palette_format);
COR_FUNCTION(Image*) CorCloneImage(
Image* source,
PixelFormat format);
// loading
COR_FUNCTION(Image*) CorOpenImage(
const char* filename,
FileFormat file_format);
COR_FUNCTION(Image*) CorOpenImageFromFile(
File* file,
FileFormat file_format);
// saving
COR_FUNCTION(bool) CorSaveImage(
const char* filename,
FileFormat file_format,
Image* image);
COR_FUNCTION(bool) CorSaveImageToFile(
File* file,
FileFormat file_format,
Image* image);
// conversion
COR_FUNCTION(Image*) CorConvertImage(
Image* image,
PixelFormat format);
COR_FUNCTION(Image*) CorConvertPalette(
Image* image,
PixelFormat palette_format);
COR_FUNCTION(Image*) CorFlipImage(
Image* image,
int coordinate_axis);
// files
COR_FUNCTION(File*) CorOpenFile(const char* name, bool writeable);
COR_FUNCTION(File*) CorCreateMemoryFile(const void* buffer, int size);
// utility
COR_FUNCTION(int) CorGetPixelSize(PixelFormat format);
}
/* PUBLIC API */
/**
* Return the Corona version string.
*
* @return Corona version information
*/
inline const char* GetVersion() {
return hidden::CorGetVersion();
}
/**
* Returns a null-terminated array of FileFormatDesc* pointers that
* describe the file formats Corona can read. The array is owned by
* Corona, so do not delete it when you are done using it.
*/
inline FileFormatDesc** GetSupportedReadFormats() {
return hidden::CorGetSupportedReadFormats();
}
/**
* Returns a null-terminated array of FileFormatDesc* pointers that
* describe the file formats Corona can write. The array is owned
* by Corona, so do not delete it when you are done using it.
*/
inline FileFormatDesc** GetSupportedWriteFormats() {
return hidden::CorGetSupportedWriteFormats();
}
/**
* Create a new, blank image with a specified width, height, and
* format. If pixels is specified, Corona uses them to initialize
* the contents of the image. Corona does *not* take ownership of
* the pixel memory, so the caller is responsible for cleaning up
* after itself. If pixels is not specified, the new image is
* filled with zeroes.
*
* @param width width of the new image
* @param height height of the new image
* @param format format the pixels are stored in, cannot be PF_DONTCARE
* @param pixels pixel buffer used to initialize the new image
*
* @return newly created blank image
*/
inline Image* CreateImage(
int width,
int height,
PixelFormat format,
void* pixels = 0)
{
return hidden::CorCreateImageWithPixels(width, height, format, pixels);
}
/**
* Create a new, blank image with a specified width, height, format,
* and palette.
*
* @param width width of image
* @param height height of image
* @param format format of palette indices, should be PF_I8
* @param palette_size number of colors in palette
* @param palette_format pixel format of palette entries
*/
inline Image* CreateImage(
int width,
int height,
PixelFormat format,
int palette_size,
PixelFormat palette_format)
{
return hidden::CorCreatePalettizedImage(
width, height, format,
palette_size, palette_format);
}
/**
* Create a new image from an old one. If format is specified, the
* new image is converted to that pixel format. If format is not
* specified, the new image simply uses the same format as the
* source. If the image could not be cloned or the pixel format is
* invalid, CloneImage returns 0.
*
* @param source image to clone
* @param format format the new image is stored in, defaults to PF_DONTCARE
*
* @return new image cloned from the source, 0 if failure
*/
inline Image* CloneImage(
Image* source,
PixelFormat format = PF_DONTCARE)
{
return hidden::CorCloneImage(source, format);
}
/**
* Opens an image from the default filesystem. This function simply
* forwards the call to OpenImage(file, file_format, pixel_format)
* with a standard C library file.
*
* See OpenImage(fs, filename, file_format, pixel_format) for more
* information.
*
* @param filename image filename to open
* @param file_format file format the image is stored in, or FF_AUTODETECT
* to try all loaders
* @param pixel_format desired pixel format, or PF_DONTCARE to use image's
* native format
*
* @return the image loaded from the disk, or 0 if it cannot be opened
*/
inline Image* OpenImage(
const char* filename,
PixelFormat pixel_format = PF_DONTCARE,
FileFormat file_format = FF_AUTODETECT)
{
return hidden::CorConvertImage(
hidden::CorOpenImage(filename, file_format),
pixel_format);
}
/**
* Opens an image from the specified file.
*
* If file_format is FF_AUTODETECT, the loader tries
* to load each format until it finds one that succeeds. Otherwise,
* it tries the specific loader specified.
*
* If pixel_format is PF_DONTCARE, the new image object has the
* pixel format closest to the image's format on disk. Otherwise,
* the pixels are converted to the specified format before the image
* is returned.
*
* @param file name of the file that contains the image
* @param file_format file format the image is stored in, or FF_AUTODETECT
* to try all loaders
* @param pixel_format desired pixel format, or PF_DONTCARE to use image's
* native format
*
* @return the image loaded from the file, or 0 if it cannot be opened
*/
inline Image* OpenImage(
File* file,
PixelFormat pixel_format = PF_DONTCARE,
FileFormat file_format = FF_AUTODETECT)
{
return hidden::CorConvertImage(
hidden::CorOpenImageFromFile(file, file_format),
pixel_format);
}
/// For compatibility. This function may be deprecated.
inline Image* OpenImage(
const char* filename,
FileFormat file_format,
PixelFormat pixel_format = PF_DONTCARE)
{
return OpenImage(filename, pixel_format, file_format);
}
/// For compatibility. This function may be deprecated.
inline Image* OpenImage(
File* file,
FileFormat file_format,
PixelFormat pixel_format = PF_DONTCARE)
{
return OpenImage(file, pixel_format, file_format);
}
/**
* Saves an image to a file in the default filesystem. This
* function simply calls SaveImage(file, file_format, image)
* with a standard C library file.
*
* See SaveImage(fs, filename, file_format, image) for more information.
*
* @param filename name of the file to save the image to
* @param file_format file format in which to save image. if FF_AUTODETECT,
* SaveImage guesses the type from the file extension
* @param image image to save
*
* @return true if save succeeds, false otherwise
*/
inline bool SaveImage(
const char* filename,
FileFormat file_format,
Image* image)
{
return hidden::CorSaveImage(filename, file_format, image);
}
/**
* Saves an image to the specified file. This function saves image
* to a file of type file_format. If file_format is not a supported
* output type, the function fails. As of now, Corona only supports
* saving images of type FF_PNG and FF_TGA.
*
* @note This function may create the file even if the save does not
* succeed, so users of this library should remove the file after
* the call to SaveImage().
*
* @param file file in which to save the image
* @param file_format file format in which to save image -- must not be
* FF_AUTODETECT
* @param image image to save
*
* @return true if the save succeeds, false otherwise
*/
inline bool SaveImage(
File* file,
FileFormat file_format,
Image* image)
{
return hidden::CorSaveImageToFile(file, file_format, image);
}
/**
* Converts an image from one format to another, destroying the old
* image. If source is 0, the function returns 0. If format is
* PF_DONTCARE or the source and target formats match, returns the
* unmodified source image. If a valid conversion is not found,
* ConvertImage destroys the old image and returns 0. For example,
* ConvertImage does not support creating a palettized image from a
* direct color image yet.
*
* @param source image to convert
* @param format desired format -- can be PF_DONTCARE
*
* @return valid image object if conversion succeeds, 0 otherwise
*/
inline Image* ConvertImage(Image* source, PixelFormat format) {
return hidden::CorConvertImage(source, format);
}
/**
* Converts the palette of a palettized image from one format to
* another, destroying the old image. If the source is 0, the
* palette_format is PF_DONTCARE, or the source and target formats
* match, the function returns the unmodified source image. If a
* valid conversion is not found or invalid inputs are given (such
* as a direct-color source image), this function destroys the old
* image and returns 0.
*
* @param source palettized image to convert
* @param palette_format desired pixel format of palette
*
* @return valid image object if conversion succeeds, 0 otherwise
*/
inline Image* ConvertPalette(Image* source, PixelFormat palette_format) {
return hidden::CorConvertPalette(source, palette_format);
}
/**
* Flips the pixels in the image around the given axis.
*
* @param source image to flip
* @param coordinate_axis Axis around which to flip. Both CA_X and CA_Y
* can be specified by ORing them together.
*
* @return the image passed in
*/
inline Image* FlipImage(Image* source, int coordinate_axis) {
return hidden::CorFlipImage(source, coordinate_axis);
}
/**
* Returns a default File implementation.
*
* @param filename name of the file on local filesystem
* @param writeable whether the file can be written to
*/
inline File* OpenFile(const char* filename, bool writeable) {
return hidden::CorOpenFile(filename, writeable);
}
/**
* Creates a File implementation that reads from a buffer in memory.
* It stores a copy of the buffer that is passed in.
*
* The File object does <i>not</i> take ownership of the memory buffer.
* When the file is destroyed, it will not free the memory.
*
* @param buffer Pointer to the beginning of the data.
* @param size Size of the buffer in bytes.
*
* @return 0 if size is non-zero and buffer is null. Otherwise,
* returns a valid File object.
*/
inline File* CreateMemoryFile(const void* buffer, int size) {
return hidden::CorCreateMemoryFile(buffer, size);
}
/**
* Returns the number of bytes needed to store a pixel of a gixen format.
*
* @param format The format to query.
*
* @return Number of bytes each pixel takes, or 0 if the format is invalid.
*/
inline int GetPixelSize(PixelFormat format) {
return hidden::CorGetPixelSize(format);
}
/**
* Returns true if the pixel format does not require a palette; that
* is, if each pixel itself contains color data.
*
* @param format The format to query.
*
* @return True if format is direct color, false otherwise.
*/
inline bool IsDirect(PixelFormat format) {
return (format == PF_R8G8B8A8 || format == PF_R8G8B8 ||
format == PF_B8G8R8A8 || format == PF_B8G8R8);
}
/**
* Returns true if the pixel format requires a palette; that
* is, if each pixel is an index into a separate palette.
*
* @param format The format to query.
*
* @return True if format is palettized, false otherwise.
*/
inline bool IsPalettized(PixelFormat format) {
return format == PF_I8;
}
/**
* Returns the number of color entries in a palette for an image
* of the given format.
*
* @param format The format to query.
*
* @return Number of color entries, or 0 if the format is not palettized.
*/
inline int GetPaletteSize(PixelFormat format) {
return (format == PF_I8 ? 256 : 0);
}
}
#endif