diff options
Diffstat (limited to 'include')
35 files changed, 7190 insertions, 0 deletions
diff --git a/include/im.h b/include/im.h new file mode 100644 index 0000000..8091e77 --- /dev/null +++ b/include/im.h @@ -0,0 +1,282 @@ +/** \file + * \brief Main API + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_H +#define __IM_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** Image data type descriptors. \n + * See also \ref datatypeutl. + * \ingroup imagerep */ +enum imDataType +{ + IM_BYTE, /**< "unsigned char". 1 byte from 0 to 255. */ + IM_USHORT, /**< "unsigned short". 2 bytes from 0 to 65,535. */ + IM_INT, /**< "int". 4 bytes from -2,147,483,648 to 2,147,483,647. */ + IM_FLOAT, /**< "float". 4 bytes single precision IEEE floating point. */ + IM_CFLOAT /**< complex "float". 2 float values in sequence, real and imaginary parts. */ +}; + +/** Image color mode color space descriptors (first byte). \n + * See also \ref colormodeutl. + * \ingroup imagerep */ +enum imColorSpace +{ + IM_RGB, /**< Red, Green and Blue (nonlinear). */ + IM_MAP, /**< Indexed by RGB color map (data_type=IM_BYTE). */ + IM_GRAY, /**< Shades of gray, luma (nonlinear Luminance), or an intensity value that is not related to color. */ + IM_BINARY, /**< Indexed by 2 colors: black (0) and white (1) (data_type=IM_BYTE). */ + IM_CMYK, /**< Cian, Magenta, Yellow and Black (nonlinear). */ + IM_YCBCR, /**< ITU-R 601 Y'CbCr. Y' is luma (nonlinear Luminance). */ + IM_LAB, /**< CIE L*a*b*. L* is Lightness (nonlinear Luminance, nearly perceptually uniform). */ + IM_LUV, /**< CIE L*u*v*. L* is Lightness (nonlinear Luminance, nearly perceptually uniform). */ + IM_XYZ /**< CIE XYZ. Linear Light Tristimulus, Y is linear Luminance. */ +}; + +/** Image color mode configuration/extra descriptors (1 bit each in the second byte). \n + * See also \ref colormodeutl. + * \ingroup imagerep */ +enum imColorModeConfig +{ + IM_ALPHA = 0x100, /**< adds an Alpha channel */ + IM_PACKED = 0x200, /**< packed components (rgbrgbrgb...) */ + IM_TOPDOWN = 0x400 /**< orientation from top down to bottom */ +}; + + + +/** File Access Error Codes + * \ingroup file */ +enum imErrorCodes +{ + IM_ERR_NONE, /**< No error. */ + IM_ERR_OPEN, /**< Error while opening the file (read or write). */ + IM_ERR_ACCESS, /**< Error while accessing the file (read or write). */ + IM_ERR_FORMAT, /**< Invalid or unrecognized file format. */ + IM_ERR_DATA, /**< Invalid or unsupported data. */ + IM_ERR_COMPRESS, /**< Invalid or unsupported compression. */ + IM_ERR_MEM, /**< Insuficient memory */ + IM_ERR_COUNTER /**< Interrupted by the counter */ +}; + +/* Internal Image File Structure. */ +typedef struct _imFile imFile; + +/** Opens the file for reading. It must exists. Also reads file header. + * It will try to identify the file format. + * See also \ref imErrorCodes. \n + * In Lua the IM file metatable name is "imFile". + * When converted to a string will return "imFile(%p)" where %p is replaced by the userdata address. + * If the file is already closed by im.FileClose, then it will return also the suffix "-closed". + * + * \verbatim im.FileOpen(file_name: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup file */ +imFile* imFileOpen(const char* file_name, int *error); + +/** Opens the file for reading using a specific format. It must exists. Also reads file header. + * See also \ref imErrorCodes and \ref format. + * + * \verbatim im.FileOpenAs(file_name, format: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup file */ +imFile* imFileOpenAs(const char* file_name, const char* format, int *error); + +/** Creates a new file for writing using a specific format. If the file exists will be replaced. \n + * It will only initialize the format driver and create the file, no data is actually written. + * See also \ref imErrorCodes and \ref format. + * + * \verbatim im.FileNew(file_name: string, format: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup file */ +imFile* imFileNew(const char* file_name, const char* format, int *error); + +/** Closes the file. \n + * In Lua if this function is not called, the file is closed by the garbage collector. + * + * \verbatim im.FileClose(ifile: imFile) [in Lua 5] \endverbatim + * \verbatim ifile:Close() [in Lua 5] \endverbatim + * \ingroup file */ +void imFileClose(imFile* ifile); + +/** Returns an internal handle. + * index=0 returns always an imBinFile* handle, + * but for some formats returns NULL because they do not use imBinFile (like AVI and WMV). + * index=1 return an internal structure used by the format, usually is a handle + * to a third party library structure. This is file format dependent. + * + * \verbatim ifile:Handle() -> handle: userdata [in Lua 5] \endverbatim + * \ingroup file */ +void* imFileHandle(imFile* ifile, int index); + +/** Returns file information. + * image_count is the number of images in a stack or + * the number of frames in a video/animation or the depth of a volume data. \n + * compression and image_count can be NULL. + * See also \ref format. + * + * \verbatim ifile:GetInfo() -> format: string, compression: string, image_count: number [in Lua 5] \endverbatim + * \ingroup file */ +void imFileGetInfo(imFile* ifile, char* format, char* compression, int *image_count); + +/** Changes the write compression method. \n + * If the compression is not supported will return an error code when writting. \n + * Use NULL to set the default compression. You can use the imFileGetInfo to retrieve the actual compression + * but only after \ref imFileWriteImageInfo. Only a few formats allow you to change the compression between frames. + * + * \verbatim ifile:SetInfo(compression: string) [in Lua 5] \endverbatim + * \ingroup file */ +void imFileSetInfo(imFile* ifile, const char* compression); + +/** Changes an extended attribute. \n + * The data will be internally duplicated. \n + * If data is NULL the attribute is removed. + * See also \ref imDataType. + * + * \verbatim ifile:SetAttribute(attrib: string, data_type: number, data: table of numbers or string) [in Lua 5] \endverbatim + * If data_type is IM_BYTE, as_string can be used as data. + * \ingroup file */ +void imFileSetAttribute(imFile* ifile, const char* attrib, int data_type, int count, const void* data); + +/** Returns an extended attribute. \n + * Returns NULL if not found. data_type and count can be NULL. + * See also \ref imDataType. + * + * \verbatim ifile:GetAttribute(attrib: string, [as_string: boolean]) -> data: table of numbers or string, data_type: number [in Lua 5] \endverbatim + * If data_type is IM_BYTE, as_string can be used to return a string instead of a table. + * \ingroup file */ +const void* imFileGetAttribute(imFile* ifile, const char* attrib, int *data_type, int *count); + +/** Returns a list of the attribute names. \n + * "attrib" must contain room enough for "attrib_count" names. Use "attrib=NULL" to return only the count. + * + * \verbatim ifile:GetAttributeList() -> data: table of strings [in Lua 5] \endverbatim + * \ingroup file */ +void imFileGetAttributeList(imFile* ifile, char** attrib, int *attrib_count); + +/** Returns the pallete if any. \n + * "palette" must be a 256 colors alocated array. \n + * Returns zero in "palette_count" if there is no palette. "palette_count" is >0 and <=256. + * + * \verbatim ifile:GetPalette() -> palette: imPalette [in Lua 5] \endverbatim + * \ingroup file */ +void imFileGetPalette(imFile* ifile, long* palette, int *palette_count); + +/** Changes the pallete. \n + * "palette_count" is >0 and <=256. + * + * \verbatim ifile:SetPalette(palette: imPalette) [in Lua 5] \endverbatim + * \ingroup file */ +void imFileSetPalette(imFile* ifile, long* palette, int palette_count); + +/** Reads the image header if any and returns image information. \n + * Reads also the extended image attributes, so other image attributes will be available only after calling this function. \n + * Returns an error code. + * index specifies the image number between 0 and image_count-1. \n + * Some drivers reads only in sequence, so "index" can be ignored by the format driver. \n + * Any parameters can be NULL. This function must be called at least once, check each format documentation. + * See also \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim ifile:ReadImageInfo([index: number]) -> error: number, width: number, height: number, file_color_mode: number, file_data_type: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup file */ +int imFileReadImageInfo(imFile* ifile, int index, int *width, int *height, int *file_color_mode, int *file_data_type); + +/** Writes the image header. Writes the file header at the first time it is called. + * Writes also the extended image attributes. \n + * Must call imFileSetPalette and set other attributes before calling this function. \n + * In some formats the color space will be converted to match file format specification. \n + * Returns an error code. This function must be called at least once, check each format documentation. + * See also \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim ifile:WriteImageInfo(width: number, height: number, user_color_mode: number, user_data_type: number) -> error: number [in Lua 5] \endverbatim + * \ingroup file */ +int imFileWriteImageInfo(imFile* ifile, int width, int height, int user_color_mode, int user_data_type); + +/** Reads the image data with or without conversion. \n + * The data can be converted to bitmap when reading. + * Data type conversion to byte will always scan for min-max then scale to 0-255, + * except integer values that min-max are already between 0-255. Complex to real conversions will use the magnitude. \n + * Color mode flags contains packed, alpha and top-botttom information. + * If flag is 0 means unpacked, no alpha and bottom up. If flag is -1 the file original flags are used. \n + * Returns an error code. + * See also \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim ifile:ReadImageData(data: userdata, convert2bitmap: bool, color_mode_flags: number) -> error: number [in Lua 5] \endverbatim + * \ingroup file */ +int imFileReadImageData(imFile* ifile, void* data, int convert2bitmap, int color_mode_flags); + +/** Writes the image data. \n + * Returns an error code. + * + * \verbatim ifile:WriteImageData(data: userdata) -> error: number [in Lua 5] \endverbatim + * \ingroup file */ +int imFileWriteImageData(imFile* ifile, void* data); + + + + +/** Registers all the internal formats. \n + * It is automatically called internally when a format is accessed, + * but can be called to force the internal formats to be registered before other formats. + * Notice that additional formats when registered will be registered before the internal formats + * if imFormatRegisterInternal is not called yet. \n + * To control the register order is usefull when two format drivers handle the same format. + * The first registered format will always be used first. + * \ingroup format */ +void imFormatRegisterInternal(void); + +/** Remove all registered formats. + * \ingroup format */ +void imFormatRemoveAll(void); + +/** Returns a list of the registered formats. \n + * format_list is an array of format identifiers. + * Each format identifier is 10 chars max, maximum of 50 formats. + * You can use "char* format_list[50]". + * + * \verbatim im.FormatList() -> format_list: table of strings [in Lua 5] \endverbatim + * \ingroup format */ +void imFormatList(char** format_list, int *format_count); + +/** Returns the format description. \n + * Format description is 50 chars max. \n + * Extensions are separated like "*.tif;*.tiff;", 50 chars max. \n + * Returns an error code. The parameters can be NULL, except format. + * See also \ref format. + * + * \verbatim im.FormatInfo(format: string) -> error: number, desc: string, ext: string, can_sequence: boolean [in Lua 5] \endverbatim + * \ingroup format */ +int imFormatInfo(const char* format, char* desc, char* ext, int *can_sequence); + +/** Returns the format compressions. \n + * Compressions are 20 chars max each, maximum of 50 compressions. You can use "char* comp[50]". \n + * color_mode and data_type are optional, use -1 to ignore them. \n + * If you use them they will select only the allowed compressions checked like in \ref imFormatCanWriteImage. \n + * Returns an error code. + * See also \ref format, \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim im.FormatCompressions(format: string, [color_mode: number], [data_type: number]) -> error: number, comp: table of strings [in Lua 5] \endverbatim + * \ingroup format */ +int imFormatCompressions(const char* format, char** comp, int *comp_count, int color_mode, int data_type); + +/** Checks if the format suport the given image class at the given compression. \n + * Returns an error code. + * See also \ref format, \ref imErrorCodes, \ref imDataType, \ref imColorSpace and \ref imColorModeConfig. + * + * \verbatim im.FormatCanWriteImage(format: string, compression: string, color_mode: number, data_type: number) -> can_write: boolean [in Lua 5] \endverbatim + * \ingroup format */ +int imFormatCanWriteImage(const char* format, const char* compression, int color_mode, int data_type); + + +#if defined(__cplusplus) +} +#endif + +#include "old_im.h" + +#endif diff --git a/include/im_attrib.h b/include/im_attrib.h new file mode 100644 index 0000000..2a7cfb6 --- /dev/null +++ b/include/im_attrib.h @@ -0,0 +1,116 @@ +/** \file + * \brief Attributes Table. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_ATTRIB_H_ +#define __IM_ATTRIB_H_ + +#include "im_attrib_flat.h" + +/** \brief Attributes Table. + * + * \par + * All the attributes have a name, a type, a count and the data.\n + * Names are usually strings with less that 30 chars. + * \par + * Attributes are stored in a hash table for fast access. \n + * We use the hash function described in "The Pratice of Programming" of Kernighan & Pike. + * \ingroup util */ +class imAttribTable +{ + imAttribTablePrivate* ptable; +public: + + /** Creates an empty table. + * If size is zero the default size of 101 is used. Size must be a prime number. + * Other common values are 67, 599 and 1499.*/ + imAttribTable(int hash_size) + { ptable = imAttribTableCreate(hash_size); } + + /** Destroys the table and all the attributes. */ + ~imAttribTable() + { imAttribTableDestroy(ptable); ptable = 0; } + + /** Returns the number of elements in the table. */ + int Count() const + { return imAttribTableCount(ptable); } + + /** Removes all the attributes in the table */ + void RemoveAll() + { imAttribTableRemoveAll(ptable); } + + /** Copies the contents of the given table into this table. */ + void CopyFrom(const imAttribTable& table) + { imAttribTableCopyFrom(ptable, table.ptable); } + + /** Inserts an attribute into the table. \n + * Data is duplicated if not NULL, else data is initialized with zeros. + * See also \ref imDataType. */ + void Set(const char* name, int data_type, int count, const void* data) + { imAttribTableSet(ptable, name, data_type, count, data); } + + /** Removes an attribute from the table given its name. */ + void UnSet(const char *name) + { imAttribTableUnSet(ptable, name); } + + /** Finds an attribute in the table. + * Returns the attribute if found, NULL otherwise. + * See also \ref imDataType. */ + const void* Get(const char *name, int *data_type = 0, int *count = 0) const + { return imAttribTableGet(ptable, name, data_type, count); } + + /** For each attribute calls the user callback. If the callback returns 0 the function returns. */ + void ForEach(void* user_data, imAttribTableCallback attrib_func) const + { imAttribTableForEach(ptable, user_data, attrib_func); } +}; + +/** \brief Attributes Table. + * + * \par + * Same as \ref imAttribTable, but uses an array of fixed size. + * \ingroup util */ +class imAttribArray +{ + imAttribTablePrivate* ptable; +public: + + /** Creates an empty array. */ + imAttribArray(int count) + { ptable = imAttribArrayCreate(count); } + + /** Destroys the array and all the attributes. */ + ~imAttribArray() + { imAttribTableDestroy(ptable); ptable = 0; } + + /** Returns the number of elements in the array. */ + int Count() const + { return imAttribTableCount(ptable); } + + /** Removes all the attributes in the array */ + void RemoveAll() + { imAttribTableRemoveAll(ptable); } + + /** Copies the contents of the given table into this table. */ + void CopyFrom(const imAttribArray& table) + { imAttribArrayCopyFrom(ptable, table.ptable); } + + /** Inserts an attribute into the array. \n + * Data is duplicated if not NULL, else data is initialized with zeros. + * See also \ref imDataType. */ + void Set(int index, const char* name, int data_type, int count, const void* data) + { imAttribArraySet(ptable, index, name, data_type, count, data); } + + /** Finds an attribute in the array. + * Returns the attribute if found, NULL otherwise. + * See also \ref imDataType. */ + const void* Get(int index, char *name = 0, int *data_type = 0, int *count = 0) const + { return imAttribArrayGet(ptable, index, name, data_type, count); } + + /** For each attribute calls the user callback. If the callback returns 0 the function returns. */ + void ForEach(void* user_data, imAttribTableCallback attrib_func) const + { imAttribTableForEach(ptable, user_data, attrib_func); } +}; + +#endif diff --git a/include/im_attrib_flat.h b/include/im_attrib_flat.h new file mode 100644 index 0000000..db6c2d8 --- /dev/null +++ b/include/im_attrib_flat.h @@ -0,0 +1,39 @@ +/** \file + * \brief Attributes Table Flat API. + * This will simplify the DLL export, and can be used for C aplications. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_ATTRIB_FLAT_H_ +#define __IM_ATTRIB_FLAT_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +struct imAttribTablePrivate; + +/** Definition of the callback used in ForEach function. */ +typedef int (*imAttribTableCallback)(void* user_data, int index, const char* name, int data_type, int count, const void* data); + +imAttribTablePrivate* imAttribTableCreate(int hash_size); +void imAttribTableDestroy(imAttribTablePrivate* ptable); +int imAttribTableCount(imAttribTablePrivate* ptable); +void imAttribTableRemoveAll(imAttribTablePrivate* ptable); +const void* imAttribTableGet(const imAttribTablePrivate* ptable, const char *name, int *data_type, int *count); +void imAttribTableSet(imAttribTablePrivate* ptable, const char* name, int data_type, int count, const void* data); +void imAttribTableUnSet(imAttribTablePrivate* ptable, const char *name); +void imAttribTableCopyFrom(imAttribTablePrivate* ptable_dst, const imAttribTablePrivate* ptable_src); +void imAttribTableForEach(const imAttribTablePrivate* ptable, void* user_data, imAttribTableCallback attrib_func); + +imAttribTablePrivate* imAttribArrayCreate(int hash_size); +const void* imAttribArrayGet(const imAttribTablePrivate* ptable, int index, char *name, int *data_type, int *count); +void imAttribArraySet(imAttribTablePrivate* ptable, int index, const char* name, int data_type, int count, const void* data); +void imAttribArrayCopyFrom(imAttribTablePrivate* ptable_dst, const imAttribTablePrivate* ptable_src); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_binfile.h b/include/im_binfile.h new file mode 100644 index 0000000..6bac31e --- /dev/null +++ b/include/im_binfile.h @@ -0,0 +1,214 @@ +/** \file + * \brief Binary File Access. + * + * See Copyright Notice in im_lib.h + */ + +#include "im_util.h" + +#ifndef __IM_BINFILE_H +#define __IM_BINFILE_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup binfile Binary File Access + * + * \par + * These functions are very usefull for reading/writing binary files + * that have headers or data that have to be converted depending on + * the current CPU byte order. It can invert 2, 4 or 8 bytes numbers to/from little/big-endian orders. + * \par + * It will process the data only if the file format is diferent from the current CPU. + * \par + * Can read from disk or memory. In case of a memory buffer, the file name must be the \ref imBinMemoryFileName structure. + * \par + * See \ref im_binfile.h + * \ingroup util */ + +typedef struct _imBinFile imBinFile; + +/** Opens an existant binary file for reading. + * The default file byte order is the CPU byte order. + * Returns NULL if failed. + * \ingroup binfile */ +imBinFile* imBinFileOpen(const char* pFileName); + +/** Creates a new binary file for writing. + * The default file byte order is the CPU byte order. + * Returns NULL if failed. + * \ingroup binfile */ +imBinFile* imBinFileNew(const char* pFileName); + +/** Closes the file. + * \ingroup binfile */ +void imBinFileClose(imBinFile* bfile); + +/** Indicates that was an error on the last operation. + * \ingroup binfile */ +int imBinFileError(imBinFile* bfile); + +/** Returns the file size in bytes. + * \ingroup binfile */ +unsigned long imBinFileSize(imBinFile* bfile); + +/** Changes the file byte order. Returns the old one. + * \ingroup binfile */ +int imBinFileByteOrder(imBinFile* bfile, int pByteOrder); + +/** Reads an array of count values with byte sizes: 1, 2, 4, or 8. And invert the byte order if necessary after read. + * \ingroup binfile */ +unsigned long imBinFileRead(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf); + +/** Writes an array of values with sizes: 1, 2, 4, or 8. And invert the byte order if necessary before write.\n + * <b>ATENTION</b>: The function will not make a temporary copy of the values to invert the byte order.\n + * So after the call the values will be invalid, if the file byte order is diferent from the CPU byte order. + * \ingroup binfile */ +unsigned long imBinFileWrite(imBinFile* bfile, void* pValues, unsigned long pCount, int pSizeOf); + +/** Writes a string without the NULL terminator. The function uses sprintf to compose the string. \n + * The internal buffer is fixed at 4096 bytes. + * \ingroup binfile */ +unsigned long imBinFilePrintf(imBinFile* bfile, char *format, ...); + +/** Moves the file pointer from the begining of the file.\n + * When writing to a file seeking can go beyond the end of the file. + * \ingroup binfile */ +void imBinFileSeekTo(imBinFile* bfile, unsigned long pOffset); + +/** Moves the file pointer from current position.\n + * If the offset is a negative value the pointer moves backwards. + * \ingroup binfile */ +void imBinFileSeekOffset(imBinFile* bfile, long pOffset); + +/** Moves the file pointer from the end of the file.\n + * The offset is usually a negative value. + * \ingroup binfile */ +void imBinFileSeekFrom(imBinFile* bfile, long pOffset); + +/** Returns the current offset position. + * \ingroup binfile */ +unsigned long imBinFileTell(imBinFile* bfile); + +/** Indicates that the file pointer is at the end of the file. + * \ingroup binfile */ +int imBinFileEndOfFile(imBinFile* bfile); + +/** Predefined I/O Modules. + * \ingroup binfile */ +enum imBinFileModule +{ + IM_RAWFILE, /**< System dependent file I/O Rotines. */ + IM_STREAM, /**< Standard Ansi C Stream I/O Rotines. */ + IM_MEMFILE, /**< Uses a memory buffer (see \ref imBinMemoryFileName). */ + IM_SUBFILE, /**< It is a sub file. FileName is a imBinFile* pointer from any other module. */ + IM_FILEHANDLE,/**< System dependent file I/O Rotines, but FileName is a system file handle ("int" in UNIX and "HANDLE" in Windows). */ + IM_IOCUSTOM0 /**< Other registered modules starts from here. */ +}; + +/** Sets the current I/O module. + * \returns the previous function set, or -1 if failed. + * See also \ref imBinFileModule. + * \ingroup binfile */ +int imBinFileSetCurrentModule(int pModule); + +/** \brief Memory File I/O Filename + * + * \par + * Fake file name for the memory I/O module. + * \ingroup binfile */ +typedef struct _imBinMemoryFileName +{ + unsigned char *buffer; /**< The memory buffer. If you are reading the buffer must exists. + * If you are writing the buffer can be internally allocated to the given size. The buffer is never free. + * The buffer is allocated using "malloc", and reallocated using "realloc". Use "free" to release it. + * To avoid RTL conflicts use the function imBinMemoryRelease. */ + int size; /**< Size of the buffer. */ + float reallocate; /**< Reallocate factor for the memory buffer when writing (size += reallocate*size). + * Set reallocate to 0 to disable reallocation, in this case buffer must not be NULL. */ +}imBinMemoryFileName; + +/** Release the internal memory allocated when writing a Memory File (see \ref imBinMemoryFileName). + * \ingroup binfile */ +void imBinMemoryRelease(unsigned char *buffer); + + +#if defined(__cplusplus) +} +#endif + + +#if defined(__cplusplus) + +/** Base class to help the creation of new modules.\n + * It handles the read/write operations with byte order correction if necessary. + * \ingroup binfile */ +class imBinFileBase +{ + friend class imBinSubFile; + +protected: + int IsNew, + FileByteOrder, + DoByteOrder; // to speed up byte order checking + + // These will actually read/write the data + virtual unsigned long ReadBuf(void* pValues, unsigned long pSize) = 0; + virtual unsigned long WriteBuf(void* pValues, unsigned long pSize) = 0; + +public: + + int InitByteOrder(int ByteOrder) + { + int old_byte_order = this->FileByteOrder; + this->FileByteOrder = ByteOrder; + + if (ByteOrder != imBinCPUByteOrder()) + this->DoByteOrder = 1; + else + this->DoByteOrder = 0; + return old_byte_order; + } + + // These will take care of byte swap if needed. + + unsigned long Read(void* pValues, unsigned long pCount, int pSizeOf) + { + unsigned long rSize = ReadBuf(pValues, pCount * pSizeOf); + if (pSizeOf != 1 && DoByteOrder) imBinSwapBytes(pValues, pCount, pSizeOf); + return rSize/pSizeOf; + } + + unsigned long Write(void* pValues, unsigned long pCount, int pSizeOf) + { + if (pSizeOf != 1 && DoByteOrder) imBinSwapBytes(pValues, pCount, pSizeOf); + return WriteBuf(pValues, pCount * pSizeOf)/pSizeOf; + } + + virtual void Open(const char* pFileName) = 0; + virtual void New(const char* pFileName) = 0; + virtual void Close() = 0; + virtual unsigned long FileSize() = 0; + virtual int HasError() const = 0; + virtual void SeekTo(unsigned long pOffset) = 0; + virtual void SeekOffset(long pOffset) = 0; + virtual void SeekFrom(long pOffset) = 0; + virtual unsigned long Tell() const = 0; + virtual int EndOfFile() const = 0; +}; + +/** File I/O module creation callback. + * \ingroup binfile */ +typedef imBinFileBase* (*imBinFileNewFunc)(); + +/** Register a user I/O module.\n + * Returns the new function set id.\n + * Accepts up to 10 modules. + * \ingroup binfile */ +int imBinFileRegisterModule(imBinFileNewFunc pNewFunc); + +#endif + +#endif diff --git a/include/im_capture.h b/include/im_capture.h new file mode 100644 index 0000000..7c130a3 --- /dev/null +++ b/include/im_capture.h @@ -0,0 +1,365 @@ +/** \file + * \brief Video Capture + * + * See Copyright Notice in im.h + */ + +#ifndef __IM_CAPTURE_H +#define __IM_CAPTURE_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/* declarations to create an export library for Watcom. */ +#if ! defined (IM_DECL) + #if defined (__WATCOMC__) + #define IM_DECL __cdecl + #elif defined(__WATCOM_CPLUSPLUS__) + #define IM_DECL __cdecl + #else + #define IM_DECL + #endif +#endif + +/** \defgroup capture Image Capture + * \par + * Functions to capture images from live video devices. + * \par + * See \ref im_capture.h + */ + +typedef struct _imVideoCapture imVideoCapture; + +/** Returns the number of available devices. + * + * \verbatim im.VideoCaptureDeviceCount() -> count: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureDeviceCount(void); + +/** Returns the device description. Returns NULL only if it is an invalid device. + * + * \verbatim im.VideoCaptureDeviceDesc(device: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* IM_DECL imVideoCaptureDeviceDesc(int device); + +/** Returns the extendend device description. May return NULL. + * + * \verbatim im.VideoCaptureDeviceExDesc(device: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* imVideoCaptureDeviceExDesc(int device); + +/** Returns the device path configuration. This is a unique string. + * + * \verbatim im.VideoCaptureDevicePath(device: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* imVideoCaptureDevicePath(int device); + +/** Returns the vendor information. May return NULL. + * + * \verbatim im.VideoCaptureDeviceVendorInfo(device: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* imVideoCaptureDeviceVendorInfo(int device); + +/** Reload the device list. The devices can be dynamically removed or added to the system. + * Returns the number of available devices. + * + * \verbatim im.imVideoCaptureReloadDevices() -> count: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureReloadDevices(void); + +/** Creates a new imVideoCapture object. \n + * Returns NULL if there is no capture device available. \n + * In Windows returns NULL if DirectX version is older than 8. \n + * In Lua the IM videocapture metatable name is "imVideoCapture". + * When converted to a string will return "imVideoCapture(%p)" where %p is replaced by the userdata address. + * If the videocapture is already destroyed by im.VideoCaptureDestroy, then it will return also the suffix "-destroyed". + * + * \verbatim im.VideoCaptureCreate() -> vc: imVideoCapture [in Lua 5] \endverbatim + * \ingroup capture */ +imVideoCapture* IM_DECL imVideoCaptureCreate(void); + +/** Destroys a imVideoCapture object. \n + * In Lua if this function is not called, the videocapture is destroyed by the garbage collector. + * + * \verbatim im.VideoCaptureDestroy(vc: imVideoCapture) [in Lua 5] \endverbatim + * \verbatim vc:Destroy() [in Lua 5] \endverbatim + * \ingroup capture */ +void IM_DECL imVideoCaptureDestroy(imVideoCapture* vc); + +/** Connects to a capture device. + * More than one imVideoCapture object can be created + * but they must be connected to different devices. \n + * If the object is conected it will disconnect first. \n + * Use -1 to return the current connected device, + * in this case returns -1 if not connected. \n + * Returns zero if failed. + * + * \verbatim vc:Connect([device: number]) -> ret: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureConnect(imVideoCapture* vc, int device); + +/** Disconnect from a capture device. + * + * \verbatim vc:Disconnect() [in Lua 5] \endverbatim + * \ingroup capture */ +void IM_DECL imVideoCaptureDisconnect(imVideoCapture* vc); + +/** Returns the number of available configuration dialogs. + * + * \verbatim vc:DialogCount() -> count: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureDialogCount(imVideoCapture* vc); + +/** Displays a configuration modal dialog of the connected device. \n + * In Windows, the capturing will be stopped in some cases. \n + * In Windows parent is a HWND of a parent window, it can be NULL. \n + * dialog can be from 0 to \ref imVideoCaptureDialogCount. \n + * Returns zero if failed. + * + * \verbatim vc:ShowDialog(dialog: number, parent: userdata) -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureShowDialog(imVideoCapture* vc, int dialog, void* parent); + +/** Allows to control the input and output of devices that have multiple input and outputs. + * cross controls in which stage the input/output will be set. Usually use 1, but some capture boards + * has a second stage. In Direct X it controls the crossbars. + * + * \verbatim vc:SetInOut(input, output, cross: number) -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int imVideoCaptureSetInOut(imVideoCapture* vc, int input, int output, int cross); + +/** Returns the description of a configuration dialog. + * dialog can be from 0 to \ref imVideoCaptureDialogCount. \n + * + * \verbatim vc:DialogDesc(dialog: number) -> desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +const char* IM_DECL imVideoCaptureDialogDesc(imVideoCapture* vc, int dialog); + +/** Returns the number of available video formats. \n + * Returns zero if failed. + * + * \verbatim vc:FormatCount() -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureFormatCount(imVideoCapture* vc); + +/** Returns information about the video format. \n + * format can be from 0 to \ref imVideoCaptureFormatCount. \n + * desc should be of size 10. \n + * The image size is usually the maximum size for that format. + * Other sizes can be available using \ref imVideoCaptureSetImageSize. \n + * Returns zero if failed. + * + * \verbatim vc:GetFormat(format: number) -> error: number, width: number, height: number, desc: string [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureGetFormat(imVideoCapture* vc, int format, int *width, int *height, char* desc); + +/** Changes the video format of the connected device. \n + * Should NOT work for DV devices. Use \ref imVideoCaptureSetImageSize only. \n + * Use -1 to return the current format, in this case returns -1 if failed. \n + * When the format is changed in the dialog, for some formats + * the returned format is the preferred format, not the current format. \n + * This will not affect color_mode of the capture image. \n + * Returns zero if failed. + * + * \verbatim vc:SetFormat(format: number) -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureSetFormat(imVideoCapture* vc, int format); + +/** Returns the current image size of the connected device. \n + * width and height returns 0 if not connected. + * + * \verbatim vc:GetImageSize() -> width: number, height: number [in Lua 5] \endverbatim + * \ingroup capture */ +void IM_DECL imVideoCaptureGetImageSize(imVideoCapture* vc, int *width, int *height); + +/** Changes the image size of the connected device. \n + * Similar to \ref imVideoCaptureSetFormat, but changes only the size. \n + * Valid sizes can be obtained with \ref imVideoCaptureGetFormat. \n + * Returns zero if failed. + * + * \verbatim vc:SetImageSize(width: number, height: number) -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureSetImageSize(imVideoCapture* vc, int width, int height); + +/** Returns a new captured frame. Use -1 for infinite timeout. \n + * Color space can be IM_RGB or IM_GRAY, and mode can be packed (IM_PACKED) or not. \n + * Data type is always IM_BYTE. \n + * It can not have an alpha channel and orientation is always bottom up. \n + * Returns zero if failed or timeout expired, the buffer is not changed. + * + * \verbatim vc:Frame(image: imImage, timeout: number) -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureFrame(imVideoCapture* vc, unsigned char* data, int color_mode, int timeout); + +/** Start capturing, returns the new captured frame and stop capturing. \n + * This is more usefull if you are switching between devices. \n + * Data format is the same as imVideoCaptureFrame. \n + * Returns zero if failed. + * + * \verbatim vc:OneFrame(image: imImage) -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureOneFrame(imVideoCapture* vc, unsigned char* data, int color_mode); + +/** Start capturing. \n + * Use -1 to return the current state. \n + * Returns zero if failed. + * + * \verbatim vc:Live(live: number) -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureLive(imVideoCapture* vc, int live); + +/** Resets a camera or video attribute to the default value or + * to the automatic setting. \n + * Not all attributes support automatic modes. \n + * Returns zero if failed. + * + * \verbatim vc:ResetAttribute(attrib: string, fauto: number) -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureResetAttribute(imVideoCapture* vc, const char* attrib, int fauto); + +/** Returns a camera or video attribute in percentage of the valid range value. \n + * Returns zero if failed or attribute not supported. + * + * \verbatim vc:GetAttribute(attrib: string) -> error: number, percent: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureGetAttribute(imVideoCapture* vc, const char* attrib, float *percent); + +/** Changes a camera or video attribute in percentage of the valid range value. \n + * Returns zero if failed or attribute not supported. + * + * \verbatim vc:SetAttribute(attrib: string, percent: number) -> error: number [in Lua 5] \endverbatim + * \ingroup capture */ +int IM_DECL imVideoCaptureSetAttribute(imVideoCapture* vc, const char* attrib, float percent); + +/** Returns a list of the description of the valid attributes for the device class. \n + * But each device may still not support some of the returned attributes. \n + * Use the return value of \ref imVideoCaptureGetAttribute to check if the attribute is supported. + * + * \verbatim vc:GetAttributeList() -> attrib_list: table of strings [in Lua 5] \endverbatim + * \ingroup capture */ +const char** IM_DECL imVideoCaptureGetAttributeList(imVideoCapture* vc, int *num_attrib); + + +/** \defgroup winattrib Windows Attributes Names + * Not all attributes are supported by each device. + * Use the return value of \ref imVideoCaptureGetAttribute to check if the attribute is supported. +\verbatim + VideoBrightness - Specifies the brightness, also called the black level. + VideoContrast - Specifies the contrast, expressed as gain factor. + VideoHue - Specifies the hue angle. + VideoSaturation - Specifies the saturation. + VideoSharpness - Specifies the sharpness. + VideoGamma - Specifies the gamma. + VideoColorEnable - Specifies the color enable setting. (0/100) + VideoWhiteBalance - Specifies the white balance, as a color temperature in degrees Kelvin. + VideoBacklightCompensation - Specifies the backlight compensation setting. (0/100) + VideoGain - Specifies the gain adjustment. + CameraPanAngle - Specifies the camera's pan angle. To 100 rotate right, To 0 rotate left (view from above). + CameraTiltAngle - Specifies the camera's tilt angle. To 100 rotate up, To 0 rotate down. + CameraRollAngle - Specifies the camera's roll angle. To 100 rotate right, To 0 rotate left. + CameraLensZoom - Specifies the camera's zoom setting. + CameraExposure - Specifies the exposure setting. + CameraIris - Specifies the camera's iris setting. + CameraFocus - Specifies the camera's focus setting, as the distance to the optimally focused target. + FlipHorizontal - Specifies the video will be flipped in the horizontal direction. + FlipVertical - Specifies the video will be flipped in the vertical direction. + AnalogFormat - Specifies the video format standard NTSC, PAL, etc. Valid values: + NTSC_M = 0 + NTSC_M_J = 1 + NTSC_433 = 2 + PAL_B = 3 + PAL_D = 4 + PAL_H = 5 + PAL_I = 6 + PAL_M = 7 + PAL_N = 8 + PAL_60 = 9 + SECAM_B = 10 + SECAM_D = 11 + SECAM_G = 12 + SECAM_H = 13 + SECAM_K = 14 + SECAM_K1 = 15 + SECAM_L = 16 + SECAM_L1 = 17 + PAL_N_COMBO = 18 +\endverbatim + * \ingroup capture */ + + +#if defined(__cplusplus) +} + +/** A C++ Wrapper for the imVideoCapture structure functions. + * \ingroup capture */ +class imCapture +{ +public: + imCapture() + { vc = imVideoCaptureCreate(); } + + ~imCapture() + { if (vc) imVideoCaptureDestroy(vc); } + + int Failed() + { if (!vc) return 0; else return 1; } + + int Connect(int device) + { return imVideoCaptureConnect(vc, device); } + + void Disconnect() + { imVideoCaptureDisconnect(vc); } + + int DialogCount() + { return imVideoCaptureDialogCount(vc); } + + int ShowDialog(int dialog, void* parent) + { return imVideoCaptureShowDialog(vc, dialog, parent); } + + const char* DialogDescription(int dialog) + { return imVideoCaptureDialogDesc(vc, dialog); } + + int FormatCount() + { return imVideoCaptureFormatCount(vc); } + + int GetFormat(int format, int *width, int *height, char* desc) + { return imVideoCaptureGetFormat(vc, format, width, height, desc); } + + int SetFormat(int format) + { return imVideoCaptureSetFormat(vc, format); } + + void GetImageSize(int *width, int *height) + { imVideoCaptureGetImageSize(vc, width, height); } + + int SetImageSize(int width, int height) + { return imVideoCaptureSetImageSize(vc, width, height); } + + int GetFrame(unsigned char* data, int color_mode, int timeout) + { return imVideoCaptureFrame(vc, data, color_mode, timeout); } + + int GetOneFrame(unsigned char* data, int color_mode) + { return imVideoCaptureOneFrame(vc, data, color_mode); } + + int Live(int live) + { return imVideoCaptureLive(vc, live); } + + int ResetAttribute(const char* attrib, int fauto) + { return imVideoCaptureResetAttribute(vc, attrib, fauto); } + + int GetAttribute(const char* attrib, float *percent) + { return imVideoCaptureGetAttribute(vc, attrib, percent); } + + int SetAttribute(const char* attrib, float percent) + { return imVideoCaptureSetAttribute(vc, attrib, percent); } + + const char** GetAttributeList(int *num_attrib) + { return imVideoCaptureGetAttributeList(vc, num_attrib); } + +protected: + imVideoCapture* vc; +}; + +#endif + +#endif diff --git a/include/im_color.h b/include/im_color.h new file mode 100644 index 0000000..b38b22c --- /dev/null +++ b/include/im_color.h @@ -0,0 +1,465 @@ +/** \file + * \brief Color Manipulation + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_COLOR_H +#define __IM_COLOR_H + +#include "im_math.h" + +/** \defgroup color Color Manipulation + * + * \par + * Functions to convert from one color space to another, + * and color gammut utilities. + * \par + * See \ref im_color.h + * + * \section s1 Some Color Science + * \par + * Y is luminance, a linear-light quantity. + * It is directly proportional to physical intensity + * weighted by the spectral sensitivity of human vision. + * \par + * L* is lightness, a nonlinear luminance + * that aproximates the perception of brightness. + * It is nearly perceptual uniform. + * It has a range of 0 to 100. + * \par + * Y' is luma, a nonlinear luminance that aproximates lightness. + * \par + * Brightness is a visual sensation according to which an area + * apears to exhibit more or less light. + * It is a subjective quantity and can not be measured. + * \par + * One unit of euclidian distante in CIE L*u*v* or CIE L*a*b* corresponds + * roughly to a just-noticeable difference (JND) of color. + * \par +\verbatim + ChromaUV = sqrt(u*u + v*v) + HueUV = atan2(v, u) + SaturationUV = ChromaUV / L (called psychometric saturation) + (the same can be calculated for Lab) +\endverbatim + * \par + * IEC 61966-2.1 Default RGB colour space - sRGB + * \li ITU-R Recommendation BT.709 (D65 white point). + * \li D65 White Point (X,Y,Z) = (0.9505 1.0000 1.0890) + * \par + * Documentation extracted from Charles Poynton - Digital Video and HDTV - Morgan Kaufmann - 2003. + * + * \section Links + * \li www.color.org - ICC + * \li www.srgb.com - sRGB + * \li www.poynton.com - Charles Poynton + * \li www.littlecms.com - A free Color Management System (use this if you need precise color conversions) + * + * \section cci Color Component Intervals + * \par + * All the color components are stored in the 0-max interval, even the signed ones. \n + * Here are the pre-defined intervals for each data type. These values are used for standard color conversion. + * You should normalize data before converting betwwen color spaces. + * \par +\verbatim + byte [0,255] or [-128,+127] (1 byte) + ushort [0,65535] or [-32768,+32767] (2 bytes) + int [0,16777215] or [-8388608,+8388607] (3 bytes) + float [0,1] or [-0.5,+0.5] (4 bytes) +\endverbatim + * \ingroup util */ + +/** Returns the zero value for color conversion porpouses. \n + * This is a value to be compensated when the data_type is unsigned and component is signed. \n + * \ingroup color */ +inline float imColorZero(int data_type) +{ + float zero[] = {128.0f, 32768.0f, 8388608.0f, 0.5f}; + return zero[data_type]; +} + +/** Returns the maximum value for color conversion porpouses. \n + * \ingroup color */ +inline int imColorMax(int data_type) +{ + int max[] = {255, 65535, 16777215, 1}; + return max[data_type]; +} + +/** Quantize r=0-1 values into q=0-max. + * max is the maximum value. + * max and the returned value are usually integers, + * but the dummy quantizer uses real values. + * See also \ref math. + * \ingroup color */ +template <class T> +inline T imColorQuantize(const float& value, const T& max) +{ + if (max == 1) return (T)value; // to allow a dummy quantizer + if (value >= 1) return max; + if (value <= 0) return 0; + /* return (T)imRound(value*(max + 1) - 0.5f); not necessary since all values are positive */ + return (T)(value*(max + 1)); +} + +/** Reconstruct 0-max values into 0-1. \n + * max is the maximum value. + * max and the given value are usually integers, + * but the dummy reconstructor uses real values. + * See also \ref math. + * \ingroup color */ +template <class T> +inline float imColorReconstruct(const T& value, const T& max) +{ + if (max == 1) return (float)value; // to allow a dummy reconstructor + if (value <= 0) return 0; + if (value >= max) return 1; + return (((float)value + 0.5f)/((float)max + 1.0f)); +} + +/** Converts Y'CbCr to R'G'B' (all nonlinear). \n + * ITU-R Recommendation 601-1 with no headroom/footroom. +\verbatim + 0 <= Y <= 1 ; -0.5 <= CbCr <= 0.5 ; 0 <= RGB <= 1 + + R'= Y' + 0.000 *Cb + 1.402 *Cr + G'= Y' - 0.344 *Cb - 0.714 *Cr + B'= Y' + 1.772 *Cb + 0.000 *Cr +\endverbatim + * \ingroup color */ +template <class T> +inline void imColorYCbCr2RGB(const T Y, const T Cb, const T Cr, + T& R, T& G, T& B, + const T& zero, const T& max) +{ + float r = float(Y + 1.402f * (Cr - zero)); + float g = float(Y - 0.344f * (Cb - zero) - 0.714f * (Cr - zero)); + float b = float(Y + 1.772f * (Cb - zero)); + + // now we should enforce 0<= rgb <= max + + R = (T)IM_CROPMAX(r, max); + G = (T)IM_CROPMAX(g, max); + B = (T)IM_CROPMAX(b, max); +} + +/** Converts R'G'B' to Y'CbCr (all nonlinear). \n + * ITU-R Recommendation 601-1 with no headroom/footroom. +\verbatim + 0 <= Y <= 1 ; -0.5 <= CbCr <= 0.5 ; 0 <= RGB <= 1 + + Y' = 0.299 *R' + 0.587 *G' + 0.114 *B' + Cb = -0.169 *R' - 0.331 *G' + 0.500 *B' + Cr = 0.500 *R' - 0.419 *G' - 0.081 *B' +\endverbatim + * \ingroup color */ +template <class T> +inline void imColorRGB2YCbCr(const T R, const T G, const T B, + T& Y, T& Cb, T& Cr, + const T& zero) +{ + Y = (T)( 0.299f *R + 0.587f *G + 0.114f *B); + Cb = (T)(-0.169f *R - 0.331f *G + 0.500f *B + (float)zero); + Cr = (T)( 0.500f *R - 0.419f *G - 0.081f *B + (float)zero); + + // there is no need for cropping here, YCrCr is already at the limits +} + +/** Converts C'M'Y'K' to R'G'B' (all nonlinear). \n + * This is a poor conversion that works for a simple visualization. +\verbatim + 0 <= CMYK <= 1 ; 0 <= RGB <= 1 + + R = (1 - K) * (1 - C) + G = (1 - K) * (1 - M) + B = (1 - K) * (1 - Y) +\endverbatim + * \ingroup color */ +template <class T> +inline void imColorCMYK2RGB(const T C, const T M, const T Y, const T K, + T& R, T& G, T& B, const T& max) +{ + T W = max - K; + R = (T)((W * (max - C)) / max); + G = (T)((W * (max - M)) / max); + B = (T)((W * (max - Y)) / max); + + // there is no need for cropping here, RGB is already at the limits +} + +/** Converts CIE XYZ to Rec 709 RGB (all linear). \n + * ITU-R Recommendation BT.709 (D65 white point). \n +\verbatim + 0 <= XYZ <= 1 ; 0 <= RGB <= 1 + + R = 3.2406 *X - 1.5372 *Y - 0.4986 *Z + G = -0.9689 *X + 1.8758 *Y + 0.0415 *Z + B = 0.0557 *X - 0.2040 *Y + 1.0570 *Z +\endverbatim + * \ingroup color */ +template <class T> +inline void imColorXYZ2RGB(const T X, const T Y, const T Z, + T& R, T& G, T& B, const T& max) +{ + float r = 3.2406f *X - 1.5372f *Y - 0.4986f *Z; + float g = -0.9689f *X + 1.8758f *Y + 0.0415f *Z; + float b = 0.0557f *X - 0.2040f *Y + 1.0570f *Z; + + // we need to crop because not all XYZ colors are visible + + R = (T)IM_CROPMAX(r, max); + G = (T)IM_CROPMAX(g, max); + B = (T)IM_CROPMAX(b, max); +} + +/** Converts Rec 709 RGB to CIE XYZ (all linear). \n + * ITU-R Recommendation BT.709 (D65 white point). \n +\verbatim + 0 <= XYZ <= 1 ; 0 <= RGB <= 1 + + X = 0.4124 *R + 0.3576 *G + 0.1805 *B + Y = 0.2126 *R + 0.7152 *G + 0.0722 *B + Z = 0.0193 *R + 0.1192 *G + 0.9505 *B +\endverbatim + * \ingroup color */ +template <class T> +inline void imColorRGB2XYZ(const T R, const T G, const T B, + T& X, T& Y, T& Z) +{ + X = (T)(0.4124f *R + 0.3576f *G + 0.1805f *B); + Y = (T)(0.2126f *R + 0.7152f *G + 0.0722f *B); + Z = (T)(0.0193f *R + 0.1192f *G + 0.9505f *B); + + // there is no need for cropping here, XYZ is already at the limits +} + +#define IM_FWLAB(_w) (_w > 0.008856f? \ + powf(_w, 1.0f/3.0f): \ + 7.787f * _w + 0.16f/1.16f) + +/** Converts CIE XYZ (linear) to CIE L*a*b* (nonlinear). \n + * The white point is D65. \n +\verbatim + 0 <= L <= 1 ; -0.5 <= ab <= +0.5 ; 0 <= XYZ <= 1 + + if (t > 0.008856) + f(t) = pow(t, 1/3) + else + f(t) = 7.787*t + 16/116 + + fX = f(X / Xn) fY = f(Y / Yn) fZ = f(Z / Zn) + + L = 1.16 * fY - 0.16 + a = 2.5 * (fX - fY) + b = (fY - fZ) + +\endverbatim + * \ingroup color */ +inline void imColorXYZ2Lab(const float X, const float Y, const float Z, + float& L, float& a, float& b) +{ + float fX = X / 0.9505f; // white point D65 + float fY = Y / 1.0f; + float fZ = Z / 1.0890f; + + fX = IM_FWLAB(fX); + fY = IM_FWLAB(fY); + fZ = IM_FWLAB(fZ); + + L = 1.16f * fY - 0.16f; + a = 2.5f * (fX - fY); + b = (fY - fZ); +} + +#define IM_GWLAB(_w) (_w > 0.20689f? \ + powf(_w, 3.0f): \ + 0.1284f * (_w - 0.16f/1.16f)) + +/** Converts CIE L*a*b* (nonlinear) to CIE XYZ (linear). \n + * The white point is D65. \n + * 0 <= L <= 1 ; -0.5 <= ab <= +0.5 ; 0 <= XYZ <= 1 + * \ingroup color */ +inline void imColorLab2XYZ(const float L, const float a, const float b, + float& X, float& Y, float& Z) + +{ + float fY = (L + 0.16f) / 1.16f; + float gY = IM_GWLAB(fY); + + float fgY = IM_FWLAB(gY); + float gX = fgY + a / 2.5f; + float gZ = fgY - b; + gX = IM_GWLAB(gX); + gZ = IM_GWLAB(gZ); + + X = gX * 0.9505f; // white point D65 + Y = gY * 1.0f; + Z = gZ * 1.0890f; +} + +/** Converts CIE XYZ (linear) to CIE L*u*v* (nonlinear). \n + * The white point is D65. \n +\verbatim + 0 <= L <= 1 ; -1 <= uv <= +1 ; 0 <= XYZ <= 1 + + Y = Y / 1.0 (for D65) + if (Y > 0.008856) + fY = pow(Y, 1/3) + else + fY = 7.787 * Y + 0.16/1.16 + L = 1.16 * fY - 0.16 + + U(x, y, z) = (4 * x)/(x + 15 * y + 3 * z) + V(x, y, z) = (9 * x)/(x + 15 * y + 3 * z) + un = U(Xn, Yn, Zn) = 0.1978 (for D65) + vn = V(Xn, Yn, Zn) = 0.4683 (for D65) + fu = U(X, Y, Z) + fv = V(X, Y, Z) + + u = 13 * L * (fu - un) + v = 13 * L * (fv - vn) +\endverbatim + * \ingroup color */ +inline void imColorXYZ2Luv(const float X, const float Y, const float Z, + float& L, float& u, float& v) +{ + float XYZ = (float)(X + 15 * Y + 3 * Z); + float fY = Y / 1.0f; + + if (XYZ != 0) + { + L = 1.16f * IM_FWLAB(fY) - 0.16f; + u = 6.5f * L * ((4 * X)/XYZ - 0.1978f); + v = 6.5f * L * ((9 * Y)/XYZ - 0.4683f); + } + else + { + L = u = v = 0; + } +} + +/** Converts CIE L*u*v* (nonlinear) to CIE XYZ (linear). \n + * The white point is D65. + * 0 <= L <= 1 ; -0.5 <= uv <= +0.5 ; 0 <= XYZ <= 1 \n + * \ingroup color */ +inline void imColorLuv2XYZ(const float L, const float u, const float v, + float& X, float& Y, float& Z) + +{ + float fY = (L + 0.16f) / 1.16f; + Y = IM_GWLAB(fY) * 1.0f; + + float ul = 0.1978f, vl = 0.4683f; + if (L != 0) + { + ul = u / (6.5f * L) + 0.1978f; + vl = v / (6.5f * L) + 0.4683f; + } + + X = ((9 * ul) / (4 * vl)) * Y; + Z = ((12 - 3 * ul - 20 * vl) / (4 * vl)) * Y; +} + +/** Converts nonlinear values to linear values. \n + * We use the sRGB transfer function. sRGB uses ITU-R 709 primaries and D65 white point. \n +\verbatim + 0 <= l <= 1 ; 0 <= v <= 1 + + if (v < 0.03928) + l = v / 12.92 + else + l = pow((v + 0.055) / 1.055, 2.4) +\endverbatim + * \ingroup color */ +inline float imColorTransfer2Linear(const float& nonlinear_value) +{ + if (nonlinear_value < 0.03928f) + return nonlinear_value / 12.92f; + else + return powf((nonlinear_value + 0.055f) / 1.055f, 2.4f); +} + +/** Converts linear values to nonlinear values. \n + * We use the sRGB transfer function. sRGB uses ITU-R 709 primaries and D65 white point. \n +\verbatim + 0 <= l <= 1 ; 0 <= v <= 1 + + if (l < 0.0031308) + v = 12.92 * l + else + v = 1.055 * pow(l, 1/2.4) - 0.055 +\endverbatim + * \ingroup color */ +inline float imColorTransfer2Nonlinear(const float& value) +{ + if (value < 0.0031308f) + return 12.92f * value; + else + return 1.055f * powf(value, 1.0f/2.4f) - 0.055f; +} + +/** Converts RGB (linear) to R'G'B' (nonlinear). + * \ingroup color */ +inline void imColorRGB2RGBNonlinear(const float RL, const float GL, const float BL, + float& R, float& G, float& B) +{ + R = imColorTransfer2Nonlinear(RL); + G = imColorTransfer2Nonlinear(GL); + B = imColorTransfer2Nonlinear(BL); +} + +/** Converts R'G'B' to Y' (all nonlinear). \n +\verbatim + Y' = 0.299 *R' + 0.587 *G' + 0.114 *B' +\endverbatim + * \ingroup color */ +template <class T> +inline T imColorRGB2Luma(const T R, const T G, const T B) +{ + return (T)((299 * R + 587 * G + 114 * B) / 1000); +} + +/** Converts Luminance (CIE Y) to Lightness (CIE L*) (all linear). \n + * The white point is D65. +\verbatim + 0 <= Y <= 1 ; 0 <= L* <= 1 + + Y = Y / 1.0 (for D65) + if (Y > 0.008856) + fY = pow(Y, 1/3) + else + fY = 7.787 * Y + 0.16/1.16 + L = 1.16 * fY - 0.16 +\endverbatim + * \ingroup color */ +inline float imColorLuminance2Lightness(const float& Y) +{ + return 1.16f * IM_FWLAB(Y) - 0.16f; +} + +/** Converts Lightness (CIE L*) to Luminance (CIE Y) (all linear). \n + * The white point is D65. +\verbatim + 0 <= Y <= 1 ; 0 <= L* <= 1 + + fY = (L + 0.16)/1.16 + if (fY > 0.20689) + Y = pow(fY, 3) + else + Y = 0.1284 * (fY - 0.16/1.16) + Y = Y * 1.0 (for D65) +\endverbatim + * \ingroup color */ +inline float imColorLightness2Luminance(const float& L) +{ + float fY = (L + 0.16f) / 1.16f; + return IM_GWLAB(fY); +} + +#undef IM_FWLAB +#undef IM_GWLAB +#undef IM_CROPL +#undef IM_CROPC + +#endif diff --git a/include/im_colorhsi.h b/include/im_colorhsi.h new file mode 100644 index 0000000..effb62a --- /dev/null +++ b/include/im_colorhsi.h @@ -0,0 +1,61 @@ +/** \file + * \brief HSI Color Manipulation + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_COLORHSI_H +#define __IM_COLORHSI_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup hsi HSI Color Coordinate System Conversions + * + * \par + * HSI is just the RGB color space written in a different coordinate system. + * \par + * "I" is defined along the cube diagonal. It ranges from 0 (black) to 1 (white). \n + * HS are the polar coordinates of a plane normal to "I". \n + * "S" is the normal distance from the diagonal of the RGB cube. It ranges from 0 to Smax. \n + * "H" is the angle starting from the red vector, given in degrees. + * \par + * This is not a new color space, this is exactly the same gammut as RGB. \n + * Since it is still a cube, Smax depends on H. + * \par + * See \ref im_colorhsi.h + * \ingroup color */ + + +/** Returns the maximum S for H (here in radians) and I. + * \ingroup hsi */ +float imColorHSI_Smax(float h, double cosh, double sinh, float i); + +/** Returns I where S is maximum given H (here in radians). + * \ingroup hsi */ +float imColorHSI_ImaxS(float h, double cosh, double sinh); + +/** Converts from RGB to HSI. + * \ingroup hsi */ +void imColorRGB2HSI(float r, float g, float b, float *h, float *s, float *i); + +/** Converts from RGB (byte) to HSI. + * \ingroup hsi */ +void imColorRGB2HSIbyte(unsigned char r, unsigned char g, unsigned char b, float *h, float *s, float *i); + +/** Converts from HSI to RGB. + * \ingroup hsi */ +void imColorHSI2RGB(float h, float s, float i, float *r, float *g, float *b); + +/** Converts from HSI to RGB (byte). + * \ingroup hsi */ +void imColorHSI2RGBbyte(float h, float s, float i, unsigned char *r, unsigned char *g, unsigned char *b); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_complex.h b/include/im_complex.h new file mode 100644 index 0000000..2ac4d92 --- /dev/null +++ b/include/im_complex.h @@ -0,0 +1,160 @@ +/** \file + * \brief Complex Data Type. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_COMPLEX_H +#define __IM_COMPLEX_H + +#include "im_math.h" + +/** \defgroup cpx Complex Numbers + * \par + * See \ref im_complex.h + * \ingroup util + */ + +/** \brief Complex Float Data Type + * + * \par + * Complex class using two floats, one for real part, one for the imaginary part. + * \par + * It is not a complete complex class, we just implement constructors inside the class. + * All the other operators and functions are external to the class. + * \ingroup cpx */ +class imcfloat +{ +public: + float real; ///< Real part. + float imag; ///< Imaginary part. + + /// Default Constructor (0,0). + imcfloat():real(0), imag(0) {} + + /// Constructor from (real, imag) + imcfloat(const float& r, const float& i):real(r),imag(i) {} + + /// Constructor from (real) + imcfloat(const float& r):real(r),imag(0) {} +}; + +/** \addtogroup cpx + * Complex numbers operators. + * @{ + */ + +inline int operator <= (const imcfloat& C1, const imcfloat& C2) +{ + return ((C1.real <= C2.real) && (C1.imag <= C2.imag)); +} + +inline int operator <= (const imcfloat& C, const float& F) +{ + return ((F <= C.real) && (0 <= C.imag)); +} + +inline imcfloat operator + (const imcfloat& C1, const imcfloat& C2) +{ + return imcfloat(C1.real + C2.real, C1.imag + C2.imag); +} + +inline imcfloat operator += (const imcfloat& C1, const imcfloat& C2) +{ + return imcfloat(C1.real + C2.real, C1.imag + C2.imag); +} + +inline imcfloat operator - (const imcfloat& C1, const imcfloat& C2) +{ + return imcfloat(C1.real - C2.real, C1.imag - C2.imag); +} + +inline imcfloat operator * (const imcfloat& C1, const imcfloat& C2) +{ + return imcfloat(C1.real * C2.real - C1.imag * C2.imag, + C1.imag * C2.real + C1.real * C2.imag); +} + +inline imcfloat operator / (const imcfloat& C1, const imcfloat& C2) +{ + float den = C2.real * C2.real - C2.imag * C2.imag; + return imcfloat((C1.real * C2.real + C1.imag * C2.imag) / den, + (C1.imag * C2.real - C1.real * C2.imag) / den); +} + +inline imcfloat operator / (const imcfloat& C, const float& R) +{ + return imcfloat(C.real / R, C.imag / R); +} + +inline imcfloat operator /= (const imcfloat& C, const float& R) +{ + return imcfloat(C.real / R, C.imag / R); +} + +inline imcfloat operator * (const imcfloat& C, const float& R) +{ + return imcfloat(C.real * R, C.imag * R); +} + +inline int operator == (const imcfloat& C1, const imcfloat& C2) +{ + return ((C1.real == C2.real) && (C1.imag == C2.imag)); +} + +inline float cpxreal(const imcfloat& C) +{ + return C.real; +} + +inline float cpximag(const imcfloat& C) +{ + return C.imag; +} + +inline float cpxmag(const imcfloat& C) +{ + return sqrtf(C.real*C.real + C.imag*C.imag); +} + +inline float cpxphase(const imcfloat& C) +{ + return atan2f(C.real, C.imag); +} + +inline imcfloat cpxconj(const imcfloat& C) +{ + return imcfloat(C.real, -C.imag); +} + +inline imcfloat log(const imcfloat& C) +{ + return imcfloat(logf(cpxmag(C)), atan2f(C.real, C.imag)); +} + +inline imcfloat exp(const imcfloat& C) +{ + float mag = expf(C.real); + return imcfloat(mag * cosf(C.imag), mag * sinf(C.imag)); +} + +inline imcfloat pow(const imcfloat& C1, const imcfloat& C2) +{ + return exp(C1 * log(C2)); +} + +inline imcfloat sqrt(const imcfloat& C) +{ + float mag = sqrtf(sqrtf(C.real*C.real + C.imag*C.imag)); + float phase = atan2f(C.real, C.imag) / 2; + return imcfloat(mag * cosf(phase), mag * sinf(phase)); +} + +inline imcfloat cpxpolar(const float& mag, const float& phase) +{ + return imcfloat(mag * cosf(phase), mag * sinf(phase)); +} + +/** @} */ + +#endif diff --git a/include/im_convert.h b/include/im_convert.h new file mode 100644 index 0000000..47950ea --- /dev/null +++ b/include/im_convert.h @@ -0,0 +1,127 @@ +/** \file + * \brief Image Conversion + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_CONVERT_H +#define __IM_CONVERT_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup convert Image Conversion + * \par + * Converts one type of image into another. Can convert between color modes + * and between data types. + * \par + * See \ref im_convert.h + * \ingroup imgclass */ + + +/** Complex to real conversions + * \ingroup convert */ +enum imComplex2Real +{ + IM_CPX_REAL, + IM_CPX_IMAG, + IM_CPX_MAG, + IM_CPX_PHASE +}; + +/** Predefined Gamma factors. Gamma can be any real number. + * When gamma<0 use logarithmic, when gamma>0 use exponential. + * gamma(x,g) = ((e^(g*x))-1)/(exp(g)-1) + * gamma(x,g) = (log((g*x)+1))/(log(g+1)) + * \ingroup convert */ +enum imGammaFactor +{ + IM_GAMMA_LINEAR = 0, + IM_GAMMA_LOGLITE = -10, + IM_GAMMA_LOGHEAVY = -1000, + IM_GAMMA_EXPLITE = 2, + IM_GAMMA_EXPHEAVY = 7 +}; + +/** Predefined Cast Modes + * \ingroup convert */ +enum imCastMode +{ + IM_CAST_MINMAX, /**< scan for min and max values */ + IM_CAST_FIXED, /**< use predefied 0-max values, see \ref color Color Manipulation. */ + IM_CAST_DIRECT /**< direct type cast the value. Only byte and ushort will be cropped. */ +}; + +/** Changes the image data type, using a complex2real conversion, + * a gamma factor, and an abssolute mode (modulus). \n + * When demoting the data type the function will scan for min/max values or use fixed values (cast_mode) + * to scale the result according to the destiny range. \n + * Except complex to real that will use only the complex2real conversion. \n + * Images must be of the same size and color mode. \n + * Returns IM_ERR_NONE, IM_ERR_DATA or IM_ERR_COUNTER, see also \ref imErrorCodes. + * See also \ref imComplex2Real, \ref imGammaFactor and \ref imCastMode. + * + * \verbatim im.ConvertDataType(src_image: imImage, dst_image: imImage, cpx2real: number, gamma: number, abssolute: bool, cast_mode: number) -> error: number [in Lua 5] \endverbatim + * \ingroup convert */ +int imConvertDataType(const imImage* src_image, imImage* dst_image, int cpx2real, float gamma, int abssolute, int cast_mode); + +/** Converts one color space to another. Images must be of the same size and data type. \n + * CMYK can be converted to RGB only, and it is a very simple conversion. \n + * All colors can be converted to Binary, the non zero gray values are converted to 1. \n + * RGB to Map uses the median cut implementation from the free IJG JPEG software, copyright Thomas G. Lane. \n + * All other color space conversions assume sRGB and CIE definitions. \n + * Returns IM_ERR_NONE, IM_ERR_DATA or IM_ERR_COUNTER, see also \ref imErrorCodes. + * + * \verbatim im.ConvertColorSpace(src_image: imImage, dst_image: imImage) -> error: number [in Lua 5] \endverbatim + * \ingroup convert */ +int imConvertColorSpace(const imImage* src_image, imImage* dst_image); + +/** Converts the image to its bitmap equivalent, + * uses \ref imConvertColorSpace and \ref imConvertDataType. \n + * Returns IM_ERR_NONE, IM_ERR_DATA or IM_ERR_COUNTER, see also \ref imErrorCodes. + * See also \ref imComplex2Real, \ref imGammaFactor and \ref imCastMode. + * + * \verbatim im.ConvertToBitmap(src_image: imImage, dst_image: imImage, cpx2real: number, gamma: number, abssolute: bool, cast_mode: number) -> error: number [in Lua 5] \endverbatim + * \ingroup convert */ +int imConvertToBitmap(const imImage* src_image, imImage* dst_image, int cpx2real, float gamma, int abssolute, int cast_mode); + + + +/** \defgroup cnvutil Raw Data Conversion Utilities + * \par + * Utilities for raw data buffers. + * \par + * See \ref im_convert.h + * \ingroup imagerep */ + + +/** Changes the packing of the data buffer. + * \ingroup cnvutil */ +void imConvertPacking(const void* src_data, void* dst_data, int width, int height, int depth, int data_type, int src_is_packed); + +/** Changes in-place a MAP data into a RGB data. The data must have room for the RGB image. \n + * depth can be 3 or 4. count=width*height. \n + * Very usefull for OpenGL applications. + * \ingroup cnvutil */ +void imConvertMapToRGB(unsigned char* data, int count, int depth, int packed, long* palette, int palette_count); + + + +/* Converts a RGB bitmap into a map bitmap using the median cut algorithm. + * Used only "im_convertcolor.cpp" implemented in "im_rgb2map.cpp". + * Internal function kept here because of the compatibility module. + * Will not be at the documentation. */ +int imConvertRGB2Map(int width, int height, + unsigned char *red, unsigned char *green, unsigned char *blue, + unsigned char *map, long *palette, int *palette_count); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_counter.h b/include/im_counter.h new file mode 100644 index 0000000..82714f5 --- /dev/null +++ b/include/im_counter.h @@ -0,0 +1,69 @@ +/** \file + * \brief Processing Counter + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_COUNTER_H +#define __IM_COUNTER_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup counter Counter + * \par + * Used to notify the application that a step in the loading, saving or processing operation has been performed. + * \par + * See \ref im_counter.h + * \ingroup util */ + +/** Counter callback, informs the progress of the operation to the client. \n + * Text contains a constant string that is NULL during normal counting, a title in the begining of a sequence + * and a message in the begining of a count. + * Counter id identifies diferrent counters. \n + * Progress in a count reports a value from 0 to 1000. If -1 indicates the start of a sequence of operations, 1001 ends the sequence. \n + * If returns 0 the client should abort the operation. \n + * If the counter is aborted, the callback will be called one last time at 1001. + * \ingroup counter */ +typedef int (*imCounterCallback)(int counter, void* user_data, const char* text, int progress); + +/** Changes the counter callback. Returns old callback. \n + * User data is changed only if not NULL. + * \ingroup counter */ +imCounterCallback imCounterSetCallback(void* user_data, imCounterCallback counter_func); + +/** Begins a new count, or a partial-count in a sequence. \n + * Calls the callback with "-1" and text=title, if it is at the top level. \n + * This is to be used by the operations. Returns a counter Id. + * \ingroup counter */ +int imCounterBegin(const char* title); + +/** Ends a count, or a partial-count in a sequence. \n + * Calls the callback with "1001", text=null, and releases the counter if it is at top level count. \n + * \ingroup counter */ +void imCounterEnd(int counter); + +/** Increments a count. Must set the total first. \n + * Calls the callback, text=message if it is the first increment for the count. \n + * Returns 0 if the callback aborted, 1 if returns normally. + * \ingroup counter */ +int imCounterInc(int counter); + +/** Set a specific count. Must set the total first. \n + * Calls the callback, text=message if it is the first increment for the count. \n + * Returns 0 if the callback aborted, 1 if returns normally. + * \ingroup counter */ +int imCounterIncTo(int counter, int count); + +/** Sets the total increments of a count. + * \ingroup counter */ +void imCounterTotal(int counter, int total, const char* message); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_dib.h b/include/im_dib.h new file mode 100644 index 0000000..49077b8 --- /dev/null +++ b/include/im_dib.h @@ -0,0 +1,195 @@ +/** \file + * \brief Windows DIB (Device Independent Bitmap) + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_DIB_H +#define __IM_DIB_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup dib Windows DIB + * + * \par + * Windows DIBs in memory are handled just like a BMP file without the file header. \n + * These functions will work only in Windows. They are usefull for interchanging data + * with the clipboard, with capture drivers, with the AVI and WMF file formats and others. + * \par + * Supported DIB aspects: + * \li bpp must be 1, 4, 8, 16, 24, or 32. + * \li BITMAPV4HEADER or BITMAPV5HEADER are handled but ignored. \n + * \li BITMAPCOREHEADER is not handled . + * \li BI_JPEG and BI_PNG compressions are not handled. + * \li biHeight can be negative, compression can be RLE only if created + * from imDibCreateReference, imDibPasteClipboard, imDibLoadFile. + * \li can not encode/decode Images to/from RLE compressed Dibs. + * \li if working with RLE Dibs bits_size is greatter than used. + * \li the resolution of a new Dib is taken from the screen. + * \li SetDIBitsToDevice(start_scan is 0, scan_lines is dib->bmih->biHeight). + * \li StretchDIBits(use always DIB_RGB_COLORS). + * \li CreateDIBPatternBrushPt(packed_dib is dib->dib). + * \par + * Must include <windows.h> before using these functions. \n + * Check <wingdi.h> for structures and definitions. + * \par + * See \ref im_dib.h + * \ingroup util */ + + +/** \brief Windows DIB Structure + * + * \par + * Handles a DIB in memory. \n + * The DIB is stored in only one buffer. + * The secondary members are pointers to the main buffer. + * \ingroup dib */ +typedef struct _imDib +{ + HGLOBAL handle; /**< The windows memory handle */ + BYTE* dib; /**< The DIB as it is defined in memory */ + int size; /**< Full size in memory */ + + BITMAPINFO* bmi; /**< Bitmap Info = Bitmap Info Header + Palette */ + BITMAPINFOHEADER* bmih; /**< Bitmap Info Header */ + RGBQUAD* bmic; /**< Bitmap Info Colors = Palette */ + BYTE* bits; /**< Bitmap Bits */ + + int palette_count; /**< number of colors in the palette */ + int bits_size; /**< size in bytes of the Bitmap Bits */ + int line_size; /**< size in bytes of one line, includes padding */ + int pad_size; /**< number of bytes remaining in the line, lines are in a word boundary */ + + int is_reference; /**< only a reference, do not free pointer */ +} imDib; + +/** Creates a new DIB. \n + * use bpp=-16/-32 to allocate space for BITFLIEDS. + * \ingroup dib */ +imDib* imDibCreate(int width, int height, int bpp); + +/** Duplicates the DIB contents in a new DIB. + * \ingroup dib */ +imDib* imDibCreateCopy(const imDib* dib); + +/** Creates a DIB using an already allocated memory. \n + * "bmi" must be a pointer to BITMAPINFOHEADER. \n + * "bits" can be NULL if it is inside "bmi" after the palette. + * \ingroup dib */ +imDib* imDibCreateReference(BYTE* bmi, BYTE* bits); + +/** Creates a DIB section for drawing porposes. \n + * Returns the image handle also created. + * \ingroup dib */ +imDib* imDibCreateSection(HDC hDC, HBITMAP *image, int width, int height, int bpp); + +/** Destroy the DIB + * \ingroup dib */ +void imDibDestroy(imDib* dib); + +/** DIB GetPixel function definition. \n + * the DWORD is a raw copy of the bits, use (unsigned char*)&pixel + * \ingroup dib */ +typedef unsigned int (*imDibLineGetPixel)(unsigned char* line, int col); + +/** Returns a function to read pixels from a DIB line. + * \ingroup dib */ +imDibLineGetPixel imDibLineGetPixelFunc(int bpp); + +/** DIB SetPixel function definition + * \ingroup dib */ +typedef void (*imDibLineSetPixel)(unsigned char* line, int col, unsigned int pixel); + +/** Returns a function to write pixels into a DIB line. + * \ingroup dib */ +imDibLineSetPixel imDibLineSetPixelFunc(int bpp); + +/** Creates a DIB from a image handle and a palette handle. + * \ingroup dib */ +imDib* imDibFromHBitmap(const HBITMAP image, const HPALETTE hPalette); + +/** Creates a image handle from a DIB. + * \ingroup dib */ +HBITMAP imDibToHBitmap(const imDib* dib); + +/** Returns a Logical palette from the DIB palette. \n + * DIB bpp must be <=8. + * \ingroup dib */ +HPALETTE imDibLogicalPalette(const imDib* dib); + +/** Captures the screen into a DIB. + * \ingroup dib */ +imDib* imDibCaptureScreen(int x, int y, int width, int height); + +/** Transfer the DIB to the clipboard. \n + * "dib" pointer can not be used after, or use imDibCopyClipboard(imDibCreateCopy(dib)). + * Warning: Clipboard functions in C++ can fail with Visual C++ /EHsc (Enable C++ Exceptions) +* \ingroup dib */ +void imDibCopyClipboard(imDib* dib); + +/** Creates a reference for the DIB in the clipboard if any. Returns NULL otherwise. + * Warning: Clipboard functions in C++ can fail with Visual C++ /EHsc (Enable C++ Exceptions) + * \ingroup dib */ +imDib* imDibPasteClipboard(void); + +/** Checks if there is a dib at the clipboard. + * \ingroup dib */ +int imDibIsClipboardAvailable(void); + +/** Saves the DIB into a file ".bmp". + * \ingroup dib */ +int imDibSaveFile(const imDib* dib, const char* filename); + +/** Creates a DIB from a file ".bmp". + * \ingroup dib */ +imDib* imDibLoadFile(const char* filename); + +/** Converts a DIB into an RGBA image. alpha is optional. bpp must be >8. \n + * alpha is used only when bpp=32. + * \ingroup dib */ +void imDibDecodeToRGBA(const imDib* dib, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha); + +/** Converts a DIB into an indexed image. bpp must be <=8. colors must have room for at least 256 colors. + * colors is rgb packed (RGBRGBRGB...) + * \ingroup dib */ +void imDibDecodeToMap(const imDib* dib, unsigned char* map, long* palette); + +/** Converts an RGBA image into a DIB. alpha is optional. bpp must be >8. \n + * alpha is used only when bpp=32. + * \ingroup dib */ +void imDibEncodeFromRGBA(imDib* dib, const unsigned char* red, const unsigned char* green, const unsigned char* blue, const unsigned char* alpha); + +/** Converts an indexed image into a DIB. bpp must be <=8. \n + * colors is rgb packed (RGBRGBRGB...) + * \ingroup dib */ +void imDibEncodeFromMap(imDib* dib, const unsigned char* map, const long* palette, int palette_count); + +/** Converts a IM_RGB packed image, with or without alpha, into a DIB. + * \ingroup dib */ +void imDibEncodeFromBitmap(imDib* dib, const unsigned char* data); + +/** Converts a DIB into IM_RGB packed image, with or without alpha. + * \ingroup dib */ +void imDibDecodeToBitmap(const imDib* dib, unsigned char* data); + +#ifdef __IM_IMAGE_H +/* You must include "im_image.h" before this header to enable these declarations. */ + +/** Creates a imImage from the dib data. + * \ingroup dib */ +imImage* imDibToImage(const imDib* dib); + +/** Creates a Dib from the image. It must be a bitmap image. + * \ingroup dib */ +imDib* imDibFromImage(const imImage* image); + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_file.h b/include/im_file.h new file mode 100644 index 0000000..a35c82a --- /dev/null +++ b/include/im_file.h @@ -0,0 +1,111 @@ +/** \file + * \brief File Access + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FILE_H +#define __IM_FILE_H + +#include "im.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup filesdk File Format SDK + * \par + * All the file formats are based on theses structures. Use them to create new file formats. \n + * The LineBuffer functions will help transfer image from format buffer to application buffer and vice-versa. + * \par + * See \ref im_file.h + * \ingroup file */ + + +/** \brief Image File Format Base (SDK Use Only) + * + * \par + * Base container to hold format independent state variables. + * \ingroup filesdk */ +struct _imFile +{ + int is_new; + void* attrib_table; /**< in fact is a imAttribTable, but we hide this here */ + + void* line_buffer; /**< used for line convertion, contains all components if packed, or only one if not */ + int line_buffer_size; + int line_buffer_extra; /**< extra bytes to be allocated */ + int line_buffer_alloc; /**< total allocated so far */ + int counter; + + int convert_bpp; /**< number of bpp to unpack/pack to/from 1 byte. + When reading converts n packed bits to 1 byte (unpack). If n>1 will also expand to 0-255. + When writing converts 1 byte to 1 bit (pack). + If negative will only expand to 0-255 (no unpack or pack). */ + int switch_type; /**< flag to switch the original data type: char-byte, short-ushort, uint-int, double-float */ + + long palette[256]; + int palette_count; + + int user_color_mode, + user_data_type, + file_color_mode, /* these two must be filled by te driver always. */ + file_data_type; + + /* these must be filled by the driver when reading, + and given by the user when writing. */ + + char compression[10]; + int image_count, + image_index, + width, + height; +}; + + +/* Internal Use only */ + +/* Initializes the imFile structure. + * Used by the special format RAW. */ +void imFileClear(imFile* ifile); + +/* Initializes the line buffer. + * Used by "im_file.cpp" only. */ +void imFileLineBufferInit(imFile* ifile); + +/* Check if the conversion is valid. + * Used by "im_file.cpp" only. */ +int imFileCheckConversion(imFile* ifile); + + + +/* File Format SDK */ + +/** Number of lines to be accessed. + * \ingroup filesdk */ +int imFileLineBufferCount(imFile* ifile); + +/** Increments the row and plane counters. + * \ingroup filesdk */ +void imFileLineBufferInc(imFile* ifile, int *row, int *plane); + +/** Converts from FILE color mode to USER color mode. + * \ingroup filesdk */ +void imFileLineBufferRead(imFile* ifile, void* data, int line, int plane); + +/** Converts from USER color mode to FILE color mode. + * \ingroup filesdk */ +void imFileLineBufferWrite(imFile* ifile, const void* data, int line, int plane); + +/** Utility to calculate the line size in byte with a specified alignment. \n + * "align" can be 1, 2 or 4. + * \ingroup filesdk */ +int imFileLineSizeAligned(int width, int bpp, int align); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_format.h b/include/im_format.h new file mode 100644 index 0000000..9120676 --- /dev/null +++ b/include/im_format.h @@ -0,0 +1,79 @@ +/** \file + * \brief File Format Access + * + * See Copyright Notice in im_lib.h + */ + +#include "im_file.h" +#include "im_attrib.h" + +#ifndef __IM_FORMAT_H +#define __IM_FORMAT_H + + +/** \brief Image File Format Driver (SDK Use Only) + * + * \par + * Virtual Base class for file formats. All file formats inherit from this class. + * \ingroup filesdk */ +class imFormat: public _imFile +{ +public: + const char* format; + const char* desc; + const char* ext; + const char** comp; + int comp_count, + can_sequence; + + imFormat(const char* _format, const char* _desc, const char* _ext, + const char** _comp, int _comp_count, int _can_sequence) + :format(_format), desc(_desc), ext(_ext), comp(_comp), + comp_count(_comp_count), can_sequence(_can_sequence) + {} + virtual ~imFormat() {} + + imAttribTable* AttribTable() {return (imAttribTable*)this->attrib_table;} + + /* Pure Virtual Methods. Every driver must implement all the following methods. */ + + virtual int Open(const char* file_name) = 0; // Must initialize compression and image_count + virtual int New(const char* file_name) = 0; + virtual void Close() = 0; + virtual void* Handle(int index) = 0; + virtual int ReadImageInfo(int index) = 0; // Should update compression + virtual int ReadImageData(void* data) = 0; + virtual int WriteImageInfo() = 0; // Should update compression + virtual int WriteImageData(void* data) = 0; // Must update image_count + virtual int CanWrite(const char* compression, int color_mode, int data_type) const = 0; +}; + +extern "C" +{ + +/* Internal Use only */ + +/* Opens a file with the respective format driver + * Uses the file extension to speed up the search for the format driver. + * Used by "im_file.cpp" only. */ +imFormat* imFormatOpen(const char* file_name, int *error); + +/* Opens a file with the given format + * Used by "im_file.cpp" only. */ +imFormat* imFormatOpenAs(const char* file_name, const char* format, int *error); + +/* Creates a file using the given format driver. + * Used by "im_file.cpp" only. */ +imFormat* imFormatNew(const char* file_name, const char* format, int *error); + + +/* File Format SDK */ + +/** Register a format driver. + * \ingroup filesdk */ +void imFormatRegister(imFormat* iformat); + + +} + +#endif diff --git a/include/im_format_all.h b/include/im_format_all.h new file mode 100644 index 0000000..3c38452 --- /dev/null +++ b/include/im_format_all.h @@ -0,0 +1,576 @@ +/** \file + * \brief All the Internal File Formats. + * They are all automatically registered by the library. + * The signatures are in C, but the functions are C++. + * Header for internal use only. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_ALL_H +#define __IM_FORMAT_ALL_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup tiff TIFF - Tagged Image File Format + * \section Description + * + * \par + * Copyright (c) 1986-1988, 1992 by Adobe Systems Incorporated. \n + * Originally created by a group of companies, + * the Aldus Corporation keeped the copyright until Aldus was aquired by Adobe. \n + * TIFF Revision 6.0 Final — June 3, 1992 \n + * http://www.adobe.com/Support/TechNotes.html + * \par + * Access to the TIFF file format uses libTIFF version 3.8.2 \n + * http://www.remotesensing.org/libtiff/ \n + * Copyright (c) 1988-1997 Sam Leffler \n + * Copyright (c) 1991-1997 Silicon Graphics, Inc. \n + * + * \section Features + * +\verbatim + Data Types: <all> + Color Spaces: Gray, RGB, CMYK, YCbCr, Lab, XYZ, Map and Binary. + Compressions: + NONE - no compression [default for IEEE Floating Point Data] + CCITTRLE - CCITT modified Huffman RLE (binary only) [default for Binary] + CCITTFAX3 - CCITT Group 3 fax (binary only) + CCITTFAX4 - CCITT Group 4 fax (binary only) + LZW - Lempel-Ziv & Welch [default] + JPEG - ISO JPEG [default for YCBCR] + NEXT - NeXT 2-bit RLE (2 bpp only) + CCITTRLEW - CCITT modified Huffman RLE with word alignment (binary only) + RLE - Packbits (Macintosh RLE) [default for MAP] + THUNDERSCAN - ThunderScan 4-bit RLE (only for 2 or 4 bpp) + PIXARLOG - Pixar companded 11-bit ZIP (only byte, ushort and float) + DEFLATE - LZ77 variation (ZIP) + ADOBE_DEFLATE - Adobe LZ77 variation + SGILOG - SGI Log Luminance RLE for L and Luv (only byte, ushort and float) [default for XYZ] + SGILOG24 - SGI Log 24-bit packed for Luv (only byte, ushort and float) + Can have more than one image. + Can have an alpha channel. + Components can be packed or not. + Lines arranged from top down to bottom or bottom up to top. + Handle(1) returns a TIFF* libTIFF structure. + + Attributes: + Photometric IM_USHORT (1) (when writing this will complement the color_mode information, for Mask, MinIsWhite, ITULab and ICCLab) + ExtraSampleInfo IM_USHORT (1) (description of alpha channel: 0- uknown, 1- pre-multiplied, 2-normal) + JPEGQuality IM_INT (1) [0-100, default 75] (write only) + ZIPQuality IM_INT (1) [1-9, default 6] (write only) + ResolutionUnit (string) ["DPC", "DPI"] + XResolution, YResolution IM_FLOAT (1) + Description, Author, Copyright, DateTime, DocumentName, + PageName, TargetPrinter, Make, Model, Software, HostComputer (string) + InkNames (strings separated by '0's) + InkSet IM_USHORT (1) + NumberOfInks IM_USHORT (1) + DotRange IM_USHORT (2) + TransferFunction0, TransferFunction1, TransferFunction3 IM_USHORT [gray=0, rgb=012] + ReferenceBlackWhite IMFLOAT (6) + WhitePoint IMFLOAT (2) + PrimaryChromaticities IMFLOAT (6) + YCbCrCoefficients IM_FLOAT (3) + YCbCrSubSampling IM_USHORT (2) + YCbCrPositioning IM_USHORT (1) + PageNumber IM_USHORT (2) + StoNits IM_FLOAT (1) + XPosition, YPosition IM_FLOAT (1) + SMinSampleValue, SMaxSampleValue IM_FLOAT (1) + HalftoneHints IM_USHORT (2) + SubfileType IM_INT (1) + ICCProfile IM_BYTE (N) + MultiBandCount IM_USHORT (1) [Number of bands in a multiband gray image.] + MultiBandSelect IM_USHORT (1) [Band number to read one band of a multiband gray image. Must be set before reading image info.] + and other TIFF tags as they are described in the TIFF documentation. + GeoTIFF tags: + GeoTiePoints, GeoTransMatrix, IntergraphMatrix, GeoPixelScale, GeoDoubleParams IM_FLOAT (N) + GeoASCIIParams (string) + Read-only support for EXIF tags as they are described in the EXIF 2.2 documentation. See http://www.exif.org/ + DNG tags as they are described in the DNG documentation. See http://www.adobe.com/br/products/dng/ + Tags BlackLevel, DefaultCropOrigin and DefaultCropSize are incorrectly interpreted by libTIFF so they are ignored. + Raw image is loaded in place of the thumbnail image in the main IFD. + SubIFDCount IM_USHORT (1) [Number of subifds of the current image.] + SubIFDSelect IM_USHORT (1) [Subifd number to be readed. Must be set before reading image info.] + (other attributes can be obtained by using libTIFF directly using the Handle(1) function) + + Comments: + LogLuv is in fact Y'+CIE(u,v), so we choose to always convert it to XYZ. + SubIFD is handled only for DNG. + Since LZW patent expired, LZW compression is enabled. LZW Copyright Unisys. + libGeoTIFF can be used without XTIFF initialization. Use Handle(1) to obtain a TIFF*. + + Changes: + "tiff_jpeg.c" - commented "downsampled_output = TRUE" in 2 places. + New file "tif_config.h" to match our needs. + New file "tiff_binfile.c" that implement I/O rotines using imBinFile. +\endverbatim + * \ingroup format */ +void imFormatRegisterTIFF(void); + +/** \defgroup jpeg JPEG - JPEG File Interchange Format + * \section Description + * + * \par + * ISO/IEC 10918 (1994, 1995, 1997, 1999)\n + * http://www.jpeg.org/ + * \par + * Access to the JPEG file format uses libJPEG version 6b. \n + * http://www.ijg.org \n + * Copyright (C) 1991-1998, Thomas G. Lane \n + * from the Independent JPEG Group. + * \par + * Access to the EXIF attributes uses libEXIF version 0.6.12. \n + * http://sourceforge.net/projects/libexif \n + * Copyright (C) 2001-2003, Lutz Müller + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: Gray, RGB, CMYK and YCbCr (Binary Saved as Gray) + Compressions: + JPEG - ISO JPEG [default] + Only one image. + No alpha channel. + Internally the components are always packed. + Internally the lines are arranged from top down to bottom. + Handle(1) returns jpeg_decompress_struct* when reading, and + jpeg_compress_struct* when writing (libJPEG structures). + + Attributes: + AutoYCbCr IM_INT (1) (controls YCbCr auto conversion) default 1 + JPEGQuality IM_INT (1) [0-100, default 75] (write only) + ResolutionUnit (string) ["DPC", "DPI"] + XResolution, YResolution IM_FLOAT (1) + Interlaced (same as Progressive) IM_INT (1 | 0) default 0 + Description (string) + (lots of Exif tags) + + Changes to libJPEG: + jdatadst.c - fflush and ferror replaced by macros JFFLUSH and JFERROR. + jinclude.h - standard JFFLUSH and JFERROR definitions, and new macro HAVE_JFIO. + jmorecfg.h - changed definition of INT32 to JINT32 for better compatibility. + jdhuf.c - added support for OJPEG_SUPPORT in libTIFF. + new file created: jconfig.h + + Changes to libEXIF: + new file config.h + changed "exif-tag.c" to add new function + changed "exif-entry.c" to improve exif_entry_initialize + fixed small bug in "mnote-pentax-tag.h". + + Comments: + Other APPx markers are ignored. + No thumbnail support. + RGB images are automatically converted to YCbCr when saved. + Also YcbCr are converted to RGB when loaded. Use AutoYCbCr=0 to disable this behavior. +\endverbatim + * \ingroup format */ +void imFormatRegisterJPEG(void); + +/** \defgroup png PNG - Portable Network Graphic Format + * \section Description + * + * \par + * Access to the PNG file format uses libPNG version 1.2.22. \n + * http://www.libpng.org \n + * Copyright (C) 1998-2007 Glenn Randers-Pehrson + * + * \section Features + * +\verbatim + Data Types: Byte and UShort + Color Spaces: Gray, RGB, MAP and Binary + Compressions: + DEFLATE - LZ77 variation (ZIP) [default] + Only one image. + Can have an alpha channel. + Internally the components are always packed. + Internally the lines are arranged from top down to bottom. + Handle(1) returns png_structp libPNG structure. + + Attributes: + ZIPQuality IM_INT (1) [1-9, default 6] (write only) + ResolutionUnit (string) ["DPC", "DPI"] + XResolution, YResolution IM_FLOAT (1) + Interlaced (same as Progressive) IM_INT (1 | 0) default 0 + Gamma IM_FLOAT (1) + WhitePoint IMFLOAT (2) + PrimaryChromaticities IMFLOAT (6) + XPosition, YPosition IM_FLOAT (1) + sRGBIntent IM_INT (1) [0: Perceptual, 1: Relative colorimetric, 2: Saturation, 3: Absolute colorimetric] + TransparencyIndex IM_BYTE (1 or N) + TransparentColor IM_BYTE (3) + CalibrationName, CalibrationUnits (string) + CalibrationLimits IM_INT (2) + CalibrationEquation IM_BYTE (1) [0-Linear,1-Exponential,2-Arbitrary,3-HyperbolicSine)] + CalibrationParam (string) [params separated by '\\n'] + Title, Author, Description, Copyright, DateTime (string) + Software, Disclaimer, Warning, Source, Comment, ... (string) + DateTimeModified (string) [when writing uses the current system time] + ICCProfile IM_BYTE (N) + ScaleUnit (string) ["meters", "radians"] + XScale, YScale IM_FLOAT (1) + + Comments: + Attributes after the image are ignored. + Define PNG_NO_CONSOLE_IO to avoid printfs. + We define PNG_TIME_RFC1123_SUPPORTED. + Add the following files to the makefile to optimize the library: + pngvcrd.c - PNG_USE_PNGVCRD + For Intel x86 CPU and Microsoft Visual C++ compiler + pnggccrd.c - PNG_USE_PNGGCCRD + For Intel x86 CPU (Pentium-MMX or later) and GNU C compiler. + Changed pngconf.h to use int instead of long in png_uint_32 and png_int_32. +\endverbatim + * \ingroup format */ +void imFormatRegisterPNG(void); + +/** \defgroup gif GIF - Graphics Interchange Format + * \section Description + * + * \par + * Copyright (c) 1987,1988,1989,1990 CompuServe Incorporated. \n + * GIF is a Service Mark property of CompuServe Incorporated. \n + * Graphics Interchange Format Programming Reference, 1990. \n + * LZW Copyright Unisys. + * \par + * Patial Internal Implementation. \n + * Decoding and encoding code were extracted from GIFLib 1.0. \n + * Copyright (c) 1989 Gershon Elber. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: MAP only, (Gray and Binary saved as MAP) + Compressions: + LZW - Lempel-Ziv & Welch [default] + Can have more than one image. + No alpha channel. + Internally the lines are arranged from top down to bottom. + + Attributes: + ScreenHeight, ScreenWidth IM_USHORT (1) screen size [default to the first image size] + Interlaced IM_INT (1 | 0) default 0 + Description (string) + TransparencyIndex IM_BYTE (1) + XScreen, YScreen IM_USHORT (1) screen position + UserInput IM_BYTE (1) [1, 0] + Disposal (string) [UNDEF, LEAVE, RBACK, RPREV] + Delay IM_USHORT (1) + Iterations IM_USHORT (1) (NETSCAPE2.0 Application Extension) + + Comments: + Attributes after the last image are ignored. + Reads GIF87 and GIF89, but writes GIF89 always. + Ignored attributes: Background Color Index, Pixel Aspect Ratio, + Plain Text Extensions, Application Extensions... +\endverbatim + * \ingroup format */ +void imFormatRegisterGIF(void); + +/** \defgroup bmp BMP - Windows Device Independent Bitmap + * \section Description + * + * \par + * Windows Copyright Microsoft Corporation. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB, MAP and Binary (Gray saved as MAP) + Compressions: + NONE - no compression [default] + RLE - Run Lenght Encoding (only for MAP and Gray) + Only one image. + Can have an alpha channel (only for RGB) + Internally the components are always packed. + Lines arranged from top down to bottom or bottom up to top. But are saved always as bottom up. + + Attributes: + ResolutionUnit (string) ["DPC", "DPI"] + XResolution, YResolution IM_FLOAT (1) + + Comments: + Reads OS2 1.x and Windows 3, but writes Windows 3 always. + Version 4 and 5 BMPs are not supported. +\endverbatim + * \ingroup format */ +void imFormatRegisterBMP(void); + +/** \defgroup ras RAS - Sun Raster File + * \section Description + * + * \par + * Copyright Sun Corporation. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: Gray, RGB, MAP and Binary + Compressions: + NONE - no compression [default] + RLE - Run Lenght Encoding + Only one image. + Can have an alpha channel (only for IM_RGB) + Internally the components are always packed. + Internally the lines are arranged from top down to bottom. + + Attributes: + none +\endverbatim + * \ingroup format */ +void imFormatRegisterRAS(void); + +/** \defgroup led LED - IUP image in LED + * \section Description + * + * \par + * Copyright Tecgraf/PUC-Rio and PETROBRAS/CENPES. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: MAP only (Gray and Binary saved as MAP) + Compressions: + NONE - no compression [default] + Only one image. + No alpha channel. + Internally the lines are arranged from top down to bottom. + + Attributes: + none + + Comments: + LED file must start with "LEDImage = IMAGE[". +\endverbatim + * \ingroup format */ +void imFormatRegisterLED(void); + +/** \defgroup sgi SGI - Silicon Graphics Image File Format + * \section Description + * + * \par + * SGI is a trademark of Silicon Graphics, Inc. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte and UShort + Color Spaces: Gray and RGB (Binary saved as Gray, MAP with fixed palette when reading only) + Compressions: + NONE - no compression [default] + RLE - Run Lenght Encoding + Only one image. + Can have an alpha channel (only for IM_RGB) + Internally the components are always packed. + Internally the lines are arranged from bottom up to top. + + Attributes: + Description (string) +\endverbatim + * \ingroup format */ +void imFormatRegisterSGI(void); + +/** \defgroup pcx PCX - ZSoft Picture + * \section Description + * + * \par + * Copyright ZSoft Corporation. \n + * ZSoft (1988) PCX Technical Reference Manual. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB, MAP and Binary (Gray saved as MAP) + Compressions: + NONE - no compression + RLE - Run Lenght Encoding [default - since uncompressed PCX is not well supported] + Only one image. + No alpha channel. + Internally the components are always packed. + Internally the lines are arranged from top down to bottom. + + Attributes: + ResolutionUnit (string) ["DPC", "DPI"] + XResolution, YResolution IM_FLOAT (1) + XScreen, YScreen IM_USHORT (1) screen position + + Comments: + Reads Versions 0-5, but writes Version 5 always. +\endverbatim + * \ingroup format */ +void imFormatRegisterPCX(void); + +/** \defgroup tga TGA - Truevision Graphics Adapter File + * \section Description + * + * \par + * Truevision TGA File Format Specification Version 2.0 \n + * Technical Manual Version 2.2 January, 1991 \n + * Copyright 1989, 1990, 1991 Truevision, Inc. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Supports 8 bits per component only. Data type is always Byte. + Color Spaces: Gray, RGB and MAP (Binary saved as Gray) + Compressions: + NONE - no compression [default] + RLE - Run Lenght Encoding + Only one image. + No alpha channel. + Internally the components are always packed. + Internally the lines are arranged from bottom up to top or from top down to bottom. + + Attributes: + XScreen, YScreen IM_USHORT (1) screen position + Title, Author, Description, JobName, Software (string) + SoftwareVersion (read only) (string) + DateTimeModified (string) [when writing uses the current system time] + Gamma IM_FLOAT (1) +\endverbatim + * \ingroup format */ +void imFormatRegisterTGA(void); + +/** \defgroup pnm PNM - Netpbm Portable Image Map + * \section Description + * + * \par + * PNM formats Copyright Jef Poskanzer + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte and UShort + Color Spaces: Gray, RGB and Binary + Compressions: + NONE - no compression [default] + ASCII (textual data) + Can have more than one image, but sequencial access only. + No alpha channel. + Internally the components are always packed. + Internally the lines are arranged from top down to bottom. + + Attributes: + Description (string) + + Comments: + In fact ASCII is an expansion... +\endverbatim + * \ingroup format */ +void imFormatRegisterPNM(void); + +/** \defgroup ico ICO - Windows Icon + * \section Description + * + * \par + * Windows Copyright Microsoft Corporation. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB, MAP and Binary (Gray saved as MAP) + Compressions: + NONE - no compression [default] + Can have more than one image. But writing is limited to 5 images, + and all images must have different sizes and bpp. + Can have an alpha channel (only for RGB) + Internally the components are always packed. + Internally the lines are arranged from bottom up to top. + + Attributes: + TransparencyIndex IM_BYTE (1 or N) + + Comments: + If the user specifies an alpha channel, the AND mask is loaded as alpha if + the file color mode does not contain the IM_ALPHA flag. + For MAP imagens, if the user does not specifies an alpha channel + the TransparencyIndex is used to initialize the AND mask when writing, + and if the user does specifies an alpha channel + the most repeated index with transparency will be the transparent index. + Although any size and common bpp can be used is recomended to use the typical configurations: + 16x16, 32x32, 48x48, 64x64 or 96x96 + 2 colors, 16 colors, 256 colors, 24bpp or 32bpp +\endverbatim + * \ingroup format */ +void imFormatRegisterICO(void); + +/** \defgroup krn KRN - IM Kernel File Format + * \section Description + * + * \par + * Textual format to provied a simple way to create kernel convolution images. + * \par + * Internal Implementation. + * + * \section Features + * +\verbatim + Data Types: Byte, Int + Color Spaces: Gray + Compressions: + NONE - no compression [default] + Only one image. + No alpha channel. + Internally the lines are arranged from top down to bottom. + + Attributes: + Description (string) + + Comments: + The format is very simple, inspired by PNM. + It was developed because PNM does not have support for INT and FLOAT. + Remeber that usually convolution operations use kernel size an odd number. + + Format Model: + IMKERNEL + Description up to 512 characters + width height + type (0 - IM_INT, 1 - IM_FLOAT) + data... + + Example: + IMKERNEL + Gradian + 3 3 + 0 + 0 -1 0 + 0 1 0 + 0 0 0 +\endverbatim + * \ingroup format */ +void imFormatRegisterKRN(void); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_format_avi.h b/include/im_format_avi.h new file mode 100644 index 0000000..32eb7fa --- /dev/null +++ b/include/im_format_avi.h @@ -0,0 +1,87 @@ +/** \file + * \brief Register the AVI Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_AVI_H +#define __IM_FORMAT_AVI_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup avi AVI - Windows Audio-Video Interleaved RIFF + * \section Description + * + * \par + * Windows Copyright Microsoft Corporation. + * \par + * Access to the AVI format uses Windows AVIFile library. Available in Windows Only. \n + * When writing a new file you must use an ".avi" extension, or the Windows API will fail. \n + * You must link the application with "im_avi.lib" + * and you must call the function \ref imFormatRegisterAVI once + * to register the format into the IM core library. \n + * Depends also on the VFW library (vfw32.lib). + * When using the "im_avi.dll" this extra library is not necessary. \n + * If using Cygwin or MingW must link with "-lvfw32". + * Old versions of Cygwin and MingW use the "-lvfw_ms32" and "-lvfw_avi32". + * \par + * See \ref im_format_avi.h + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB, MAP and Binary (Gray saved as MAP) + Compressions (installed in Windows XP by default): + NONE - no compression [default] + RLE - Microsoft RLE (8bpp only) + CINEPACK - Cinepak Codec by Radius + MSVC - Microsoft Video 1 (old) + M261 - Microsoft H.261 Video Codec + M263 - Microsoft H.263 Video Codec + I420 - Intel 4:2:0 Video Codec (same as M263) + IV32 - Intel Indeo Video Codec 3.2 (old) + IV41 - Intel Indeo Video Codec 4.5 (old) + IV50 - Intel Indeo Video 5.1 + IYUV - Intel IYUV Codec + MPG4 - Microsoft MPEG-4 Video Codec V1 (not MPEG-4 compliant) (old) + MP42 - Microsoft MPEG-4 Video Codec V2 (not MPEG-4 compliant) + CUSTOM - (show compression dialog) + DIVX - DivX 5.0.4 Codec (DivX must be installed) + (others, must be the 4 charaters of the fourfcc code) + Can have more than one image. + Can have an alpha channel (only for RGB) + Internally the components are always packed. + Lines arranged from top down to bottom or bottom up to top. But are saved always as bottom up. + Handle(0) returns NULL. imBinFile is not supported. + Handle(1) returns PAVIFILE. + Handle(2) returns PAVISTREAM. + + Attributes: + FPS IM_FLOAT (1) (should set when writing, default 15) + AVIQuality IM_INT (1) [1-10000, default -1] (write only) + KeyFrameRate IM_INT (1) (write only) [key frame frequency, if 0 not using key frames, default 15] + DataRate IM_INT (1) (write only) [kilobits/second, default 2400] + + Comments: + Reads only the first video stream. Other streams are ignored. + All the images have the same size, you must call imFileReadImageInfo/imFileWriteImageInfo + at least once. + For codecs comparsion and download go to: + http://graphics.lcs.mit.edu/~tbuehler/video/codecs/ + http://www.fourcc.org +\endverbatim + * \ingroup format */ + +/** Register the AVI Format. \n + * In Lua, when using require"imlua_avi" this function will be automatically called. + * \ingroup avi */ +void imFormatRegisterAVI(void); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_format_ecw.h b/include/im_format_ecw.h new file mode 100644 index 0000000..701bac3 --- /dev/null +++ b/include/im_format_ecw.h @@ -0,0 +1,93 @@ +/** \file + * \brief Register the ECW Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_ECW_H +#define __IM_FORMAT_ECW_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup ecw ECW - ECW JPEG 2000 + * \section Description + * + * \par + * ECW JPEG 2000 Copyright 1998 Earth Resource Mapping Ltd. + * Two formats are supported with this module. The ECW (Enhanced Compression Wavelet) format and the ISO JPEG 2000 format. + * \par + * Access to the ECW format uses the ECW JPEG 2000 SDK version 3.3. + * Available in Windows, Linux and Solaris Only. But source code is also available. \n + * You must link the application with "im_ecw.lib" + * and you must call the function \ref imFormatRegisterECW once + * to register the format into the IM core library. \n + * Depends also on the ECW JPEG 2000 SDK libraries (NCSEcw.lib). + * \par + * When using other JPEG 2000 libraries the first registered library will be used to guess the file format. + * Use the extension *.ecw to shortcut to this implementation of the JPEG 2000 format. + * \par + * See \ref im_format_ecw.h + * \par + * \par + * http://www.ermapper.com/ecw/ \n + * The three types of licenses available for the ECW JPEG 2000 SDK are as follows: +\verbatim + - ECW JPEG 2000 SDK Free Use License Agreement - This license governs the free use of + the ECW JPEG 2000 SDK with Unlimited Decompression and Limited Compression (Less + than 500MB). + - ECW JPEG 2000 SDK Public Use License Agreement - This license governs the use of the + ECW SDK with Unlimited Decompression and Unlimited Compression for applications + licensed under a GNU General Public style license. + - ECW JPEG 2000 SDK Commercial Use License Agreement - This license governs the use + of the ECW JPEG 2000 SDK with Unlimited Decompression and Unlimited Compression + for commercial applications. +\endverbatim + * + * \section Features + * +\verbatim + Data Types: Byte, UShort, Float + Color Spaces: BINARY, GRAY, RGB, YCBCR + Compressions: + ECW - Enhanced Compression Wavelet + JPEG-2000 - ISO JPEG 2000 + Only one image. + Can have an alpha channel + Internally the components are always packed. + Lines arranged from top down to bottom. + Handle() returns NCSFileView* when reading, NCSEcwCompressClient* when writing. + + Attributes: + CompressionRatio IM_FLOAT (1) [example: Ratio=7 just like 7:1] + OriginX, OriginY IM_FLOAT (1) + Rotation IM_FLOAT (1) + CellIncrementX, CellIncrementY IM_FLOAT (1) + CellUnits (string) + Datum (string) + Projection (string) + ViewWidth, ViewHeight IM_INT (1) [view zoom] + ViewXmin, ViewYmin, ViewXmax, ViewYmax IM_INT (1) [view limits] + MultiBandCount IM_USHORT (1) [Number of bands in a multiband gray image.] + MultiBandSelect IM_USHORT (1) [Band number to read one band of a multiband gray image. Must be set before reading image info.] + + Comments: + Only read support is implemented. + To read a region of the image you must set the View* attributes before reading the image data. + After reading a partial image the width and height returned in ReadImageInfo is the view size. + The view limits define the region to be readed. + The view size is the actual size of the image, so the result can be zoomed. +\endverbatim + * \ingroup format */ + +/** Register the ECW Format + * \ingroup ecw */ +void imFormatRegisterECW(void); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_format_jp2.h b/include/im_format_jp2.h new file mode 100644 index 0000000..96c1c0a --- /dev/null +++ b/include/im_format_jp2.h @@ -0,0 +1,78 @@ +/** \file + * \brief Register the JP2 Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_JP2_H +#define __IM_FORMAT_JP2_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup jp2 JP2 - JPEG-2000 JP2 File Format + * \section Description + * + * \par + * ISO/IEC 15444 (2000, 2003)\n + * http://www.jpeg.org/ + * \par + * You must link the application with "im_jp2.lib" + * and you must call the function \ref imFormatRegisterJP2 once + * to register the format into the IM core library. \n + * \par + * Access to the JPEG2000 file format uses libJasper version 1.900.1 \n + * http://www.ece.uvic.ca/~mdadams/jasper \n + * Copyright (c) 2001-2006 Michael David Adams. \n + * and GeoJasPer 1.4.0 \n + * Copyright (c) 2003-2007 Dmitry V. Fedorov. \n + * http://www.dimin.net/software/geojasper/ \n + * + * \par + * See \ref im_format_jp2.h + * + * \section Features + * +\verbatim + Data Types: Byte and UShort + Color Spaces: Binary, Gray, RGB, YCbCr, Lab and XYZ + Compressions: + JPEG-2000 - ISO JPEG 2000 [default] + Only one image. + Can have an alpha channel. + Internally the components are always unpacked. + Internally the lines are arranged from top down to bottom. + Handle(1) returns jas_image_t* + Handle(2) returns jas_stream_t* + + Attributes: + CompressionRatio IM_FLOAT (1) [write only, example: Ratio=7 just like 7:1] + GeoTIFFBox IM_BYTE (n) + XMLPacket IM_BYTE (n) + + Comments: + We read code stream syntax and JP2, but we write always as JP2. + Used definitions EXCLUDE_JPG_SUPPORT,EXCLUDE_MIF_SUPPORT, + EXCLUDE_PNM_SUPPORT,EXCLUDE_RAS_SUPPORT, + EXCLUDE_BMP_SUPPORT,EXCLUDE_PGX_SUPPORT + Changed jas_config.h to match our needs. + New file jas_binfile.c + Changed base/jas_stream.c to export jas_stream_create and jas_stream_initbuf. + Changed jp2/jp2_dec.c and jpc/jpc_cs.c to remove "uint" and "ulong" usage. + The counter is restarted many times, because it has many phases. +\endverbatim + * \ingroup format */ + +/** Register the JP2 Format. \n + * In Lua, when using require"imlua_jp2" this function will be automatically called. + * \ingroup jp2 */ +void imFormatRegisterJP2(void); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_format_raw.h b/include/im_format_raw.h new file mode 100644 index 0000000..8027f82 --- /dev/null +++ b/include/im_format_raw.h @@ -0,0 +1,64 @@ +/** \file + * \brief Initialize the RAW Format Driver + * Header for internal use only. + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_RAW_H +#define __IM_FORMAT_RAW_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup raw RAW - RAW File + * + * \par + * The file must be open/created with the functions \ref imFileOpenRaw and \ref imFileNewRaw. + * + * \section Description + * + * \par + * Internal Implementation. + * \par + * Supports RAW binary images. You must know image parameters a priori. \n + * You must set the IM_INT attributes "Width", "Height", "ColorMode", "DataType" before the imFileReadImageInfo/imFileWriteImageInfo functions. + * \par + * The data must be in binary form, but can start in an arbitrary offset from the begining of the file, use attribute "StartOffset". + * The default is at 0 offset. + * \par + * Integer sign and double precision can be converted using attribute "SwitchType". \n + * The conversions will be BYTE<->CHAR, USHORT<->SHORT, INT<->UINT, FLOAT<->DOUBLE. + * \par + * Byte Order can be Little Endian (Intel=1) or Big Endian (Motorola=0), use the attribute "ByteOrder", the default is the current CPU. + * \par + * The lines can be aligned to a BYTE (1), WORD (2) or DWORD (4) boundaries, ue attribute "Padding" with the respective value. + * \par + * See \ref im_raw.h + * + * \section Features + * +\verbatim + Data Types: <all> + Color Spaces: all, except MAP. + Compressions: + NONE - no compression + Can have more than one image, depends on "StartOffset" attribute. + Can have an alpha channel. + Components can be packed or not. + Lines arranged from top down to bottom or bottom up to top. + + Attributes: + Width, Height, ColorMode, DataType IM_INT (1) + StartOffset, SwitchType, ByteOrder, Padding IM_INT (1) +\endverbatim + * \ingroup format */ +imFormat* imFormatInitRAW(void); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_format_wmv.h b/include/im_format_wmv.h new file mode 100644 index 0000000..10007b8 --- /dev/null +++ b/include/im_format_wmv.h @@ -0,0 +1,100 @@ +/** \file + * \brief Register the WMF Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_FORMAT_WMV_H +#define __IM_FORMAT_WMV_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** \defgroup wmv WMV - Windows Media Video Format + * \section Description + * + * \par + * Advanced Systems Format (ASF) \n + * Windows Copyright Microsoft Corporation. + * \par + * Access to the WMV format uses Windows Media SDK. Available in Windows Only. \n + * You must link the application with "im_wmv.lib" + * and you must call the function \ref imFormatRegisterWMV once + * to register the format into the IM core library. \n + * Depends also on the WMF SDK (wmvcore.lib). + * When using the "im_wmv.dll" this extra library is not necessary. + * \par + * The application users should have the WMV codec 9 installed: + * http://www.microsoft.com/windows/windowsmedia/format/codecdownload.aspx + * \par + * You must agree with the WMF SDK EULA to use the SDK. \n + * http://wmlicense.smdisp.net/v9sdk/ + * \par + * For more information: \n + * http://www.microsoft.com/windows/windowsmedia/9series/sdk.aspx \n + * http://msdn.microsoft.com/library/en-us/wmform/htm/introducingwindowsmediaformat.asp + * \par + * See \ref im_format_wmv.h + * + * \section Features + * +\verbatim + Data Types: Byte + Color Spaces: RGB and MAP (Gray and Binary saved as MAP) + Compressions (installed in Windows XP by default): + NONE - no compression + MPEG-4v3 - Windows Media MPEG-4 Video V3 + MPEG-4v1 - ISO MPEG-4 Video V1 + WMV7 - Windows Media Video V7 + WMV7Screen - Windows Media Screen V7 + WMV8 - Windows Media Video V8 + WMV9Screen - Windows Media Video 9 Screen + WMV9 - Windows Media Video 9 [default] + Unknown - Others + Can have more than one image. + Can have an alpha channel (only for RGB) ? + Internally the components are always packed. + Lines arranged from top down to bottom or bottom up to top. + Handle(0) return NULL. imBinFile is not supported. + Handle(1) returns IWMSyncReader* when reading, IWMWriter* when writing. + + Attributes: + FPS IM_FLOAT (1) (should set when writing, default 15) + WMFQuality IM_INT (1) [0-100, default 50] (write only) + MaxKeyFrameTime IM_INT (1) (write only) [maximum key frame interval in miliseconds, default 5 seconds] + DataRate IM_INT (1) (write only) [kilobits/second, default 2400] + VBR IM_INT (1) [0, 1] (write only) [0 - Constant Bit Rate (default), 1 - Variable Bit Rate (Quality-Based)] + (and several others from the file-level attributes) For ex: + Title, Author, Copyright, Description (string) + Duration IM_INT [100-nanosecond units] + Seekable, HasAudio, HasVideo, Is_Protected, Is_Trusted, IsVBR IM_INT (1) [0, 1] + NumberOfFrames IM_INT (1) + + Comments: + IMPORTANT - The "image_count" and the "FPS" attribute may not be available from the file, + we try to estimate from the duration and from the average time between frames, or using the default value. + We do not handle DRM protected files (Digital Rights Management). + Reads only the first video stream. Other streams are ignored. + All the images have the same size, you must call imFileReadImageInfo/imFileWriteImageInfo + at least once. + For optimal random reading, the file should be indexed previously. + If not indexed by frame, random positioning may not be precise. + Sequencial reading will always be precise. + When writing we use a custom profile and time indexing only. + We do not support multipass encoding. + Since the driver uses COM, CoInitialize(NULL) and CoUninitialize() are called every Open/Close. +\endverbatim + * \ingroup format */ + +/** Register the WMF Format. \n + * In Lua, when using require"imlua_wmv" this function will be automatically called. + * \ingroup wmv */ +void imFormatRegisterWMV(void); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_image.h b/include/im_image.h new file mode 100644 index 0000000..fca3212 --- /dev/null +++ b/include/im_image.h @@ -0,0 +1,403 @@ +/** \file + * \brief Image Manipulation + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_IMAGE_H +#define __IM_IMAGE_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup imgclass imImage + * + * \par + * Base definitions and functions for image representation. \n + * Only the image processing operations depends on these definitions, + * Image Storage and Image Capture are completely independent. + * \par + * You can also initialize a structure with your own memory buffer, see \ref imImageInit. + * To release the structure without releasing the buffer, + * set "data[0]" to NULL before calling imImageDestroy. + * \par + * See \ref im_image.h + * \ingroup imagerep */ + + + +/** \brief imImage Structure Definition. + * + * \par + * An image representation than supports all the color spaces, + * but planes are always unpacked and the orientation is always bottom up. + * \ingroup imgclass */ +typedef struct _imImage +{ + /* main parameters */ + int width; /**< Number of columns. image:Width() -> width: number [in Lua 5]. */ + int height; /**< Number of lines. image:Height() -> height: number [in Lua 5]. */ + int color_space; /**< Color space descriptor. See also \ref imColorSpace. image:ColorSpace() -> color_space: number [in Lua 5]. */ + int data_type; /**< Data type descriptor. See also \ref imDataType. image:DataType() -> data_type: number [in Lua 5]. */ + int has_alpha; /**< Indicates that there is an extra channel with alpha. image:HasAlpha() -> has_alpha: number [in Lua 5]. \n + It will not affect the secondary parameters, i.e. the number of planes will be in fact depth+1. \n + It is always 0 unless imImageAddAlpha is called, this is done in image load functions. */ + + /* secondary parameters */ + int depth; /**< Number of planes (ColorSpaceDepth) */ + int line_size; /**< Number of bytes per line in one plane (width * DataTypeSize) */ + int plane_size; /**< Number of bytes per plane. (line_size * height) */ + int size; /**< Number of bytes occupied by the image (plane_size * depth) */ + int count; /**< Number of pixels (width * height) */ + + /* image data */ + void** data; /**< Image data organized as a 2D matrix with several planes. \n + But plane 0 is also a pointer to the full data. \n + The remaining planes are: data[i] = data[0] + i*plane_size \n + In Lua, data indexing is possible using: image[plane][row][column] */ + + /* image attributes */ + long *palette; /**< Color palette. image:GetPalette() -> palette: imPalette [in Lua 5]. \n + Used when depth=1. Otherwise is NULL. */ + int palette_count; /**< The palette is always 256 colors allocated, but can have less colors used. */ + + void* attrib_table; /**< in fact is an imAttribTable, but we hide this here */ +} imImage; + + +/** Creates a new image. + * See also \ref imDataType and \ref imColorSpace. \n + * In Lua the IM image metatable name is "imImage". + * When converted to a string will return "imImage(%p) [width=%d,height=%d,color_space=%s,data_type=%s,depth=%d]" where %p is replaced by the userdata address, + * and other values are replaced by the respective attributes. + * If the image is already destroyed by im.ImageDestroy, then it will return also the suffix "-destroyed". + * + * \verbatim im.ImageCreate(width: number, height: number, color_space: number, data_type: number) -> image: imImage [in Lua 5] \endverbatim + * \ingroup imgclass */ +imImage* imImageCreate(int width, int height, int color_space, int data_type); + +/** Initializes the image structure but does not allocates image data. + * See also \ref imDataType and \ref imColorSpace. + * \ingroup imgclass */ +imImage* imImageInit(int width, int height, int color_space, int data_type, void* data_buffer, long* palette, int palette_count); + +/** Creates a new image based on an existing one. \n + * If the addicional parameters are -1, the given image parameters are used. \n + * The image atributes always are copied. + * See also \ref imDataType and \ref imColorSpace. + * + * \verbatim im.ImageCreateBased(image: imImage, [width: number], [height: number], [color_space: number], [data_type: number]) -> image: imImage [in Lua 5] \endverbatim + * The addicional parameters in Lua can be nil, + * and they can also be functions with the based image as a parameter to return the respective value. + * \ingroup imgclass */ +imImage* imImageCreateBased(const imImage* image, int width, int height, int color_space, int data_type); + +/** Destroys the image and frees the memory used. + * image data is destroyed only if its data[0] is not NULL. \n + * In Lua if this function is not called, the image is destroyed by the garbage collector. + * + * \verbatim im.ImageDestroy(image: imImage) [in Lua 5] \endverbatim + * \verbatim image:Destroy() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageDestroy(imImage* image); + +/** Adds an alpha channel plane. + * + * \verbatim image:AddAlpha() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageAddAlpha(imImage* image); + +/** Changes the buffer size. Reallocate internal buffers if the new size is larger than the original. + * + * \verbatim image:Reshape(width: number, height: number) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageReshape(imImage* image, int width, int height); + +/** Copy image data and attributes from one image to another. \n + * Images must have the same size and type. + * + * \verbatim image:Copy(dst_image: imImage) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageCopy(const imImage* src_image, imImage* dst_image); + +/** Copy image data only fom one image to another. \n + * Images must have the same size and type. + * + * \verbatim image:CopyData(dst_image: imImage) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageCopyData(const imImage* src_image, imImage* dst_image); + +/** Creates a copy of the image. + * + * \verbatim image:Duplicate() -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup imgclass */ +imImage* imImageDuplicate(const imImage* image); + +/** Creates a clone of the image. i.e. same attributes but ignore contents. + * + * \verbatim image:Clone() -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup imgclass */ +imImage* imImageClone(const imImage* image); + +/** Changes an extended attribute. \n + * The data will be internally duplicated. \n + * If data is NULL the attribute is removed. \n + * If count is -1 and data_type is IM_BYTE then data is zero terminated. + * See also \ref imDataType. + * + * \verbatim image:SetAttribute(attrib: string, data_type: number, data: table of numbers or string) [in Lua 5] \endverbatim + * If data_type is IM_BYTE, as_string can be used as data. + * \ingroup imgclass */ +void imImageSetAttribute(imImage* image, const char* attrib, int data_type, int count, const void* data); + +/** Returns an extended attribute. \n + * Returns NULL if not found. + * See also \ref imDataType. + * + * \verbatim image:GetAttribute(attrib: string, [as_string: boolean]) -> data: table of numbers or string, data_type: number [in Lua 5] \endverbatim + * If data_type is IM_BYTE, as_string can be used to return a string instead of a table. + * \ingroup imgclass */ +const void* imImageGetAttribute(const imImage* image, const char* attrib, int *data_type, int *count); + +/** Returns a list of the attribute names. \n + * "attrib" must contain room enough for "attrib_count" names. Use "attrib=NULL" to return only the count. + * + * \verbatim image:GetAttributeList() -> data: table of strings [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageGetAttributeList(const imImage* image, char** attrib, int *attrib_count); + +/** Sets all image data to zero. + * + * \verbatim image:Clear() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageClear(imImage* image); + +/** Indicates that the image can be viewed in common graphic devices. + * Data type must be IM_BYTE. Color mode can be IM_RGB, IM_MAP, IM_GRAY or IM_BINARY. + * + * \verbatim image:IsBitmap() -> is_bitmap: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageIsBitmap(const imImage* image); + +/** Changes the image palette. + * This will destroy the existing palette and replace it with the given palette buffer. + * + * \verbatim image:SetPalette(palette: imPalette) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageSetPalette(imImage* image, long* palette, int palette_count); + +/** Copies the image attributes from src to dst. + * + * \verbatim image:CopyAttributes(dst_image: imImage) [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageCopyAttributes(const imImage* src_image, imImage* dst_image); + +/** Returns 1 if the images match width and height. Returns 0 otherwise. + * + * \verbatim image:MatchSize(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatchSize(const imImage* image1, const imImage* image2); + +/** Returns 1 if the images match color mode and data type. Returns 0 otherwise. + * + * \verbatim image:MatchColor(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatchColor(const imImage* image1, const imImage* image2); + +/** Returns 1 if the images match width, height and data type. Returns 0 otherwise. + * + * \verbatim image:MatchDataType(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatchDataType(const imImage* image1, const imImage* image2); + +/** Returns 1 if the images match width, height and color space. Returns 0 otherwise. + * + * \verbatim image:MatchColorSpace(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatchColorSpace(const imImage* image1, const imImage* image2); + +/** Returns 1 if the images match in width, height, data type and color space. Returns 0 otherwise. + * + * \verbatim image:Match(image2: imImage) -> match: boolean [in Lua 5] \endverbatim + * \ingroup imgclass */ +int imImageMatch(const imImage* image1, const imImage* image2); + +/** Changes the image space from gray to binary by just changing color_space and the palette. + * + * \verbatim image:SetBinary() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageSetBinary(imImage* image); + +/** Changes a gray data into a binary data, done in-place. + * + * \verbatim image:MakeBinary() [in Lua 5] \endverbatim + * \ingroup imgclass */ +void imImageMakeBinary(imImage *image); + + + +/** \defgroup imgfile imImage Storage + * + * \par + * Functions to simplify the process of reading and writting imImage structures. + * Will also load and save the alpha planes when possible. + * \par + * See \ref im_image.h + * \ingroup file */ + + +/** Loads an image from an already open file. Returns NULL if failed. \n + * This will call \ref imFileReadImageInfo and \ref imFileReadImageData. \n + * index specifies the image number between 0 and image_count-1. \n + * The returned image will be of the same color_space and data_type of the image in the file. \n + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim ifile:LoadImage([index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileLoadImage(imFile* ifile, int index, int *error); + +/** Loads an image from an already open file. Returns NULL if failed. \n + * This function assumes that the image in the file has the same parameters as the given image. \n + * This will call \ref imFileReadImageInfo and \ref imFileReadImageData. \n + * index specifies the image number between 0 and image_count-1. \n + * The returned image will be of the same color_space and data_type of the image in the file. \n + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim ifile:LoadImageFrame(index: number, image: imImage) -> error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +void imFileLoadImageFrame(imFile* ifile, int index, imImage* image, int *error); + +/** Loads an image from an already open file, but forces the image to be a bitmap.\n + * The returned imagem will be always a Bitmap image, with color_space RGB, MAP, GRAY or BINARY, and data_type IM_BYTE. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim ifile:LoadBitmap([index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileLoadBitmap(imFile* ifile, int index, int *error); + +/** Loads an image region from an already open file. Returns NULL if failed. \n + * This will call \ref imFileReadImageInfo and \ref imFileReadImageData. \n + * index specifies the image number between 0 and image_count-1. \n + * The returned image will be of the same color_space and data_type of the image in the file, + * or will be a Bitmap image. \n + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. \n + * For now works only for ECW file format. + * + * \verbatim ifile:LoadRegion(index, bitmap, xmin, xmax, ymin, ymax, width, height: number) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileLoadImageRegion(imFile* ifile, int index, int bitmap, int *error, + int xmin, int xmax, int ymin, int ymax, int width, int height); + +/** Loads an image from an already open file, but forces the image to be a bitmap.\n + * This function assumes that the image in the file has the same parameters as the given image. \n + * The imagem must be a Bitmap image, with color_space RGB, MAP, GRAY or BINARY, and data_type IM_BYTE. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim ifile:LoadBitmapFrame(index: number, image: imImage) -> error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +void imFileLoadBitmapFrame(imFile* ifile, int index, imImage* image, int *error); + +/** Saves the image to an already open file. \n + * This will call \ref imFileWriteImageInfo and \ref imFileWriteImageData. \n + * Attributes from the image will be stored at the file. + * Returns error code. + * + * \verbatim ifile:SaveImage(image: imImage) -> error: number [in Lua 5] \endverbatim + * \ingroup imgfile */ +int imFileSaveImage(imFile* ifile, const imImage* image); + +/** Loads an image from file. Open, loads and closes the file. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim im.FileImageLoad(file_name: string, [index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileImageLoad(const char* file_name, int index, int *error); + +/** Loads an image from file, but forces the image to be a bitmap. Open, loads and closes the file. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. + * + * \verbatim im.FileImageLoadBitmap(file_name: string, [index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileImageLoadBitmap(const char* file_name, int index, int *error); + +/** Loads an image region from file. Open, loads and closes the file. \n + * index specifies the image number between 0 and image_count-1. \n + * Returns NULL if failed. + * Attributes from the file will be stored at the image. + * See also \ref imErrorCodes. \n + * For now works only for ECW file format. + * + * \verbatim im.FileImageLoadRegion(file_name: string, index, bitmap, xmin, xmax, ymin, ymax, width, height: number, ) -> image: imImage, error: number [in Lua 5] \endverbatim + * Default index is 0. + * \ingroup imgfile */ +imImage* imFileImageLoadRegion(const char* file_name, int index, int bitmap, int *error, + int xmin, int xmax, int ymin, int ymax, int width, int height); + +/** Saves the image to file. Open, saves and closes the file. \n + * Returns error code. \n + * Attributes from the image will be stored at the file. + * + * \verbatim im.FileImageSave(file_name: string, format: string, image: imImage) -> error: number [in Lua 5] \endverbatim + * \verbatim image:Save(file_name: string, format: string) -> error: number [in Lua 5] \endverbatim + * \ingroup imgfile */ +int imFileImageSave(const char* file_name, const char* format, const imImage* image); + + + +/** Utility macro to draw the image in a CD library canvas. + * Works only for data_type IM_BYTE, and color spaces: IM_RGB, IM_MAP, IMGRAY and IM_BINARY. + * \ingroup imgclass */ +#define imcdCanvasPutImage(_canvas, _image, _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax) \ + { \ + if (_image->color_space == IM_RGB) \ + { \ + if (_image->has_alpha) \ + cdCanvasPutImageRectRGBA(_canvas, _image->width, _image->height, \ + (unsigned char*)_image->data[0], \ + (unsigned char*)_image->data[1], \ + (unsigned char*)_image->data[2], \ + (unsigned char*)_image->data[3], \ + _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax); \ + else \ + cdCanvasPutImageRectRGB(_canvas, _image->width, _image->height, \ + (unsigned char*)_image->data[0], \ + (unsigned char*)_image->data[1], \ + (unsigned char*)_image->data[2], \ + _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax); \ + } \ + else \ + cdCanvasPutImageRectMap(_canvas, _image->width, _image->height, \ + (unsigned char*)_image->data[0], _image->palette, \ + _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax); \ + } + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_kernel.h b/include/im_kernel.h new file mode 100644 index 0000000..db066d8 --- /dev/null +++ b/include/im_kernel.h @@ -0,0 +1,315 @@ +/** \file + * \brief Kernel Generators + * Creates several known kernels + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_KERNEL_H +#define __IM_KERNEL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup kernel Kernel Generators + * \par + * Creates several known kernels + * \par + * See \ref im_kernel.h + * \ingroup convolve */ + + +/** Creates a kernel with the following values: + * +\verbatim + 1 2 1 + 0 0 0 + -1 -2 -1 +\endverbatim + * + * \verbatim im.KernelSobel() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelSobel(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 1 1 + 0 0 0 + -1 -1 -1 +\endverbatim + * + * \verbatim im.KernelPrewitt() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelPrewitt(void); + +/** Creates a kernel with the following values: + * +\verbatim + 5 5 5 + -3 0 -3 + -3 -3 -3 +\endverbatim + * + * \verbatim im.KernelKirsh() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelKirsh(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 0 + -1 4 -1 + 0 -1 0 +\endverbatim + * + * \verbatim im.KernelLaplacian4() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelLaplacian4(void); + +/** Creates a kernel with the following values: + * +\verbatim + -1 -1 -1 + -1 8 -1 + -1 -1 -1 +\endverbatim + * + * \verbatim im.KernelLaplacian8() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelLaplacian8(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 -1 -1 0 + -1 0 1 0 -1 + -1 1 8 1 -1 + -1 0 1 0 -1 + 0 -1 -1 -1 0 +\endverbatim + * + * \verbatim im.KernelLaplacian5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelLaplacian5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 48 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 + -1 -1 -1 -1 -1 -1 -1 +\endverbatim + * + * \verbatim im.KernelLaplacian7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelLaplacian7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 0 + 0 1 0 + 0 0 0 +\endverbatim + * + * \verbatim im.KernelGradian3x3() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelGradian3x3(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 -1 0 1 1 0 + -1 -2 -2 0 2 2 1 + -1 -2 -3 0 3 2 1 + -1 -2 -3 0 3 2 1 + -1 -2 -3 0 3 2 1 + -1 -2 -2 0 2 2 1 + 0 -1 -1 0 1 1 0 +\endverbatim + * + * \verbatim im.KernelGradian7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelGradian7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + -1 0 0 + 0 0 0 + 0 0 1 +\endverbatim + * + * \verbatim im.KernelSculpt() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelSculpt(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 1 1 + 1 1 1 + 1 1 1 +\endverbatim + * + * \verbatim im.KernelMean3x3() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelMean3x3(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 1 1 1 1 + 1 1 1 1 1 + 1 1 1 1 1 + 1 1 1 1 1 + 1 1 1 1 1 +\endverbatim + * + * \verbatim im.KernelMean5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelMean5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 1 1 1 0 + 1 1 1 1 1 + 1 1 1 1 1 + 1 1 1 1 1 + 0 1 1 1 0 +\endverbatim + * + * \verbatim im.KernelMean5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelCircularMean5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 +\endverbatim + * + * \verbatim im.KernelMean7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelMean7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 0 1 1 1 0 0 + 0 1 1 1 1 1 0 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 + 0 1 1 1 1 1 0 + 0 0 1 1 1 0 0 +\endverbatim + * + * \verbatim im.KernelCircularMean7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelCircularMean7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 2 1 + 2 4 2 + 1 2 1 +\endverbatim + * + * \verbatim im.KernelGaussian3x3() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelGaussian3x3(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 4 6 4 1 + 4 16 24 16 4 + 6 24 36 24 6 + 4 16 24 16 4 + 1 4 6 4 1 +\endverbatim + * + * \verbatim im.KernelGaussian5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelGaussian5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 1 2 3 2 1 + 2 4 6 4 2 + 3 6 9 6 3 + 2 4 6 4 2 + 1 2 3 2 1 +\endverbatim + * + * \verbatim im.KernelBarlett5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelBarlett5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 -1 -1 0 + -1 -1 3 -1 -1 + -1 3 4 3 -1 + -1 -1 3 -1 -1 + 0 -1 -1 -1 0 +\endverbatim + * + * \verbatim im.KernelTopHat5x5() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelTopHat5x5(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 0 -1 -1 -1 0 0 + 0 -1 -1 -1 -1 -1 0 + -1 -1 3 3 3 -1 -1 + -1 -1 3 4 3 -1 -1 + -1 -1 3 3 3 -1 -1 + 0 -1 -1 -1 -1 -1 0 + 0 0 -1 -1 -1 0 0 +\endverbatim + * + * \verbatim im.KernelTopHat7x7() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelTopHat7x7(void); + +/** Creates a kernel with the following values: + * +\verbatim + 0 -1 -2 -1 0 + -1 -4 0 -4 -1 + -2 0 40 0 -2 + -1 -4 0 -4 -1 + 0 -1 -2 -1 0 +\endverbatim + * + * \verbatim im.KernelEnhance() -> kernel: imImage [in Lua 5] \endverbatim + * \ingroup kernel */ +imImage* imKernelEnhance(void); + +#if defined(__cplusplus) +} +#endif + +#endif + diff --git a/include/im_lib.h b/include/im_lib.h new file mode 100644 index 0000000..80330cc --- /dev/null +++ b/include/im_lib.h @@ -0,0 +1,191 @@ +/** \file + * \brief Library Management and Main Documentation + * + * See Copyright Notice in this file. + */ + +#ifndef __IM_LIB_H +#define __IM_LIB_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup lib Library Management + * \ingroup util + * \par + * Usefull definitions for about dialogs and + * for comparing the compiled version with the linked version of the library. + * \par + * \verbatim im._AUTHOR [in Lua 5] \endverbatim + * \verbatim im._COPYRIGHT [in Lua 5] \endverbatim + * \verbatim im._VERSION [in Lua 5] \endverbatim + * \verbatim im._VERSION_DATE [in Lua 5] \endverbatim + * \verbatim im._VERSION_NUMBER [in Lua 5] \endverbatim + * \verbatim im._DESCRIPTION [in Lua 5] \endverbatim + * \verbatim im._NAME [in Lua 5] \endverbatim + * \par + * See \ref im_lib.h + * @{ + */ +#define IM_AUTHOR "Antonio Scuri" +#define IM_COPYRIGHT "Copyright (C) 1994-2008 Tecgraf, PUC-Rio." +#define IM_VERSION "3.4.0" +#define IM_VERSION_NUMBER 304000 +#define IM_VERSION_DATE "2008/10/14" +#define IM_DESCRIPTION "Image Representation, Storage, Capture and Processing" +#define IM_NAME "IM - An Imaging Toolkit" +/** @} */ + + +/** Returns the library current version. Returns the definition IM_VERSION. + * + * \verbatim im.Version() -> version: string [in Lua 5] \endverbatim + * \ingroup lib */ +const char* imVersion(void); + +/** Returns the library current version release date. Returns the definition IM_VERSION_DATE. + * + * \verbatim im.VersionDate() -> date: string [in Lua 5] \endverbatim + * \ingroup lib */ +const char* imVersionDate(void); + +/** Returns the library current version number. Returns the definition IM_VERSION_NUMBER. \n + * Can be compared in run time with IM_VERSION_NUMBER to compare compiled and linked versions of the library. + * + * \verbatim im.VersionNumber() -> version: number [in Lua 5] \endverbatim + * \ingroup lib */ +int imVersionNumber(void); + + +#if defined(__cplusplus) +} +#endif + + +/*! \mainpage IM + * <CENTER> + * <H3> Image Representation, Storage, Capture and Processing </H3> + * Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil \n + * http://www.tecgraf.puc-rio.br/im \n + * mailto:im@tecgraf.puc-rio.br + * </CENTER> + * + * \section over Overview + * \par + * IM is a toolkit for Digital Imaging. + * \par + * It provides support for image capture, several image file formats and many image processing operations. + * \par + * Image representation includes scientific data types (like IEEE floating point data) + * and attributes (or metadata like GeoTIFF and Exif tags). + * Animation, video and volumes are supported as image sequences, + * but there is no digital audio support. + * \par + * The main goal of the library is to provide a simple API and abstraction + * of images for scientific applications. + * \par + * The toolkit API is written in C. + * The core library source code is implemented in C++ and it is very portable, + * it can be compiled in Windows and UNIX with no modifications. + * New image processing operations can be implemented in C or in C++. + * \par + * IM is free software, can be used for public and commercial applications. + * \par + * This work was developed at Tecgraf/PUC-Rio + * by means of the partnership with PETROBRAS/CENPES. + * + * \section author Author + * \par + * Basic Software Group @ Tecgraf/PUC-Rio + * - Antonio Scuri scuri@tecgraf.puc-rio.br + * + * \section copyright Copyright Notice +\verbatim + +**************************************************************************** +Copyright (C) 1994-2008 Tecgraf, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************** +\endverbatim + */ + + +/** \defgroup imagerep Image Representation + * \par + * See \ref im.h + */ + + +/** \defgroup file Image Storage + * \par + * See \ref im.h + */ + + +/** \defgroup format File Formats + * \par + * See \ref im.h + * + * Internal Predefined File Formats: + * \li "BMP" - Windows Device Independent Bitmap + * \li "PCX" - ZSoft Picture + * \li "GIF" - Graphics Interchange Format + * \li "TIFF" - Tagged Image File Format + * \li "RAS" - Sun Raster File + * \li "SGI" - Silicon Graphics Image File Format + * \li "JPEG" - JPEG File Interchange Format + * \li "LED" - IUP image in LED + * \li "TGA" - Truevision Targa + * \li "RAW" - RAW File + * \li "PNM" - Netpbm Portable Image Map + * \li "ICO" - Windows Icon + * \li "PNG" - Portable Network Graphic Format + * + * Other Supported File Formats: + * \li "JP2" - JPEG-2000 JP2 File Format + * \li "AVI" - Windows Audio-Video Interleaved RIFF + * \li "WMV" - Windows Media Video Format + * + * Some Known Compressions: + * \li "NONE" - No Compression. + * \li "RLE" - Run Lenght Encoding. + * \li "LZW" - Lempel, Ziff and Welsh. + * \li "JPEG" - Join Photographics Experts Group. + * \li "DEFLATE" - LZ77 variation (ZIP) + * + * \ingroup file */ + + +/* Library Names Convention + * + * Global Functions and Types - "im[Object][Action]" using first capitals (imFileOpen) + * Local Functions and Types - "i[Object][Action]" using first capitals (iTIFFGetCompIndex) + * Local Static Variables - same as local functions and types (iFormatCount) + * Local Static Tables - same as local functions and types with "Table" suffix (iTIFFCompTable) + * Variables and Members - no prefix, all lower case (width) + * Defines and Enumerations - all capitals (IM_ERR_NONE) + * + */ + + +#endif diff --git a/include/im_math.h b/include/im_math.h new file mode 100644 index 0000000..8e9b3dd --- /dev/null +++ b/include/im_math.h @@ -0,0 +1,368 @@ +/** \file + * \brief Math Utilities + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_MATH_H +#define __IM_MATH_H + +#include <math.h> +#include "im_util.h" + +#ifdef IM_DEFMATHFLOAT +inline float acosf(float _X) {return ((float)acos((double)_X)); } +inline float asinf(float _X) {return ((float)asin((double)_X)); } +inline float atanf(float _X) {return ((float)atan((double)_X)); } +inline float atan2f(float _X, float _Y) {return ((float)atan2((double)_X, (double)_Y)); } +inline float ceilf(float _X) {return ((float)ceil((double)_X)); } +inline float cosf(float _X) {return ((float)cos((double)_X)); } +inline float coshf(float _X) {return ((float)cosh((double)_X)); } +inline float expf(float _X) {return ((float)exp((double)_X)); } +inline float fabsf(float _X) {return ((float)fabs((double)_X)); } +inline float floorf(float _X) {return ((float)floor((double)_X)); } +inline float fmodf(float _X, float _Y) {return ((float)fmod((double)_X, (double)_Y)); } +inline float logf(float _X) {return ((float)log((double)_X)); } +inline float log10f(float _X) {return ((float)log10((double)_X)); } +inline float powf(float _X, float _Y) {return ((float)pow((double)_X, (double)_Y)); } +inline float sinf(float _X) {return ((float)sin((double)_X)); } +inline float sinhf(float _X) {return ((float)sinh((double)_X)); } +inline float sqrtf(float _X) {return ((float)sqrt((double)_X)); } +inline float tanf(float _X) {return ((float)tan((double)_X)); } +inline float tanhf(float _X) {return ((float)tanh((double)_X)); } +#endif + +/** \defgroup math Math Utilities + * \par + * When converting between continuous and discrete use: \n + * Continuous = Discrete + 0.5 [Reconstruction/Interpolation] \n + * Discrete = Round(Continuous - 0.5) [Sampling/Quantization] \n + * \par + * Notice that must check 0-max limits when converting from Continuous to Discrete. + * \par + * When converting between discrete and discrete use: \n + * integer src_size, dst_len, src_i, dst_i \n + * real factor = (real)(dst_size)/(real)(src_size) \n + * dst_i = Round(factor*(src_i + 0.5) - 0.5) + * \par + * See \ref im_math.h + * \ingroup util */ + + +/** Round a real to the nearest integer. + * \ingroup math */ +inline int imRound(float x) +{ + return (int)(x < 0? x-0.5f: x+0.5f); +} +inline int imRound(double x) +{ + return (int)(x < 0? x-0.5: x+0.5); +} + +/** Converts between two discrete grids. + * factor is "dst_size/src_size". + * \ingroup math */ +inline int imResample(int x, float factor) +{ + float xr = factor*(x + 0.5f) - 0.5f; + return (int)(xr < 0? xr-0.5f: xr+0.5f); /* Round */ +} + +/** Does Zero Order Decimation (Mean). + * \ingroup math */ +template <class T, class TU> +inline T imZeroOrderDecimation(int width, int height, T *map, float xl, float yl, float box_width, float box_height, TU Dummy) +{ + int x0,x1,y0,y1; + (void)Dummy; + + x0 = (int)floor(xl - box_width/2.0 - 0.5) + 1; + y0 = (int)floor(yl - box_height/2.0 - 0.5) + 1; + x1 = (int)floor(xl + box_width/2.0 - 0.5); + y1 = (int)floor(yl + box_height/2.0 - 0.5); + + if (x0 == x1) x1++; + if (y0 == y1) y1++; + + x0 = x0<0? 0: x0>width-1? width-1: x0; + y0 = y0<0? 0: y0>height-1? height-1: y0; + x1 = x1<0? 0: x1>width-1? width-1: x1; + y1 = y1<0? 0: y1>height-1? height-1: y1; + + TU Value; + int Count = 0; + + Value = 0; + + for (int y = y0; y <= y1; y++) + { + for (int x = x0; x <= x1; x++) + { + Value += map[y*width+x]; + Count++; + } + } + + if (Count == 0) + { + Value = 0; + return (T)Value; + } + + return (T)(Value/(float)Count); +} + +/** Does Bilinear Decimation. + * \ingroup math */ +template <class T, class TU> +inline T imBilinearDecimation(int width, int height, T *map, float xl, float yl, float box_width, float box_height, TU Dummy) +{ + int x0,x1,y0,y1; + (void)Dummy; + + x0 = (int)floor(xl - box_width/2.0 - 0.5) + 1; + y0 = (int)floor(yl - box_height/2.0 - 0.5) + 1; + x1 = (int)floor(xl + box_width/2.0 - 0.5); + y1 = (int)floor(yl + box_height/2.0 - 0.5); + + if (x0 == x1) x1++; + if (y0 == y1) y1++; + + x0 = x0<0? 0: x0>width-1? width-1: x0; + y0 = y0<0? 0: y0>height-1? height-1: y0; + x1 = x1<0? 0: x1>width-1? width-1: x1; + y1 = y1<0? 0: y1>height-1? height-1: y1; + + TU Value, LineValue; + float LineNorm, Norm, dxr, dyr; + + Value = 0; + Norm = 0; + + for (int y = y0; y <= y1; y++) + { + dyr = yl - (y+0.5f); + if (dyr < 0) dyr *= -1; + + LineValue = 0; + LineNorm = 0; + + for (int x = x0; x <= x1; x++) + { + dxr = xl - (x+0.5f); + if (dxr < 0) dxr *= -1; + + LineValue += map[y*width+x] * dxr; + LineNorm += dxr; + } + + Value += LineValue * dyr; + Norm += dyr * LineNorm; + } + + if (Norm == 0) + { + Value = 0; + return (T)Value; + } + + return (T)(Value/Norm); +} + +/** Does Zero Order Interpolation (Nearest Neighborhood). + * \ingroup math */ +template <class T> +inline T imZeroOrderInterpolation(int width, int height, T *map, float xl, float yl) +{ + int x0 = imRound(xl-0.5f); + int y0 = imRound(yl-0.5f); + x0 = x0<0? 0: x0>width-1? width-1: x0; + y0 = y0<0? 0: y0>height-1? height-1: y0; + return map[y0*width + x0]; +} + +/** Does Bilinear Interpolation. + * \ingroup math */ +template <class T> +inline T imBilinearInterpolation(int width, int height, T *map, float xl, float yl) +{ + int x0, y0, x1, y1; + float t, u; + + if (xl < 0.5) + { + x1 = x0 = 0; + t = 0; + } + else if (xl > width-0.5) + { + x1 = x0 = width-1; + t = 0; + } + else + { + x0 = (int)(xl-0.5f); + x1 = x0+1; + t = xl - (x0+0.5f); + } + + if (yl < 0.5) + { + y1 = y0 = 0; + u = 0; + } + else if (yl > height-0.5) + { + y1 = y0 = height-1; + u = 0; + } + else + { + y0 = (int)(yl-0.5f); + y1 = y0+1; + u = yl - (y0+0.5f); + } + + T fll = map[y0*width + x0]; + T fhl = map[y0*width + x1]; + T flh = map[y1*width + x0]; + T fhh = map[y1*width + x1]; + + return (T)((fhh - flh - fhl + fll) * u * t + + (fhl - fll) * t + + (flh - fll) * u + + fll); +} + +/** Does Bicubic Interpolation. + * \ingroup math */ +template <class T, class TU> +inline T imBicubicInterpolation(int width, int height, T *map, float xl, float yl, TU Dummy) +{ + int X[4], Y[4]; + float t, u; + (void)Dummy; + + if (xl > width-0.5) + { + X[3] = X[2] = X[1] = width-1; + X[0] = X[1]-1; + t = 0; + } + else + { + X[1] = (int)(xl-0.5f); + if (X[1] < 0) X[1] = 0; + + X[0] = X[1]-1; + X[2] = X[1]+1; + X[3] = X[1]+2; + + if (X[0] < 0) X[0] = 0; + if (X[3] > width-1) X[3] = width-1; + + t = xl - (X[1]+0.5f); + } + + if (yl > height-0.5) + { + Y[3] = Y[2] = Y[1] = height-1; + Y[0] = Y[1]-1; + u = 0; + } + else + { + Y[1] = (int)(yl-0.5f); + if (Y[1] < 0) Y[1] = 0; + + Y[0] = Y[1]-1; + Y[2] = Y[1]+1; + Y[3] = Y[1]+2; + + if (Y[0] < 0) Y[0] = 0; + if (Y[3] > height-1) Y[3] = height-1; + + u = yl - (Y[1]+0.5f); + } + + float CX[4], CY[4]; + + // Optimize calculations + { + float c, c2, c3; + +#define C0 (-c3 + 2.0f*c2 - c) +#define C1 ( c3 - 2.0f*c2 + 1.0f) +#define C2 (-c3 + c2 + c) +#define C3 ( c3 - c2) + + c = t; + c2 = c*c; c3 = c2*c; + CX[0] = C0; CX[1] = C1; CX[2] = C2; CX[3] = C3; + + c = u; + c2 = c*c; c3 = c2*c; + CY[0] = C0; CY[1] = C1; CY[2] = C2; CY[3] = C3; + +#undef C0 +#undef C1 +#undef C2 +#undef C3 + } + + TU LineValue, Value; + float LineNorm, Norm; + + Value = 0; + Norm = 0; + + for (int y = 0; y < 4; y++) + { + LineValue = 0; + LineNorm = 0; + + for (int x = 0; x < 4; x++) + { + LineValue += map[Y[y]*width+X[x]] * CX[x]; + LineNorm += CX[x]; + } + + Value += LineValue * CY[y]; + Norm += CY[y] * LineNorm; + } + + if (Norm == 0) + { + Value = 0; + return (T)Value; + } + + Value = (Value/Norm); + + int size = sizeof(T); + if (size == 1) + return (T)(Value<=(TU)0? (TU)0: Value<=(TU)255? Value: (TU)255); + else + return (T)(Value); +} + +/** Calculates minimum and maximum values. + * \ingroup math */ +template <class T> +inline void imMinMax(const T *map, int count, T& min, T& max) +{ + min = *map++; + max = min; + for (int i = 1; i < count; i++) + { + T value = *map++; + + if (value > max) + max = value; + else if (value < min) + min = value; + } +} + +#endif diff --git a/include/im_math_op.h b/include/im_math_op.h new file mode 100644 index 0000000..f410c62 --- /dev/null +++ b/include/im_math_op.h @@ -0,0 +1,219 @@ +/** \file + * \brief Math Operations + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_MATH_OP_H +#define __IM_MATH_OP_H + +#include "im_complex.h" + +//#define IM_NEARZERO 0.0000001f +//#define IM_NEARINF 10000000 + +/// Crop value to Byte limit +template <class T> +inline T crop_byte(const T& v) +{ + return v <= 0? 0: v <= 255? v: 255; +} + +/// Generic Addition with 2 template types +template <class T1, class T2> +inline T1 add_op(const T1& v1, const T2& v2) +{ + return v2 + v1; +} + +/// Generic Subtraction with 2 template types +template <class T1, class T2> +inline T1 sub_op(const T1& v1, const T2& v2) +{ + return v2 - v1; +} + +/// Generic Multiplication with 2 template types +template <class T1, class T2> +inline T1 mul_op(const T1& v1, const T2& v2) +{ + return v2 * v1; +} + +/// Generic Division with 2 template types +template <class T1, class T2> +inline T1 div_op(const T1& v1, const T2& v2) +{ +// if (v2 == 0) return (T1)IM_NEARINF; + return v1 / v2; +} + +/// Generic Invert +template <class T> +inline T inv_op(const T& v) +{ +// if (v == 0) return (T)IM_NEARINF; + return 1/v; +} + +/// Generic Difference with 2 template types +template <class T1, class T2> +inline T1 diff_op(const T1& v1, const T2& v2) +{ + if (v1 <= v2) + return v2 - v1; + return v1 - v2; +} + +/// Generic Minimum with 2 template types +template <class T1, class T2> +inline T1 min_op(const T1& v1, const T2& v2) +{ + if (v1 <= v2) + return v1; + return v2; +} + +/// Generic Maximum with 2 template types +template <class T1, class T2> +inline T1 max_op(const T1& v1, const T2& v2) +{ + if (v1 <= v2) + return v2; + return v1; +} + +inline imbyte pow_op(const imbyte& v1, const imbyte& v2) +{ + return (imbyte)pow((float)v1, v2); +} + +inline imushort pow_op(const imushort& v1, const imushort& v2) +{ + return (imushort)pow((float)v1, v2); +} + +inline int pow_op(const int& v1, const int& v2) +{ + return (int)pow((float)v1, v2); +} + +/// Generic Power with 2 template types +template <class T1, class T2> +inline T1 pow_op(const T1& v1, const T2& v2) +{ + return (T1)pow(v1, v2); +} + +/// Generic Abssolute +template <class T> +inline T abs_op(const T& v) +{ + if (v <= 0) + return -1*v; + return v; +} + +/// Generic Less +template <class T> +inline T less_op(const T& v) +{ + return -1*v; +} + +/// Generic Square +template <class T> +inline T sqr_op(const T& v) +{ + return v*v; +} + +inline int sqrt(const int& C) +{ + return (int)sqrt(float(C)); +} + +/// Generic Square Root +template <class T> +inline T sqrt_op(const T& v) +{ + return (T)sqrt(v); +} + +inline int exp(const int& v) +{ + return (int)exp((float)v); +} + +/// Generic Exponential +template <class T> +inline T exp_op(const T& v) +{ + return (T)exp(v); +} + +inline int log(const int& v) +{ + return (int)log((float)v); +} + +/// Generic Logarithm +template <class T> +inline T log_op(const T& v) +{ +// if (v <= 0) return (T)IM_NEARINF; + return (T)log(v); +} + +// Dummy sin +inline imcfloat sin(const imcfloat& v) +{ + return (v); +} + +inline int sin(const int& v) +{ + return (int)sin((float)v); +} + +/// Generic Sine +template <class T> +inline T sin_op(const T& v) +{ + return (T)sin(v); +} + +inline int cos(const int& v) +{ + return (int)cos((float)v); +} + +// Dummy cos +inline imcfloat cos(const imcfloat& v) +{ + return (v); +} + +/// Generic Cosine +template <class T> +inline T cos_op(const T& v) +{ + return (T)cos(v); +} + +/// Sets a bit in an array +inline void imDataBitSet(imbyte* data, int index, int bit) +{ + if (bit) + data[index / 8] |= (0x01 << (7 - (index % 8))); + else + data[index / 8] &= ~(0x01 << (7 - (index % 8))); +} + +/// Gets a bit from an array +inline int imDataBitGet(imbyte* data, int index) +{ + return (data[index / 8] >> (7 - (index % 8))) & 0x01; +} + +#endif diff --git a/include/im_palette.h b/include/im_palette.h new file mode 100644 index 0000000..c7ed88c --- /dev/null +++ b/include/im_palette.h @@ -0,0 +1,172 @@ +/** \file + * \brief Palette Generators + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PALETTE_H +#define __IM_PALETTE_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup palette Palette Generators + * \par + * Creates several standard palettes. The palette is just an array of encoded color values. + * See also \ref colorutl. + * \par + * In Lua, to create a palette you can call im.PaletteCreate. + * \verbatim im.PaletteCreate([count: number]) -> pal: imPalette [in Lua 5] \endverbatim + * Default count is 256. + * IMLua and CDLua palettes are 100% compatible. The IM palette metatable name is "imPalette". \n + * When converted to a string will return "imPalete(%p)" where %p is replaced by the userdata address. + * If the palette is already destroyed by im.PaletteDestroy, then it will return also the suffix "-destroyed". + * \par + * In Lua, to destroy a palette you can call im.PaletteDestroy. + * If this function is not called, the palette is destroyed by the garbage collector. + * \verbatim im.PaletteDestroy(pal: imPalette) [in Lua 5] \endverbatim + * \par + * In Lua, array access is enabled so you can do:. + * \verbatim color = pal[index] \endverbatim + * \verbatim pal[index] = color \endverbatim + * \verbatim count = #pal \endverbatim + * \par + * See \ref im_palette.h + * \ingroup util */ + + +/** Searches for the nearest color on the table and returns the color index if successful. + * It looks in all palette entries and finds the minimum euclidian square distance. + * If the color matches the given color it returns immediately. + * See also \ref colorutl. + * + * \verbatim im.PaletteFindNearest(pal: imPalette, color: lightuserdata) -> index: number [in Lua 5] \endverbatim + * \ingroup palette */ +int imPaletteFindNearest(const long *palette, int palette_count, long color); + +/** Searches for the color on the table and returns the color index if successful. + * If the tolerance is 0 search for the exact match in the palette else search for the + * first color that fits in the tolerance range. + * See also \ref colorutl. + * + * \verbatim im.PaletteFindColor(pal: imPalette, color: lightuserdata, tol: number) -> index: number [in Lua 5] \endverbatim + * \ingroup palette */ +int imPaletteFindColor(const long *palette, int palette_count, long color, unsigned char tol); + +/** Creates a palette of gray scale values. + * The colors are arranged from black to white. + * + * \verbatim im.PaletteGray() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteGray(void); + +/** Creates a palette of a gradient of red colors. + * The colors are arranged from black to pure red. + * + * \verbatim im.PaletteRed() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteRed(void); + +/** Creates a palette of a gradient of green colors. + * The colors are arranged from black to pure green. + * + * \verbatim im.PaletteGreen() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteGreen(void); + +/** Creates a palette of a gradient of blue colors. + * The colors are arranged from black to pure blue. + * + * \verbatim im.PaletteBlue() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteBlue(void); + +/** Creates a palette of a gradient of yellow colors. + * The colors are arranged from black to pure yellow. + * + * \verbatim im.PaletteYellow() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteYellow(void); + +/** Creates a palette of a gradient of magenta colors. + * The colors are arranged from black to pure magenta. + * + * \verbatim im.PaletteMagenta() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteMagenta(void); + +/** Creates a palette of a gradient of cian colors. + * The colors are arranged from black to pure cian. + * + * \verbatim im.PaletteCian() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteCian(void); + +/** Creates a palette of rainbow colors. + * The colors are arranged in the light wave length spectrum order (starting from purple). + * + * \verbatim im.PaletteRainbow() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteRainbow(void); + +/** Creates a palette of hues with maximum saturation. + * + * \verbatim im.PaletteHues() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteHues(void); + +/** Creates a palette of a gradient of blue colors. + * The colors are arranged from pure blue to white. + * + * \verbatim im.PaletteBlueIce() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteBlueIce(void); + +/** Creates a palette of a gradient from black to white passing trough red and orange. + * + * \verbatim im.PaletteHotIron() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteHotIron(void); + +/** Creates a palette of a gradient from black to white passing trough red and yellow. + * + * \verbatim im.PaletteBlackBody() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteBlackBody(void); + +/** Creates a palette with high contrast colors. + * + * \verbatim im.PaletteHighContrast() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteHighContrast(void); + +/** Creates a palette of an uniform range of colors from black to white. + * This is a 2^(2.6) bits per pixel palette. + * + * \verbatim im.PaletteUniform() -> pal: imPalette [in Lua 5] \endverbatim + * \ingroup palette */ +long* imPaletteUniform(void); + +/** Returns the index of the correspondent RGB color of an uniform palette. + * + * \verbatim im.PaletteUniformIndex(color: lightuserdata) -> index: number [in Lua 5] \endverbatim + * \ingroup palette */ +int imPaletteUniformIndex(long color); + +/** Returns the index of the correspondent RGB color of an uniform palette. + * Uses an 8x8 ordered dither to lookup the index in a halftone matrix. + * The spatial position used by the halftone method. + * + * \verbatim im.PaletteUniformIndexHalftoned(color: lightuserdata, x: number, y: number) -> index: number [in Lua 5] \endverbatim + * \ingroup palette */ +int imPaletteUniformIndexHalftoned(long color, int x, int y); + + +#if defined(__cplusplus) +} +#endif + +#endif + diff --git a/include/im_plus.h b/include/im_plus.h new file mode 100644 index 0000000..0aabd1f --- /dev/null +++ b/include/im_plus.h @@ -0,0 +1,73 @@ +/** \file + * \brief C++ Wrapper for File Access + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PLUS_H +#define __IM_PLUS_H + + +/** \brief C++ Wrapper for the Image File Structure + * + * \par + * Usage is just like the C API. Open and New are replaced by equivalent constructors. \n + * Close is replaced by the destructor. Error checking is done by the Error() member. \n + * Open and New errors are cheked using the Failed() member. + * \ingroup file */ +class imImageFile +{ + imFile* ifile; + int error; + + imImageFile() {}; + +public: + + imImageFile(const char* file_name) + { this->ifile = imFileOpen(file_name, &this->error); } + + imImageFile(const char* file_name, const char* format) + { this->ifile = imFileNew(file_name, format, &this->error); } + + ~imImageFile() + { if (this->ifile) imFileClose(this->ifile); } + + int Failed() + { return this->ifile == 0; } + + int Error() + { return this->error; } + + void SetAttribute(const char* attrib, int data_type, int count, const void* data) + { imFileSetAttribute(this->ifile, attrib, data_type, count, data); } + + const void* GetAttribute(const char* attrib, int *data_type, int *count) + { return imFileGetAttribute(this->ifile, attrib, data_type, count); } + + void GetInfo(char* format, char* compression, int *image_count) + { imFileGetInfo(this->ifile, format, compression, image_count); } + + void ReadImageInfo(int index, int *width, int *height, int *color_mode, int *data_type) + { this->error = imFileReadImageInfo(this->ifile, index, width, height, color_mode, data_type); } + + void GetPalette(long* palette, int *palette_count) + { imFileGetPalette(this->ifile, palette, palette_count); } + + void ReadImageData(void* data, int convert2bitmap, int color_mode_flags) + { this->error = imFileReadImageData(this->ifile, data, convert2bitmap, color_mode_flags); } + + void SetInfo(const char* compression) + { imFileSetInfo(this->ifile, compression); } + + void SetPalette(long* palette, int palette_count) + { imFileSetPalette(this->ifile, palette, palette_count); } + + void WriteImageInfo(int width, int height, int color_mode, int data_type) + { this->error = imFileWriteImageInfo(this->ifile, width, height, color_mode, data_type); } + + void WriteImageData(void* data) + { this->error = imFileWriteImageData(this->ifile, data); } +}; + +#endif diff --git a/include/im_process.h b/include/im_process.h new file mode 100644 index 0000000..e0d3d6c --- /dev/null +++ b/include/im_process.h @@ -0,0 +1,35 @@ +/** \file + * \brief Image Processing + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROCESS_H +#define __IM_PROCESS_H + +#include "im_process_pon.h" +#include "im_process_loc.h" +#include "im_process_glo.h" +#include "im_process_ana.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup process Image Processing + * \par + * Several image processing functions based on the \ref imImage structure. + * \par + * You must link the application with "im_process.lib/.a/.so". \n + * Some complex operations use the \ref counter.\n + * There is no check on the input/output image properties, + * check each function documentation before using it. + */ + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_process_ana.h b/include/im_process_ana.h new file mode 100644 index 0000000..2458be3 --- /dev/null +++ b/include/im_process_ana.h @@ -0,0 +1,221 @@ +/** \file + * \brief Image Statistics and Analysis + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROC_ANA_H +#define __IM_PROC_ANA_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + + +/** \defgroup stats Image Statistics Calculations + * \par + * Operations to calculate some statistics over images. + * \par + * See \ref im_process_ana.h + * \ingroup process */ + +/** Calculates the RMS error between two images (Root Mean Square Error). + * + * \verbatim im.CalcRMSError(image1: imImage, image2: imImage) -> rms: number [in Lua 5] \endverbatim + * \ingroup stats */ +float imCalcRMSError(const imImage* image1, const imImage* image2); + +/** Calculates the SNR of an image and its noise (Signal Noise Ratio). + * + * \verbatim im.CalcSNR(src_image: imImage, noise_image: imImage) -> snr: number [in Lua 5] \endverbatim + * \ingroup stats */ +float imCalcSNR(const imImage* src_image, const imImage* noise_image); + +/** Count the number of different colors in an image. \n + * Image must be IM_BYTE, but all color spaces except IM_CMYK. + * + * \verbatim im.CalcCountColors(image: imImage) -> count: number [in Lua 5] \endverbatim + * \ingroup stats */ +unsigned long imCalcCountColors(const imImage* image); + +/** Calculates the histogram of a IM_BYTE data. \n + * Histogram is always 256 positions long. \n + * When cumulative is different from zero it calculates the cumulative histogram. + * + * \verbatim im.CalcHistogram(image: imImage, plane: number, cumulative: number) -> histo: table of numbers [in Lua 5] \endverbatim + * Where plane is the depth plane to calculate the histogram. \n + * The returned table is zero indexed. image can be IM_USHORT or IM_BYTE. + * \ingroup stats */ +void imCalcHistogram(const unsigned char* data, int count, unsigned long* histo, int cumulative); + +/** Calculates the histogram of a IM_USHORT data. \n + * Histogram is always 65535 positions long. \n + * When cumulative is different from zero it calculates the cumulative histogram. \n + * Use \ref imCalcHistogram in Lua. + * \ingroup stats */ +void imCalcUShortHistogram(const unsigned short* data, int count, unsigned long* histo, int cumulative); + +/** Calculates the gray histogram of an image. \n + * Image must be IM_BYTE/(IM_RGB, IM_GRAY, IM_BINARY or IM_MAP). \n + * If the image is IM_RGB then the histogram of the luma component is calculated. \n + * Histogram is always 256 positions long. \n + * When cumulative is different from zero it calculates the cumulative histogram. + * + * \verbatim im.CalcGrayHistogram(image: imImage, cumulative: number) -> histo: table of numbers [in Lua 5] \endverbatim + * \ingroup stats */ +void imCalcGrayHistogram(const imImage* image, unsigned long* histo, int cumulative); + +/** Numerical Statistics Structure + * \ingroup stats */ +typedef struct _imStats +{ + float max; /**< Maximum value */ + float min; /**< Minimum value */ + unsigned long positive; /**< Number of Positive Values */ + unsigned long negative; /**< Number of Negative Values */ + unsigned long zeros; /**< Number of Zeros */ + float mean; /**< Mean */ + float stddev; /**< Standard Deviation */ +} imStats; + +/** Calculates the statistics about the image data. \n + * There is one stats for each depth plane. For ex: stats[0]=red stats, stats[0]=green stats, ... \n + * Supports all data types except IM_CFLOAT. \n + * + * \verbatim im.CalcImageStatistics(image: imImage) -> stats: table [in Lua 5] \endverbatim + * Table contains the following fields: max, min, positive, negative, zeros, mean, stddev. + * The same as the \ref imStats structure. + * \ingroup stats */ +void imCalcImageStatistics(const imImage* image, imStats* stats); + +/** Calculates the statistics about the image histogram data.\n + * There is one stats for each depth plane. For ex: stats[0]=red stats, stats[0]=green stats, ... \n + * Only IM_BYTE images are supported. + * + * \verbatim im.CalcHistogramStatistics(image: imImage) -> stats: table [in Lua 5] \endverbatim + * \ingroup stats */ +void imCalcHistogramStatistics(const imImage* image, imStats* stats); + +/** Calculates some extra statistics about the image histogram data.\n + * There is one stats for each depth plane. \n + * Only IM_BYTE images are supported. \n + * mode will be -1 if more than one max is found. + * + * \verbatim im.CalcHistoImageStatistics(image: imImage) -> median: number, mode: number [in Lua 5] \endverbatim + * \ingroup stats */ +void imCalcHistoImageStatistics(const imImage* image, int* median, int* mode); + + + +/** \defgroup analyze Image Analysis + * \par + * See \ref im_process_ana.h + * \ingroup process */ + +/** Find white regions in binary image. \n + * Result is IM_GRAY/IM_USHORT type. Regions can be 4 connected or 8 connected. \n + * Returns the number of regions found. Background is marked as 0. \n + * Regions touching the border are considered only if touch_border=1. + * + * \verbatim im.AnalyzeFindRegions(src_image: imImage, dst_image: imImage, connect: number, touch_border: number) -> count: number [in Lua 5] \endverbatim + * \verbatim im.AnalyzeFindRegionsNew(image: imImage, connect: number, touch_border: number) -> count: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup analyze */ +int imAnalyzeFindRegions(const imImage* src_image, imImage* dst_image, int connect, int touch_border); + +/** Measure the actual area of all regions. Holes are not included. \n + * This is the number of pixels of each region. \n + * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * area has size the number of regions. + * + * \verbatim im.AnalyzeMeasureArea(image: imImage, [region_count: number]) -> area: table of numbers [in Lua 5] \endverbatim + * The returned table is zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasureArea(const imImage* image, int* area, int region_count); + +/** Measure the polygonal area limited by the perimeter line of all regions. Holes are not included. \n + * Notice that some regions may have polygonal area zero. \n + * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * perimarea has size the number of regions. + * + * \verbatim im.AnalyzeMeasurePerimArea(image: imImage, [region_count: number]) -> perimarea: table of numbers [in Lua 5] \endverbatim + * The returned table is zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasurePerimArea(const imImage* image, float* perimarea); + +/** Calculate the centroid position of all regions. Holes are not included. \n + * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * area, cx and cy have size the number of regions. If area is NULL will be internally calculated. + * + * \verbatim im.AnalyzeMeasureCentroid(image: imImage, [area: table of numbers], [region_count: number]) -> cx: table of numbers, cy: table of numbers [in Lua 5] \endverbatim + * The returned tables are zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasureCentroid(const imImage* image, const int* area, int region_count, float* cx, float* cy); + +/** Calculate the principal major axis slope of all regions. \n + * Source image is IM_GRAY/IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * data has size the number of regions. If area or centroid are NULL will be internally calculated. \n + * Principal (major and minor) axes are defined to be those axes that pass through the + * centroid, about which the moment of inertia of the region is, respectively maximal or minimal. + * + * \verbatim im.AnalyzeMeasurePrincipalAxis(image: imImage, [area: table of numbers], [cx: table of numbers], [cy: table of numbers], [region_count: number]) + -> major_slope: table of numbers, major_length: table of numbers, minor_slope: table of numbers, minor_length: table of numbers [in Lua 5] \endverbatim + * The returned tables are zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasurePrincipalAxis(const imImage* image, const int* area, const float* cx, const float* cy, + const int region_count, float* major_slope, float* major_length, + float* minor_slope, float* minor_length); + +/** Measure the number and area of holes of all regions. \n + * Source image is IM_USHORT type (the result of \ref imAnalyzeFindRegions). \n + * area and perim has size the number of regions, if some is NULL it will be not calculated. + * + * \verbatim im.AnalyzeMeasureHoles(image: imImage, connect: number, [region_count: number]) -> holes_count: number, area: table of numbers, perim: table of numbers [in Lua 5] \endverbatim + * The returned tables are zero indexed. + * \ingroup analyze */ +void imAnalyzeMeasureHoles(const imImage* image, int connect, int *holes_count, int* area, float* perim); + +/** Measure the total perimeter of all regions (external and internal). \n + * Source image is IM_GRAY/IM_USHORT type (the result of imAnalyzeFindRegions). \n + * It uses a half-pixel inter distance for 8 neighboors in a perimeter of a 4 connected region. \n + * This function can also be used to measure line lenght. \n + * perim has size the number of regions. + * + * \verbatim im.AnalyzeMeasurePerimeter(image: imImage) -> perim: table of numbers [in Lua 5] \endverbatim + * \ingroup analyze */ +void imAnalyzeMeasurePerimeter(const imImage* image, float* perim, int region_count); + +/** Isolates the perimeter line of gray integer images. Background is defined as being black (0). \n + * It just checks if at least one of the 4 connected neighboors is non zero. Image borders are extended with zeros. + * + * \verbatim im.ProcessPerimeterLine(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessPerimeterLineNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup analyze */ +void imProcessPerimeterLine(const imImage* src_image, imImage* dst_image); + +/** Eliminates regions that have size outside the given interval. \n + * Source and destiny are a binary images. Regions can be 4 connected or 8 connected. \n + * Can be done in-place. end_size can be zero to ignore big objects. + * + * \verbatim im.ProcessPrune(src_image: imImage, dst_image: imImage, connect: number, start_size: number, end_size: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessPruneNew(image: imImage, connect: number, start_size: number, end_size: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup analyze */ +void imProcessPrune(const imImage* src_image, imImage* dst_image, int connect, int start_size, int end_size); + +/** Fill holes inside white regions. \n + * Source and destiny are a binary images. Regions can be 4 connected or 8 connected. \n + * Can be done in-place. + * + * \verbatim im.ProcessFillHoles(src_image: imImage, dst_image: imImage, connect: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessFillHolesNew(image: imImage, connect: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup analyze */ +void imProcessFillHoles(const imImage* src_image, imImage* dst_image, int connect); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_process_glo.h b/include/im_process_glo.h new file mode 100644 index 0000000..fc6dba8 --- /dev/null +++ b/include/im_process_glo.h @@ -0,0 +1,170 @@ +/** \file + * \brief Image Processing - Global Operations + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROCESS_GLO_H +#define __IM_PROCESS_GLO_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + + +/** \defgroup transform Other Domain Transform Operations + * \par + * Hough, Distance. + * + * See \ref im_process_glo.h + * \ingroup process */ + +/** Hough Lines Transform. \n + * It will detect white lines in a black background. So the source image must be a IM_BINARY image + * with the white lines of interest enhanced. The better the threshold with the white lines the better + * the line detection. \n + * The destiny image must have IM_GRAY, IM_INT, hg_width=180, hg_height=2*rmax+1, + * where rmax is the image diagonal/2 (rmax = srqrt(width*width + height*height)). \n + * The hough transform defines "cos(theta) * X + sin(theta) * Y = rho" and the parameters are in the interval: \n + * theta = "0 .. 179", rho = "-hg_height/2 .. hg_height/2" .\n + * Where rho is the perpendicular distance from the center of the image and theta the angle with the normal. + * So do not confuse theta with the line angle, they are perpendicular. \n + * Returns zero if the counter aborted. \n + * Inspired from ideas in XITE, Copyright 1991, Blab, UiO \n + * http://www.ifi.uio.no/~blab/Software/Xite/ + * + * \verbatim im.ProcessHoughLines(src_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessHoughLinesNew(image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +int imProcessHoughLines(const imImage* src_image, imImage* dst_image); + +/** Draw detected hough lines. \n + * The source image must be IM_GRAY and IM_BYTE. The destiny image can be a clone of the source image or + * it can be the source image for in place processing. \n + * If the hough transform is not NULL, then the hough points are filtered to include only lines + * that are significally different from each other. \n + * The hough image is the hough transform image, but it is optional and can be NULL. + * If not NULL then it will be used to filter lines that are very similar. \n + * The hough points image is a hough transform image that was thresholded to a IM_BINARY image, + * usually using a Local Max threshold operation (see \ref imProcessLocalMaxThreshold). Again the better the threshold the better the results. \n + * The destiny image will be set to IM_MAP, and the detected lines will be drawn using a red color. \n + * Returns the number of detected lines. + * + * \verbatim im.ProcessHoughLinesDraw(src_image: imImage, hough: imImage, hough_points: imImage, dst_image: imImage) -> lines: number [in Lua 5] \endverbatim + * \verbatim im.ProcessHoughLinesDrawNew(image: imImage, hough: imImage, hough_points: imImage) -> lines: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +int imProcessHoughLinesDraw(const imImage* src_image, const imImage* hough, const imImage* hough_points, imImage* dst_image); + +/** Calculates the Cross Correlation in the frequency domain. \n + * CrossCorr(a,b) = IFFT(Conj(FFT(a))*FFT(b)) \n + * Images must be of the same size and only destiny image must be of type complex. + * + * \verbatim im.ProcessCrossCorrelation(src_image1: imImage, src_image2: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessCrossCorrelationNew(image1: imImage, image2: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +void imProcessCrossCorrelation(const imImage* src_image1, const imImage* src_image2, imImage* dst_image); + +/** Calculates the Auto Correlation in the frequency domain. \n + * Uses the cross correlation. + * Images must be of the same size and only destiny image must be of type complex. + * + * \verbatim im.ProcessAutoCorrelation(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessAutoCorrelationNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +void imProcessAutoCorrelation(const imImage* src_image, imImage* dst_image); + +/** Calculates the Distance Transform of a binary image + * using an aproximation of the euclidian distance.\n + * Each white pixel in the binary image is + * assigned a value equal to its distance from the nearest + * black pixel. \n + * Uses a two-pass algorithm incrementally calculating the distance. \n + * Source image must be IM_BINARY, destiny must be IM_FLOAT. + * + * \verbatim im.ProcessDistanceTransform(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessDistanceTransformNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +void imProcessDistanceTransform(const imImage* src_image, imImage* dst_image); + +/** Marks all the regional maximum of the distance transform. \n + * source is IMGRAY/IM_FLOAT destiny in IM_BINARY. \n + * We consider maximum all connected pixel values that have smaller pixel values around it. + * + * \verbatim im.ProcessRegionalMaximum(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessRegionalMaximumNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup transform */ +void imProcessRegionalMaximum(const imImage* src_image, imImage* dst_image); + + + +/** \defgroup fourier Fourier Transform Operations + * \par + * All Fourier transforms use FFTW library version 2.1.5. \n + * Although there are newer versions, we build binaries only to version 2 + * because it is small and as fast as newer versions. + * Source code to use FFTW version 3 is available. + * \par + * FFTW Copyright Matteo Frigo, Steven G. Johnson and the MIT. \n + * http://www.fftw.org \n + * See "fftw.h" + * \par + * Must link with "im_fftw" library. \n + * \par + * The FFTW lib has a GPL license. The license of the "im_fftw" library is automatically the GPL. + * So you cannot use it for commercial applications without contacting the authors. + * \par + * See \ref im_process_glo.h + * \ingroup process */ + +/** Forward FFT. \n + * The result has its lowest frequency at the center of the image. \n + * This is an unnormalized fft. \n + * Images must be of the same size. Destiny image must be of type complex. + * + * \verbatim im.ProcessFFT(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessFFTNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup fourier */ +void imProcessFFT(const imImage* src_image, imImage* dst_image); + +/** Inverse FFT. \n + * The image has its lowest frequency restored to the origin before the transform. \n + * The result is normalized by (width*height). \n + * Images must be of the same size and both must be of type complex. + * + * \verbatim im.ProcessIFFT(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessIFFTNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup fourier */ +void imProcessIFFT(const imImage* src_image, imImage* dst_image); + +/** Raw in-place FFT (forward or inverse). \n + * The lowest frequency can be centered after forward, or + * can be restored to the origin before inverse. \n + * The result can be normalized after the transform by sqrt(w*h) [1] or by (w*h) [2], + * or left unnormalized [0]. \n + * Images must be of the same size and both must be of type complex. + * + * \verbatim im.ProcessFFTraw(image: imImage, inverse: number, center: number, normalize: number) [in Lua 5] \endverbatim + * \ingroup fourier */ +void imProcessFFTraw(imImage* image, int inverse, int center, int normalize); + +/** Auxiliary function for the raw FFT. \n + * This is the function used internally to change the lowest frequency position in the image. \n + * If the image size has even dimensions the flag "center2origin" is useless. But if it is odd, + * you must specify if its from center to origin (usually used before inverse) or + * from origin to center (usually used after forward). \n + * Notice that this function is used for images in the the frequency domain. \n + * Image type must be complex. + * + * \verbatim im.ProcessSwapQuadrants(image: imImage, center2origin: number) [in Lua 5] \endverbatim + * \ingroup fourier */ +void imProcessSwapQuadrants(imImage* image, int center2origin); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_process_loc.h b/include/im_process_loc.h new file mode 100644 index 0000000..9c0531b --- /dev/null +++ b/include/im_process_loc.h @@ -0,0 +1,577 @@ +/** \file + * \brief Image Processing - Local Operations + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROCESS_LOC_H +#define __IM_PROCESS_LOC_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + + +/** \defgroup resize Image Resize + * \par + * Operations to change the image size. + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Only reduze the image size using the given decimation order. \n + * Supported decimation orders: + * \li 0 - zero order (mean) + * \li 1 - first order (bilinear decimation) + * Images must be of the same type. If image type is IM_MAP or IM_BINARY, must use order=0. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessReduce(src_image: imImage, dst_image: imImage, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessReduceNew(image: imImage, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +int imProcessReduce(const imImage* src_image, imImage* dst_image, int order); + +/** Change the image size using the given interpolation order. \n + * Supported interpolation orders: + * \li 0 - zero order (near neighborhood) + * \li 1 - first order (bilinear interpolation) + * \li 3 - third order (bicubic interpolation) + * Images must be of the same type. If image type is IM_MAP or IM_BINARY, must use order=0. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessResize(src_image: imImage, dst_image: imImage, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessResizeNew(image: imImage, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +int imProcessResize(const imImage* src_image, imImage* dst_image, int order); + +/** Reduze the image area by 4 (w/2,h/2). \n + * Images must be of the same type. Destiny image size must be source image width/2, height/2. + * Can not operate on IM_MAP nor IM_BINARY images. + * + * \verbatim im.ProcessReduceBy4(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessReduceBy4New(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +void imProcessReduceBy4(const imImage* src_image, imImage* dst_image); + +/** Extract a rectangular region from an image. \n + * Images must be of the same type. Destiny image size must be smaller than source image width-xmin, height-ymin. \n + * ymin and xmin must be >0 and <size. + * + * \verbatim im.ProcessCrop(src_image: imImage, dst_image: imImage, xmin: number, ymin: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessCropNew(image: imImage, xmin: number, xmax: number, ymin: number, ymax: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +void imProcessCrop(const imImage* src_image, imImage* dst_image, int xmin, int ymin); + +/** Insert a rectangular region in an image. \n + * Images must be of the same type. Region image size can be larger than source image. \n + * ymin and xmin must be >0 and <size. \n + * Source and destiny must be of the same size. Can be done in place. + * + * \verbatim im.ProcessInsert(src_image: imImage, region_image: imImage, dst_image: imImage, xmin: number, ymin: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessInsertNew(image: imImage, region_image: imImage, xmin: number, ymin: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +void imProcessInsert(const imImage* src_image, const imImage* region_image, imImage* dst_image, int xmin, int ymin); + +/** Increase the image size by adding pixels with zero value. \n + * Images must be of the same type. Destiny image size must be greatter than source image width+xmin, height+ymin. + * + * \verbatim im.ProcessAddMargins(src_image: imImage, dst_image: imImage, xmin: number, ymin: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessAddMarginsNew(image: imImage, xmin: number, xmax: number, ymin: number, ymax: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup resize */ +void imProcessAddMargins(const imImage* src_image, imImage* dst_image, int xmin, int ymin); + + + +/** \defgroup geom Geometric Operations + * \par + * Operations to change the shape of the image. + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Calculates the size of the new image after rotation. + * + * \verbatim im.ProcessCalcRotateSize(width: number, height: number, cos0: number, sin0: number) [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessCalcRotateSize(int width, int height, int *new_width, int *new_height, double cos0, double sin0); + +/** Rotates the image using the given interpolation order (see \ref imProcessResize). \n + * Images must be of the same type. The destiny size can be calculated using \ref imProcessCalcRotateSize to fit the new image size, + * or can be any size, including the original size. The rotation is relative to the center of the image. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRotate(src_image: imImage, dst_image: imImage, cos0: number, sin0: number, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRotateNew(image: imImage, cos0: number, sin0: number, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +int imProcessRotate(const imImage* src_image, imImage* dst_image, double cos0, double sin0, int order); + +/** Rotates the image using the given interpolation order (see \ref imProcessResize). \n + * Images must be of the same type. Destiny can have any size, including the original size. \n + * The rotation is relative to the reference point. But the result can be shifted to the origin. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRotateRef(src_image: imImage, dst_image: imImage, cos0: number, sin0: number, x: number, y: number, to_origin: boolean, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRotateRefNew(image: imImage, cos0: number, sin0: number, x: number, y: number, to_origin: boolean, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +int imProcessRotateRef(const imImage* src_image, imImage* dst_image, double cos0, double sin0, int x, int y, int to_origin, int order); + +/** Rotates the image in 90 degrees counterclockwise or clockwise. Swap columns by lines. \n + * Images must be of the same type. Destiny width and height must be source height and width. \n + * Direction can be clockwise (1) or counter clockwise (-1). + * + * \verbatim im.ProcessRotate90(src_image: imImage, dst_image: imImage, dir_clockwise: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessRotate90New(image: imImage, dir_clockwise: boolean) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessRotate90(const imImage* src_image, imImage* dst_image, int dir_clockwise); + +/** Rotates the image in 180 degrees. Swap columns and swap lines. \n + * Images must be of the same type and size. + * + * \verbatim im.ProcessRotate180(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessRotate180New(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessRotate180(const imImage* src_image, imImage* dst_image); + +/** Mirror the image in a horizontal flip. Swap columns. \n + * Images must be of the same type and size. + * Can be done in-place. + * + * \verbatim im.ProcessMirror(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMirrorNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessMirror(const imImage* src_image, imImage* dst_image); + +/** Apply a vertical flip. Swap lines. \n + * Images must be of the same type and size. + * Can be done in-place. + * + * \verbatim im.ProcessFlip(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessFlipNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessFlip(const imImage* src_image, imImage* dst_image); + +/** Apply a radial distortion using the given interpolation order (see imProcessResize). \n + * Images must be of the same type and size. Returns zero if the counter aborted. + * + * \verbatim im.ProcessRadial(src_image: imImage, dst_image: imImage, k1: number, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRadialNew(image: imImage, k1: number, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +int imProcessRadial(const imImage* src_image, imImage* dst_image, float k1, int order); + +/** Apply a swirl distortion using the given interpolation order (see imProcessResize). \n + * Images must be of the same type and size. Returns zero if the counter aborted. + * + * \verbatim im.ProcessSwirl(src_image: imImage, dst_image: imImage, k: number, order: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessSwirlNew(image: imImage, k: number, order: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +int imProcessSwirl(const imImage* src_image, imImage* dst_image, float k1, int order); + +/** Split the image in two images, one containing the odd lines and other containing the even lines. \n + * Images must be of the same type. Height of the output images must be half the height of the input image. + * If the height of the input image is odd then the first image must have height equals to half+1. + * + * \verbatim im.ProcessInterlaceSplit(src_image: imImage, dst_image1: imImage, dst_image2: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessInterlaceSplitNew(image: imImage) -> new_image1: imImage, new_image2: imImage [in Lua 5] \endverbatim + * \ingroup geom */ +void imProcessInterlaceSplit(const imImage* src_image, imImage* dst_image1, imImage* dst_image2); + + + +/** \defgroup morphgray Morphology Operations for Gray Images + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Base gray morphology convolution. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. \n + * Kernel is always IM_INT. Use kernel size odd for better results. \n + * Use -1 for don't care positions in kernel. Kernel values are added to image values, then \n + * you can use the maximum or the minimum within the kernel area. \n + * No border extensions are used. + * All the gray morphology operations use this function. \n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessGrayMorphConvolve(src_image: imImage, dst_image: imImage, kernel: imImage, ismax: boolean) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphConvolveNew(image: imImage, kernel: imImage, ismax: boolean) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage* kernel, int ismax); + +/** Gray morphology convolution with a kernel full of "0"s and use minimum value. + * + * \verbatim im.ProcessGrayMorphErode(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphErodeNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Gray morphology convolution with a kernel full of "0"s and use maximum value. + * + * \verbatim im.ProcessGrayMorphDilate(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphDilateNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Erode+Dilate. + * + * \verbatim im.ProcessGrayMorphOpen(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphOpenNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Dilate+Erode. + * + * \verbatim im.ProcessGrayMorphClose(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphCloseNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Open+Difference. + * + * \verbatim im.ProcessGrayMorphTopHat(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphTopHatNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphTopHat(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Close+Difference. + * + * \verbatim im.ProcessGrayMorphWell(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphWellNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphWell(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Difference(Erode, Dilate). + * + * \verbatim im.ProcessGrayMorphGradient(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGrayMorphGradientNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphgray */ +int imProcessGrayMorphGradient(const imImage* src_image, imImage* dst_image, int kernel_size); + + + +/** \defgroup morphbin Morphology Operations for Binary Images + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Base binary morphology convolution. \n + * Images are all IM_BINARY. Kernel is IM_INT, but values can be only 1, 0 or -1. Use kernel size odd for better results. \n + * Hit white means hit=1 and miss=0, or else hit=0 and miss=1. \n + * Use -1 for don't care positions in kernel. Kernel values are simply compared with image values. \n + * The operation can be repeated by a number of iterations. + * The border is zero extended. \n + * Almost all the binary morphology operations use this function.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessBinMorphConvolve(src_image: imImage, dst_image: imImage, kernel: imImage, hit_white: boolean, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphConvolveNew(image: imImage, kernel: imImage, hit_white: boolean, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphConvolve(const imImage* src_image, imImage* dst_image, const imImage* kernel, int hit_white, int iter); + +/** Binary morphology convolution with a kernel full of "1"s and hit white. + * + * \verbatim im.ProcessBinMorphErode(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphErodeNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphErode(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Binary morphology convolution with a kernel full of "0"s and hit black. + * + * \verbatim im.ProcessBinMorphDilate(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphDilateNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphDilate(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Erode+Dilate. + * When iteration is more than one it means Erode+Erode+Erode+...+Dilate+Dilate+Dilate+... + * + * \verbatim im.ProcessBinMorphOpen(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphOpenNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphOpen(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Dilate+Erode. + * + * \verbatim im.ProcessBinMorphClose(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphCloseNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphClose(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Erode+Difference. \n + * The difference from the source image is applied only once. + * + * \verbatim im.ProcessBinMorphOutline(src_image: imImage, dst_image: imImage, kernel_size: number, iter: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphOutlineNew(image: imImage, kernel_size: number, iter: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +int imProcessBinMorphOutline(const imImage* src_image, imImage* dst_image, int kernel_size, int iter); + +/** Thins the supplied binary image using Rosenfeld's parallel thinning algorithm. \n + * Reference: \n + * "Efficient Binary Image Thinning using Neighborhood Maps" \n + * by Joseph M. Cychosz, 3ksnn64@ecn.purdue.edu \n + * in "Graphics Gems IV", Academic Press, 1994 + * + * \verbatim im.ProcessBinMorphThin(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessBinMorphThinNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup morphbin */ +void imProcessBinMorphThin(const imImage* src_image, imImage* dst_image); + + + +/** \defgroup rank Rank Convolution Operations + * \par + * All the rank convolution use the same base function. Near the border the base function + * includes only the real image pixels in the rank. No border extensions are used. + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Rank convolution using the median value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessMedianConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessMedianConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessMedianConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Rank convolution using (maximum-minimum) value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessRangeConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRangeConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessRangeConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Rank convolution using the closest maximum or minimum value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessRankClosestConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRankClosestConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessRankClosestConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Rank convolution using the maximum value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessRankMaxConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRankMaxConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessRankMaxConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Rank convolution using the minimum value. \n + * Returns zero if the counter aborted. \n + * Supports all data types except IM_CFLOAT. Can be applied on color images. + * + * \verbatim im.ProcessRankMinConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRankMinConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup rank */ +int imProcessRankMinConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Threshold using a rank convolution with a range contrast function. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. \n + * Local variable threshold by the method of Bernsen. \n + * Extracted from XITE, Copyright 1991, Blab, UiO \n + * http://www.ifi.uio.no/~blab/Software/Xite/ +\verbatim + Reference: + Bernsen, J: "Dynamic thresholding of grey-level images" + Proc. of the 8th ICPR, Paris, Oct 1986, 1251-1255. + Author: Oivind Due Trier +\endverbatim + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRangeContrastThreshold(src_image: imImage, dst_image: imImage, kernel_size: number, min_range: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRangeContrastThresholdNew(image: imImage, kernel_size: number, min_range: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessRangeContrastThreshold(const imImage* src_image, imImage* dst_image, int kernel_size, int min_range); + +/** Threshold using a rank convolution with a local max function. \n + * Returns zero if the counter aborted. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. + * + * \verbatim im.ProcessLocalMaxThreshold(src_image: imImage, dst_image: imImage, kernel_size: number, min_level: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessLocalMaxThresholdNew(image: imImage, kernel_size: number, min_level: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessLocalMaxThreshold(const imImage* src_image, imImage* dst_image, int kernel_size, int min_level); + + + +/** \defgroup convolve Convolution Operations + * \par + * See \ref im_process_loc.h + * \ingroup process */ + +/** Base Convolution with a kernel. \n + * Kernel can be IM_INT or IM_FLOAT, but always IM_GRAY. Use kernel size odd for better results. \n + * Supports all data types. The border is mirrored. \n + * Returns zero if the counter aborted. Most of the convolutions use this function.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessConvolve(src_image: imImage, dst_image: imImage, kernel: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessConvolveNew(image: imImage, kernel: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessConvolve(const imImage* src_image, imImage* dst_image, const imImage* kernel); + +/** Base convolution when the kernel is separable. Only the first line and the first column will be used. \n + * Returns zero if the counter aborted.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessConvolveSep(src_image: imImage, dst_image: imImage, kernel: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessConvolveSepNew(image: imImage, kernel: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessConvolveSep(const imImage* src_image, imImage* dst_image, const imImage* kernel); + +/** Base Convolution with two kernels. The result is the magnitude of the result of each convolution. \n + * Kernel can be IM_INT or IM_FLOAT, but always IM_GRAY. Use kernel size odd for better results. \n + * Supports all data types. The border is mirrored. \n + * Returns zero if the counter aborted. Most of the convolutions use this function.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessConvolveDual(src_image: imImage, dst_image: imImage, kernel1, kernel2: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessConvolveDualNew(image: imImage, kernel1, kernel2: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessConvolveDual(const imImage* src_image, imImage* dst_image, const imImage *kernel1, const imImage *kernel2); + +/** Repeats the convolution a number of times. \n + * Returns zero if the counter aborted.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessConvolveRep(src_image: imImage, dst_image: imImage, kernel: imImage, count: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessConvolveRepNew(image: imImage, kernel: imImage, count: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessConvolveRep(const imImage* src_image, imImage* dst_image, const imImage* kernel, int count); + +/** Convolve with a kernel rotating it 8 times and getting the absolute maximum value. \n + * Kernel must be square. \n + * The rotation is implemented only for kernel sizes 3x3, 5x5 and 7x7. \n + * Supports all data types except IM_CFLOAT. + * Returns zero if the counter aborted.\n + * If the kernel image attribute "Description" exists it is used by the counter. + * + * \verbatim im.ProcessCompassConvolve(src_image: imImage, dst_image: imImage, kernel: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessCompassConvolveNew(image: imImage, kernel: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessCompassConvolve(const imImage* src_image, imImage* dst_image, imImage* kernel); + +/** Utility function to rotate a kernel one time. + * + * \verbatim im.ProcessRotateKernel(kernel: imImage) [in Lua 5] \endverbatim + * \ingroup convolve */ +void imProcessRotateKernel(imImage* kernel); + +/** Difference(Gaussian1, Gaussian2). \n + * Supports all data types, + * but if source is IM_BYTE or IM_USHORT destiny image must be of type IM_INT. + * + * \verbatim im.ProcessDiffOfGaussianConvolve(src_image: imImage, dst_image: imImage, stddev1: number, stddev2: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessDiffOfGaussianConvolveNew(image: imImage, stddev1: number, stddev2: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessDiffOfGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev1, float stddev2); + +/** Convolution with a laplacian of a gaussian kernel. \n + * Supports all data types, + * but if source is IM_BYTE or IM_USHORT destiny image must be of type IM_INT. + * + * \verbatim im.ProcessLapOfGaussianConvolve(src_image: imImage, dst_image: imImage, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessLapOfGaussianConvolveNew(image: imImage, stddev: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessLapOfGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev); + +/** Convolution with a kernel full of "1"s inside a circle. \n + * Supports all data types. + * + * \verbatim im.ProcessMeanConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessMeanConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessMeanConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Convolution with a float gaussian kernel. \n + * If sdtdev is negative its magnitude will be used as the kernel size. \n + * Supports all data types. + * + * \verbatim im.ProcessGaussianConvolve(src_image: imImage, dst_image: imImage, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessGaussianConvolveNew(image: imImage, stddev: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessGaussianConvolve(const imImage* src_image, imImage* dst_image, float stddev); + +/** Convolution with a barlett kernel. \n + * Supports all data types. + * + * \verbatim im.ProcessBarlettConvolve(src_image: imImage, dst_image: imImage, kernel_size: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessBarlettConvolveNew(image: imImage, kernel_size: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessBarlettConvolve(const imImage* src_image, imImage* dst_image, int kernel_size); + +/** Magnitude of the sobel convolution. \n + * Supports all data types. + * + * \verbatim im.ProcessSobelConvolve(src_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessSobelConvolveNew(image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessSobelConvolve(const imImage* src_image, imImage* dst_image); + +/** Magnitude of the prewitt convolution. \n + * Supports all data types. + * + * \verbatim im.ProcessPrewittConvolve(src_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessPrewittConvolveNew(image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessPrewittConvolve(const imImage* src_image, imImage* dst_image); + +/** Spline edge dectection. \n + * Supports all data types. + * + * \verbatim im.ProcessSplineEdgeConvolve(src_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessSplineEdgeConvolveNew(image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +int imProcessSplineEdgeConvolve(const imImage* src_image, imImage* dst_image); + +/** Finds the zero crossings of IM_INT and IM_FLOAT images. Crossings are marked with non zero values + * indicating the intensity of the edge. It is usually used after a second derivative, laplace. \n + * Extracted from XITE, Copyright 1991, Blab, UiO \n + * http://www.ifi.uio.no/~blab/Software/Xite/ + * + * \verbatim im.ProcessZeroCrossing(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessZeroCrossingNew(image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +void imProcessZeroCrossing(const imImage* src_image, imImage* dst_image); + +/** First part of the Canny edge detector. Includes the gaussian filtering and the nonmax suppression. \n + * After using this you could apply a Hysteresis Threshold, see \ref imProcessHysteresisThreshold. \n + * Image must be IM_BYTE/IM_GRAY. \n + * Implementation from the book: + \verbatim + J. R. Parker + "Algoritms for Image Processing and Computer Vision" + WILEY + \endverbatim + * + * \verbatim im.ProcessCanny(src_image: imImage, dst_image: imImage, stddev: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessCannyNew(image: imImage, stddev: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup convolve */ +void imProcessCanny(const imImage* src_image, imImage* dst_image, float stddev); + +/** Calculates the kernel size given the standard deviation. \n + * If sdtdev is negative its magnitude will be used as the kernel size. + * + * \verbatim im.GaussianStdDev2KernelSize(stddev: number) -> kernel_size: number [in Lua 5] \endverbatim + * \ingroup convolve */ +int imGaussianStdDev2KernelSize(float stddev); + +/** Calculates the standard deviation given the kernel size. + * + * \verbatim im.GaussianKernelSize2StdDev(kernel_size: number) -> stddev: number [in Lua 5] \endverbatim + * \ingroup convolve */ +float imGaussianKernelSize2StdDev(int kernel_size); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_process_pon.h b/include/im_process_pon.h new file mode 100644 index 0000000..cfed5ae --- /dev/null +++ b/include/im_process_pon.h @@ -0,0 +1,712 @@ +/** \file + * \brief Image Processing - Pontual Operations + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_PROCESS_PON_H +#define __IM_PROCESS_PON_H + +#include "im_image.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + + +/** \defgroup arithm Arithmetic Operations + * \par + * Simple math operations for images. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Unary Arithmetic Operations. + * Inverse and log may lead to math exceptions. + * \ingroup arithm */ +enum imUnaryOp { + IM_UN_EQL, /**< equal = a */ + IM_UN_ABS, /**< abssolute = |a| */ + IM_UN_LESS, /**< less = -a */ + IM_UN_INC, /**< increment += a */ + IM_UN_INV, /**< invert = 1/a (#) */ + IM_UN_SQR, /**< square = a*a */ + IM_UN_SQRT, /**< square root = a^(1/2) */ + IM_UN_LOG, /**< natural logarithm = ln(a) (#) */ + IM_UN_EXP, /**< exponential = exp(a) */ + IM_UN_SIN, /**< sine = sin(a) */ + IM_UN_COS, /**< cosine = cos(a) */ + IM_UN_CONJ, /**< complex conjugate = ar - ai*i */ + IM_UN_CPXNORM /**< complex normalization by magnitude = a / cpxmag(a) */ +}; + +/** Apply an arithmetic unary operation. \n + * Can be done in place, images must match size, does not need to match type. + * + * \verbatim im.ProcessUnArithmeticOp(src_image: imImage, dst_image: imImage, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessUnArithmeticOpNew(image: imImage, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessUnArithmeticOp(const imImage* src_image, imImage* dst_image, int op); + +/** Binary Arithmetic Operations. + * Inverse and log may lead to math exceptions. + * \ingroup arithm */ +enum imBinaryOp { + IM_BIN_ADD, /**< add = a+b */ + IM_BIN_SUB, /**< subtract = a-b */ + IM_BIN_MUL, /**< multiply = a*b */ + IM_BIN_DIV, /**< divide = a/b (#) */ + IM_BIN_DIFF, /**< difference = |a-b| */ + IM_BIN_POW, /**< power = a^b */ + IM_BIN_MIN, /**< minimum = (a < b)? a: b */ + IM_BIN_MAX /**< maximum = (a > b)? a: b */ +}; + +/** Apply a binary arithmetic operation. \n + * Can be done in place, images must match size. \n + * Source images must match type, destiny image can be several types depending on source: \n + * \li byte -> byte, ushort, int, float + * \li ushort -> ushort, int, float + * \li int -> int, float + * \li float -> float + * \li complex -> complex + * One exception is that you can combine complex with float resulting complex. + * + * \verbatim im.ProcessArithmeticOp(src_image1: imImage, src_image2: imImage, dst_image: imImage, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessArithmeticOpNew(image1: imImage, image2: imImage, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * The New function will create a new image of the same type of the source images. + * \ingroup arithm */ +void imProcessArithmeticOp(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int op); + +/** Apply a binary arithmetic operation with a constant value. \n + * Can be done in place, images must match size. \n + * Destiny image can be several types depending on source: \n + * \li byte -> byte, ushort, int, float + * \li ushort -> byte, ushort, int, float + * \li int -> byte, ushort, int, float + * \li float -> float + * \li complex -> complex + * The constant value is type casted to an apropriate type before the operation. + * + * \verbatim im.ProcessArithmeticConstOp(src_image: imImage, src_const: number, dst_image: imImage, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessArithmeticConstOpNew(image: imImage, src_const: number, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessArithmeticConstOp(const imImage* src_image, float src_const, imImage* dst_image, int op); + +/** Blend two images using an alpha value = [a * alpha + b * (1 - alpha)]. \n + * Can be done in place, images must match size and type. \n + * alpha value must be in the interval [0.0 - 1.0]. + * + * \verbatim im.ProcessBlendConst(src_image1: imImage, src_image2: imImage, dst_image: imImage, alpha: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessBlendConstNew(image1: imImage, image2: imImage, alpha: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessBlendConst(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, float alpha); + +/** Blend two images using an alpha channel = [a * alpha + b * (1 - alpha)]. \n + * Can be done in place, images must match size and type. \n + * alpha_image must have the same data type except for complex images that must be float, and color_space must be IM_GRAY. + * integer alpha values must be: +\verbatim +0 - 255 IM_BYTE +0 - 65535 IM_USHORT +0 - 2147483647 IM_INT +\endverbatim + * that will be normalized to 0 - 1. + * \verbatim im.ProcessBlend(src_image1: imImage, src_image2: imImage, alpha_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessBlendNew(image1: imImage, image2: imImage, alpha_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessBlend(const imImage* src_image1, const imImage* src_image2, const imImage* alpha_image, imImage* dst_image); + +/** Split a complex image into two images with real and imaginary parts \n + * or magnitude and phase parts (polar). \n + * Source image must be IM_CFLOAT, destiny images must be IM_FLOAT. + * + * \verbatim im.ProcessSplitComplex(src_image: imImage, dst_image1: imImage, dst_image2: imImage, do_polar: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessSplitComplexNew(image: imImage, do_polar: boolean) -> dst_image1: imImage, dst_image2: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessSplitComplex(const imImage* src_image, imImage* dst_image1, imImage* dst_image2, int do_polar); + +/** Merges two images as the real and imaginary parts of a complex image, \n + * or as magnitude and phase parts (polar = 1). \n + * Source images must be IM_FLOAT, destiny image must be IM_CFLOAT. + * + * \verbatim im.ProcessMergeComplex(src_image1: imImage, src_image2: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMergeComplexNew(image1: imImage, image2: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessMergeComplex(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int polar); + +/** Calculates the mean of multiple images. \n + * Images must match size and type. + * + * \verbatim im.ProcessMultipleMean(src_image_list: table of imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMultipleMeanNew(src_image_list: table of imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessMultipleMean(const imImage** src_image_list, int src_image_count, imImage* dst_image); + +/** Calculates the standard deviation of multiple images. \n + * Images must match size and type. Use \ref imProcessMultipleMean to calculate the mean_image. + * + * \verbatim im.ProcessMultipleStdDev(src_image_list: table of imImage, mean_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMultipleStdDevNew(src_image_list: table of imImage, mean_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessMultipleStdDev(const imImage** src_image_list, int src_image_count, const imImage *mean_image, imImage* dst_image); + +/** Calculates the auto-covariance of an image with the mean of a set of images. \n + * Images must match size and type. Returns zero if the counter aborted. \n + * Destiny is IM_FLOAT. + * + * \verbatim im.ProcessAutoCovariance(src_image: imImage, mean_image: imImage, dst_image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessAutoCovarianceNew(src_image: imImage, mean_image: imImage) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +int imProcessAutoCovariance(const imImage* src_image, const imImage* mean_image, imImage* dst_image); + +/** Multiplies the conjugate of one complex image with another complex image. \n + * Images must match size. Conj(img1) * img2 \n + * Can be done in-place. + * + * \verbatim im.ProcessMultiplyConj(src_image1: imImage, src_image2: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMultiplyConjNew(src_image1: imImage, src_image2: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup arithm */ +void imProcessMultiplyConj(const imImage* src_image1, const imImage* src_image2, imImage* dst_image); + + + +/** \defgroup quantize Additional Image Quantization Operations + * \par + * Additionally operations to the \ref imConvertColorSpace function. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Converts a RGB image to a MAP image using uniform quantization + * with an optional 8x8 ordered dither. The RGB image must have data type IM_BYTE. + * + * \verbatim im.ProcessQuantizeRGBUniform(src_image: imImage, dst_image: imImage, do_dither: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessQuantizeRGBUniformNew(src_image: imImage, do_dither: boolean) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup quantize */ +void imProcessQuantizeRGBUniform(const imImage* src_image, imImage* dst_image, int do_dither); + +/** Quantizes a gray scale image in less that 256 grays using uniform quantization. \n + * Both images must be IM_BYTE/IM_GRAY. Can be done in place. + * + * \verbatim im.ProcessQuantizeGrayUniform(src_image: imImage, dst_image: imImage, grays: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessQuantizeGrayUniformNew(src_image: imImage, grays: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup quantize */ +void imProcessQuantizeGrayUniform(const imImage* src_image, imImage* dst_image, int grays); + + + +/** \defgroup histo Histogram Based Operations + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Performs an histogram expansion based on a percentage of the number of pixels. \n + * Percentage defines an amount of pixels to include at the lowest level and at the highest level. + * If its is zero only empty counts of the histogram will be considered. \n + * Images must be IM_BYTE/(IM_RGB or IM_GRAY). Can be done in place. \n + * To expand the gammut without using the histogram, by just specifing the lowest and highest levels + * use the \ref IM_GAMUT_EXPAND tone gammut operation (\ref imProcessToneGamut). + * + * \verbatim im.ProcessExpandHistogram(src_image: imImage, dst_image: imImage, percent: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessExpandHistogramNew(src_image: imImage, percent: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup histo */ +void imProcessExpandHistogram(const imImage* src_image, imImage* dst_image, float percent); + +/** Performs an histogram equalization. \n + * Images must be IM_BYTE/(IM_RGB or IM_GRAY). Can be done in place. + * + * \verbatim im.ProcessEqualizeHistogram(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessEqualizeHistogramNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup histo */ +void imProcessEqualizeHistogram(const imImage* src_image, imImage* dst_image); + + + +/** \defgroup colorproc Color Processing Operations + * \par + * Operations to change the color components configuration. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Split a RGB image into luma and chroma. \n + * Chroma is calculated as R-Y,G-Y,B-Y. Source image must be IM_RGB/IM_BYTE. \n + * luma image is IM_GRAY/IM_BYTE and chroma is IM_RGB/IM_BYTE. \n + * Source and destiny must have the same size. + * + * \verbatim im.ProcessSplitYChroma(src_image: imImage, y_image: imImage, chroma_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessSplitYChromaNew(src_image: imImage) -> y_image: imImage, chroma_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessSplitYChroma(const imImage* src_image, imImage* y_image, imImage* chroma_image); + +/** Split a RGB image into HSI planes. \n + * Source image must be IM_RGB/IM_BYTE,IM_FLOAT. Destiny images are all IM_GRAY/IM_FLOAT. \n + * Source images must normalized to 0-1 if type is IM_FLOAT (\ref imProcessToneGamut can be used). See \ref hsi for a definition of the color conversion.\n + * Source and destiny must have the same size. + * + * \verbatim im.ProcessSplitHSI(src_image: imImage, h_image: imImage, s_image: imImage, i_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessSplitHSINew(src_image: imImage) -> h_image: imImage, s_image: imImage, i_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessSplitHSI(const imImage* src_image, imImage* h_image, imImage* s_image, imImage* i_image); + +/** Merge HSI planes into a RGB image. \n + * Source images must be IM_GRAY/IM_FLOAT. Destiny image can be IM_RGB/IM_BYTE,IM_FLOAT. \n + * Source and destiny must have the same size. See \ref hsi for a definition of the color conversion. + * + * \verbatim im.ProcessMergeHSI(h_image: imImage, s_image: imImage, i_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMergeHSINew(h_image: imImage, s_image: imImage, i_image: imImage) -> dst_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessMergeHSI(const imImage* h_image, const imImage* s_image, const imImage* i_image, imImage* dst_image); + +/** Split a multicomponent image into separate components.\n + * Destiny images must be IM_GRAY. Size and data types must be all the same.\n + * The number of destiny images must match the depth of the source image. + * + * \verbatim im.ProcessSplitComponents(src_image: imImage, dst_image_list: table of imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessSplitComponentsNew(src_image: imImage) -> dst_image_list: table of imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessSplitComponents(const imImage* src_image, imImage** dst_image_list); + +/** Merges separate components into a multicomponent image.\n + * Source images must be IM_GRAY. Size and data types must be all the same.\n + * The number of source images must match the depth of the destiny image. + * + * \verbatim im.ProcessMergeComponents(src_image_list: table of imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessMergeComponentsNew(src_image_list: table of imImage) -> dst_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessMergeComponents(const imImage** src_image_list, imImage* dst_image); + +/** Normalize the color components by their sum. Example: c1 = c1/(c1+c2+c3). \n + * Destiny image must be IM_FLOAT. + * + * \verbatim im.ProcessNormalizeComponents(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessNormalizeComponentsNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessNormalizeComponents(const imImage* src_image, imImage* dst_image); + +/** Replaces the source color by the destiny color. \n + * The color will be type casted to the image data type. \n + * The colors must have the same number of components of the images. \n + * Supports all color spaces and all data types except IM_CFLOAT. + * + * \verbatim im.ProcessReplaceColor(src_image: imImage, dst_image: imImage, src_color: table of numbers, dst_color: table of numbers) [in Lua 5] \endverbatim + * \verbatim im.ProcessReplaceColorNew(src_image: imImage, src_color: table of numbers, dst_color: table of numbers) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup colorproc */ +void imProcessReplaceColor(const imImage* src_image, imImage* dst_image, float* src_color, float* dst_color); + + + +/** \defgroup logic Logical Arithmetic Operations + * \par + * Logical binary math operations for images. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Logical Operations. + * \ingroup logic */ +enum imLogicOp { + IM_BIT_AND, /**< and = a & b */ + IM_BIT_OR, /**< or = a | b */ + IM_BIT_XOR /**< xor = ~(a | b) */ +}; + +/** Apply a logical operation.\n + * Images must have data type IM_BYTE, IM_USHORT or IM_INT. Can be done in place. + * + * \verbatim im.ProcessBitwiseOp(src_image1: imImage, src_image2: imImage, dst_image: imImage, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessBitwiseOpNew(src_image1: imImage, src_image2: imImage, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup logic */ +void imProcessBitwiseOp(const imImage* src_image1, const imImage* src_image2, imImage* dst_image, int op); + +/** Apply a logical NOT operation.\n + * Images must have data type IM_BYTE, IM_USHORT or IM_INT. Can be done in place. + * + * \verbatim im.ProcessBitwiseNot(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessBitwiseNotNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup logic */ +void imProcessBitwiseNot(const imImage* src_image, imImage* dst_image); + +/** Apply a bit mask. \n + * The same as imProcessBitwiseOp but the second image is replaced by a fixed mask. \n + * Images must have data type IM_BYTE. It is valid only for AND, OR and XOR. Can be done in place. + * + * \verbatim im.ProcessBitMask(src_image: imImage, dst_image: imImage, mask: string, op: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessBitMaskNew(src_image: imImage, mask: string, op: number) -> new_image: imImage [in Lua 5] \endverbatim + * In Lua, mask is a string with 0s and 1s, for example: "11001111". + * \ingroup logic */ +void imProcessBitMask(const imImage* src_image, imImage* dst_image, unsigned char mask, int op); + +/** Extract or Reset a bit plane. For ex: 000X0000 or XXX0XXXX (plane=3).\n + * Images must have data type IM_BYTE. Can be done in place. + * + * \verbatim im.ProcessBitPlane(src_image: imImage, dst_image: imImage, plane: number, do_reset: boolean) [in Lua 5] \endverbatim + * \verbatim im.ProcessBitPlaneNew(src_image: imImage, plane: number, do_reset: boolean) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup logic */ +void imProcessBitPlane(const imImage* src_image, imImage* dst_image, int plane, int do_reset); + + + +/** \defgroup render Synthetic Image Render + * \par + * Renders some 2D mathematical functions as images. All the functions operates in place + * and supports all data types except IM_CFLOAT. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Render Funtion. + * \verbatim render_func(x: number, y: number, d: number, param: table of number) -> value: number [in Lua 5] \endverbatim + * \ingroup render */ +typedef float (*imRenderFunc)(int x, int y, int d, float* param); + +/** Render Conditional Funtion. + * \verbatim render_cond_func(x: number, y: number, d: number, param: table of number) -> value: number, cond: boolean [in Lua 5] \endverbatim + * \ingroup render */ +typedef float (*imRenderCondFunc)(int x, int y, int d, int *cond, float* param); + +/** Render a synthetic image using a render function. \n + * plus will make the render be added to the current image data, + * or else all data will be replaced. All the render functions use this or the conditional function. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRenderOp(image: imImage, render_func: function, render_name: string, param: table of number, plus: boolean) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderOp(imImage* image, imRenderFunc render_func, char* render_name, float* param, int plus); + +/** Render a synthetic image using a conditional render function. \n + * Data will be rendered only if the condional param is true. \n + * Returns zero if the counter aborted. + * + * \verbatim im.ProcessRenderCondOp(image: imImage, render_cond_func: function, render_name: string, param: table of number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderCondOp(imImage* image, imRenderCondFunc render_cond_func, char* render_name, float* param); + +/** Render speckle noise on existing data. Can be done in place. + * + * \verbatim im.ProcessRenderAddSpeckleNoise(src_image: imImage, dst_image: imImage, percent: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRenderAddSpeckleNoiseNew(src_image: imImage, percent: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderAddSpeckleNoise(const imImage* src_image, imImage* dst_image, float percent); + +/** Render gaussian noise on existing data. Can be done in place. + * + * \verbatim im.ProcessRenderAddGaussianNoise(src_image: imImage, dst_image: imImage, mean: number, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRenderAddGaussianNoiseNew(src_image: imImage, mean: number, stddev: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderAddGaussianNoise(const imImage* src_image, imImage* dst_image, float mean, float stddev); + +/** Render uniform noise on existing data. Can be done in place. + * + * \verbatim im.ProcessRenderAddUniformNoise(src_image: imImage, dst_image: imImage, mean: number, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \verbatim im.ProcessRenderAddUniformNoiseNew(src_image: imImage, mean: number, stddev: number) -> counter: boolean, new_image: imImage [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderAddUniformNoise(const imImage* src_image, imImage* dst_image, float mean, float stddev); + +/** Render random noise. + * + * \verbatim im.ProcessRenderRandomNoise(image: imImage) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderRandomNoise(imImage* image); + +/** Render a constant. The number of values must match the depth of the image. + * + * \verbatim im.ProcessRenderConstant(image: imImage, value: table of number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderConstant(imImage* image, float* value); + +/** Render a centered wheel. + * + * \verbatim im.ProcessRenderWheel(image: imImage, internal_radius: number, external_radius: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderWheel(imImage* image, int internal_radius, int external_radius); + +/** Render a centered cone. + * + * \verbatim im.ProcessRenderCone(image: imImage, radius: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderCone(imImage* image, int radius); + +/** Render a centered tent. + * + * \verbatim im.ProcessRenderTent(image: imImage, tent_width: number, tent_height: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderTent(imImage* image, int tent_width, int tent_height); + +/** Render a ramp. Direction can be vertical (1) or horizontal (0). + * + * \verbatim im.ProcessRenderRamp(image: imImage, start: number, end: number, vert_dir: boolean) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderRamp(imImage* image, int start, int end, int vert_dir); + +/** Render a centered box. + * + * \verbatim im.ProcessRenderBox(image: imImage, box_width: number, box_height: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderBox(imImage* image, int box_width, int box_height); + +/** Render a centered sinc. + * + * \verbatim im.ProcessRenderSinc(image: imImage, x_period: number, y_period: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderSinc(imImage* image, float x_period, float y_period); + +/** Render a centered gaussian. + * + * \verbatim im.ProcessRenderGaussian(image: imImage, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderGaussian(imImage* image, float stddev); + +/** Render the laplacian of a centered gaussian. + * + * \verbatim im.ProcessRenderLapOfGaussian(image: imImage, stddev: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderLapOfGaussian(imImage* image, float stddev); + +/** Render a centered cosine. + * + * \verbatim im.ProcessRenderCosine(image: imImage, x_period: number, y_period: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderCosine(imImage* image, float x_period, float y_period); + +/** Render a centered grid. + * + * \verbatim im.ProcessRenderGrid(image: imImage, x_space: number, y_space: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderGrid(imImage* image, int x_space, int y_space); + +/** Render a centered chessboard. + * + * \verbatim im.ProcessRenderChessboard(image: imImage, x_space: number, y_space: number) -> counter: boolean [in Lua 5] \endverbatim + * \ingroup render */ +int imProcessRenderChessboard(imImage* image, int x_space, int y_space); + + + +/** \defgroup tonegamut Tone Gamut Operations + * \par + * Operations that try to preserve the min-max interval in the output (the dynamic range). + * \par + * See \ref im_process_pon.h + * \ingroup process */ + + +/** Tone Gamut Operations. + * \ingroup tonegamut */ +enum imToneGamut { + IM_GAMUT_NORMALIZE, /**< normalize = (a-min) / (max-min) (destiny image must be IM_FLOAT) */ + IM_GAMUT_POW, /**< pow = ((a-min) / (max-min))^gamma * (max-min) + min \n + param[0]=gamma */ + IM_GAMUT_LOG, /**< log = log(K * (a-min) / (max-min) + 1))*(max-min)/log(K+1) + min \n + param[0]=K (K>0) */ + IM_GAMUT_EXP, /**< exp = (exp(K * (a-min) / (max-min)) - 1))*(max-min)/(exp(K)-1) + min \n + param[0]=K */ + IM_GAMUT_INVERT, /**< invert = max - (a-min) */ + IM_GAMUT_ZEROSTART, /**< zerostart = a - min */ + IM_GAMUT_SOLARIZE, /**< solarize = a < level ? a: (level * (max-min) - a * (level-min)) / (max-level) \n + param[0]=level percentage (0-100) relative to min-max \n + photography solarization effect. */ + IM_GAMUT_SLICE, /**< slice = start < a || a > end ? min: binarize? max: a \n + param[0]=start, param[1]=end, param[2]=binarize */ + IM_GAMUT_EXPAND, /**< expand = a < start ? min: a > end ? max : (a-start)*(max-min)/(end-start) + min \n + param[0]=start, param[1]=end */ + IM_GAMUT_CROP, /**< crop = a < start ? start: a > end ? end : a \n + param[0]=start, param[1]=end */ + IM_GAMUT_BRIGHTCONT /**< brightcont = a < min ? min: a > max ? max: a * tan(c_a) + b_s + (max-min)*(1 - tan(c_a))/2 \n + param[0]=bright_shift (-100%..+100%), param[1]=contrast_factor (-100%..+100%) \n + change brightness and contrast simultaneously. */ +}; + +/** Apply a gamut operation with arguments. \n + * Supports all data types except IM_CFLOAT. \n + * The linear operation do a special convertion when min > 0 and max < 1, it forces min=0 and max=1. \n + * IM_BYTE images have min=0 and max=255 always. \n + * Can be done in place. When there is no extra params use NULL. + * + * \verbatim im.ProcessToneGamut(src_image: imImage, dst_image: imImage, op: number, param: table of number) [in Lua 5] \endverbatim + * \verbatim im.ProcessToneGamutNew(src_image: imImage, op: number, param: table of number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup tonegamut */ +void imProcessToneGamut(const imImage* src_image, imImage* dst_image, int op, float* param); + +/** Converts from (0-1) to (0-255), crop out of bounds values. \n + * Source image must be IM_FLOAT, and destiny image must be IM_BYTE. + * + * \verbatim im.ProcessUnNormalize(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessUnNormalizeNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup tonegamut */ +void imProcessUnNormalize(const imImage* src_image, imImage* dst_image); + +/** Directly converts IM_USHORT, IM_INT and IM_FLOAT into IM_BYTE images. \n + * This can also be done using \ref imConvertDataType with IM_CAST_DIRECT. + * + * \verbatim im.ProcessDirectConv(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessDirectConvNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup tonegamut */ +void imProcessDirectConv(const imImage* src_image, imImage* dst_image); + +/** A negative effect. Uses \ref imProcessToneGamut with IM_GAMUT_INVERT for non MAP images. \n + * Supports all color spaces and all data types except IM_CFLOAT. \n + * Can be done in place. + * + * \verbatim im.ProcessNegative(src_image: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessNegativeNew(src_image: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup tonegamut */ +void imProcessNegative(const imImage* src_image, imImage* dst_image); + + + +/** \defgroup threshold Threshold Operations + * \par + * Operations that converts a usually IM_GRAY/IM_BYTE image into a IM_BINARY image using several threshold techniques. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + +/** Apply a manual threshold. \n + * threshold = a <= level ? 0: value \n + * Normal value is 1 but another common value is 255. Can be done in place for IM_BYTE source. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. + * + * \verbatim im.ProcessThreshold(src_image: imImage, dst_image: imImage, level: number, value: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessThresholdNew(src_image: imImage, level: number, value: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessThreshold(const imImage* src_image, imImage* dst_image, int level, int value); + +/** Apply a threshold by the difference of two images. \n + * threshold = a1 <= a2 ? 0: 1 \n + * Can be done in place. + * + * \verbatim im.ProcessThresholdByDiff(src_image1: imImage, src_image2: imImage, dst_image: imImage) [in Lua 5] \endverbatim + * \verbatim im.ProcessThresholdByDiffNew(src_image1: imImage, src_image2: imImage) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessThresholdByDiff(const imImage* src_image1, const imImage* src_image2, imImage* dst_image); + +/** Apply a threshold by the Hysteresis method. \n + * Hysteresis thersholding of edge pixels. Starting at pixels with a + * value greater than the HIGH threshold, trace a connected sequence + * of pixels that have a value greater than the LOW threhsold. \n + * Supports only IM_BYTE images. + * Note: could not find the original source code author name. + * + * \verbatim im.ProcessHysteresisThreshold(src_image: imImage, dst_image: imImage, low_thres: number, high_thres: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessHysteresisThresholdNew(src_image: imImage, low_thres: number, high_thres: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessHysteresisThreshold(const imImage* src_image, imImage* dst_image, int low_thres, int high_thres); + +/** Estimates hysteresis low and high threshold levels. \n + * Supports only IM_BYTE images. + * Usefull for \ref imProcessHysteresisThreshold. + * + * \verbatim im.ProcessHysteresisThresEstimate(image: imImage) -> low_level: number, high_level: number [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessHysteresisThresEstimate(const imImage* image, int *low_level, int *high_level); + +/** Calculates the threshold level for manual threshold using an uniform error approach. \n + * Supports only IM_BYTE images. + * Extracted from XITE, Copyright 1991, Blab, UiO \n + * http://www.ifi.uio.no/~blab/Software/Xite/ +\verbatim + Reference: + S. M. Dunn & D. Harwood & L. S. Davis: + "Local Estimation of the Uniform Error Threshold" + IEEE Trans. on PAMI, Vol PAMI-6, No 6, Nov 1984. + Comments: It only works well on images whith large objects. + Author: Olav Borgli, BLAB, ifi, UiO + Image processing lab, Department of Informatics, University of Oslo +\endverbatim + * Returns the used level. + * + * \verbatim im.ProcessUniformErrThreshold(src_image: imImage, dst_image: imImage) -> level: number [in Lua 5] \endverbatim + * \verbatim im.ProcessUniformErrThresholdNew(src_image: imImage) -> level: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessUniformErrThreshold(const imImage* src_image, imImage* dst_image); + +/** Apply a dithering on each image channel by using a difusion error method. \n + * It can be applied on any IM_BYTE images. It will "threshold" each channel indivudually, so + * source and destiny must be of the same depth. + * + * \verbatim im.ProcessDifusionErrThreshold(src_image: imImage, dst_image: imImage, level: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessDifusionErrThresholdNew(src_image: imImage, level: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessDifusionErrThreshold(const imImage* src_image, imImage* dst_image, int level); + +/** Calculates the threshold level for manual threshold using a percentage of pixels + * that should stay bellow the threshold. \n + * Supports only IM_BYTE images. + * Returns the used level. + * + * \verbatim im.ProcessPercentThreshold(src_image: imImage, dst_image: imImage, percent: number) -> level: number [in Lua 5] \endverbatim + * \verbatim im.ProcessPercentThresholdNew(src_image: imImage, percent: number) -> level: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessPercentThreshold(const imImage* src_image, imImage* dst_image, float percent); + +/** Calculates the threshold level for manual threshold using the Otsu approach. \n + * Returns the used level. \n + * Supports only IM_BYTE images. + * Original implementation by Flavio Szenberg. + * + * \verbatim im.ProcessOtsuThreshold(src_image: imImage, dst_image: imImage) -> level: number [in Lua 5] \endverbatim + * \verbatim im.ProcessOtsuThresholdNew(src_image: imImage) -> level: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessOtsuThreshold(const imImage* src_image, imImage* dst_image); + +/** Calculates the threshold level for manual threshold using (max-min)/2. \n + * Returns the used level. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. + * + * \verbatim im.ProcessMinMaxThreshold(src_image: imImage, dst_image: imImage) -> level: number [in Lua 5] \endverbatim + * \verbatim im.ProcessMinMaxThresholdNew(src_image: imImage) -> level: number, new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +int imProcessMinMaxThreshold(const imImage* src_image, imImage* dst_image); + +/** Estimates Local Max threshold level for IM_BYTE images. + * + * \verbatim im.ProcessLocalMaxThresEstimate(image: imImage) -> level: number [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessLocalMaxThresEstimate(const imImage* image, int *level); + +/** Apply a manual threshold using an interval. \n + * threshold = start_level <= a <= end_level ? 1: 0 \n + * Normal value is 1 but another common value is 255. Can be done in place for IM_BYTE source. \n + * Supports all integer IM_GRAY images as source, and IM_BINARY as destiny. + * + * \verbatim im.ProcessSliceThreshold(src_image: imImage, dst_image: imImage, start_level: number, end_level: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessSliceThresholdNew(src_image: imImage, start_level: number, end_level: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup threshold */ +void imProcessSliceThreshold(const imImage* src_image, imImage* dst_image, int start_level, int end_level); + + +/** \defgroup effects Special Effects + * \par + * Operations to change image appearance. + * \par + * See \ref im_process_pon.h + * \ingroup process */ + + +/** Generates a zoom in effect averaging colors inside a square region. \n + * Operates only on IM_BYTE images. + * + * \verbatim im.ProcessPixelate(src_image: imImage, dst_image: imImage, box_size: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessPixelateNew(src_image: imImage, box_size: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup effects */ +void imProcessPixelate(const imImage* src_image, imImage* dst_image, int box_size); + +/** A simple Posterize effect. It reduces the number of colors in the image eliminating + * less significant bit planes. Can have 1 to 7 levels. See \ref imProcessBitMask. \n + * Images must have data type IM_BYTE. + * + * \verbatim im.ProcessPosterize(src_image: imImage, dst_image: imImage, level: number) [in Lua 5] \endverbatim + * \verbatim im.ProcessPosterizeNew(src_image: imImage, level: number) -> new_image: imImage [in Lua 5] \endverbatim + * \ingroup effects */ +void imProcessPosterize(const imImage* src_image, imImage* dst_image, int level); + + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_raw.h b/include/im_raw.h new file mode 100644 index 0000000..073ad7d --- /dev/null +++ b/include/im_raw.h @@ -0,0 +1,34 @@ +/** \file + * \brief RAW File Format + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_RAW_H +#define __IM_RAW_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** Opens a RAW image file. + * See also \ref imErrorCodes. + * + * \verbatim im.FileOpenRaw(file_name: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup raw */ +imFile* imFileOpenRaw(const char* file_name, int *error); + +/** Creates a RAW image file. + * See also \ref imErrorCodes. + * + * \verbatim im.FileNewRaw(file_name: string) -> ifile: imFile, error: number [in Lua 5] \endverbatim + * \ingroup raw */ +imFile* imFileNewRaw(const char* file_name, int *error); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/im_util.h b/include/im_util.h new file mode 100644 index 0000000..ab50671 --- /dev/null +++ b/include/im_util.h @@ -0,0 +1,277 @@ +/** \file + * \brief Utilities + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_UTIL_H +#define __IM_UTIL_H + +#if defined(__cplusplus) +extern "C" { +#endif + + +/** \defgroup util Utilities + * \par + * See \ref im_util.h + * @{ + */ + +#define IM_MIN(_a, _b) (_a < _b? _a: _b) +#define IM_MAX(_a, _b) (_a > _b? _a: _b) + +/** @} */ + + +/** \defgroup str String Utilities + * \par + * See \ref im_util.h + * \ingroup util */ + +/** Check if the two strings are equal. + * \ingroup str */ +int imStrEqual(const char* str1, const char* str2); + +/** Calculate the size of the string but limited to max_len. + * \ingroup str */ +int imStrNLen(const char* str, int max_len); + +/** Check if the data is a string. + * \ingroup str */ +int imStrCheck(const void* data, int count); + + + +/** \defgroup imageutil Raw Data Utilities + * \par + * See \ref im_util.h + * \ingroup imagerep */ + +/** Returns the size of the data buffer. + * + * \verbatim im.ImageDataSize(width: number, height: number, color_mode: number, data_type: number) -> datasize: number [in Lua 5] \endverbatim + * \ingroup imageutil */ +int imImageDataSize(int width, int height, int color_mode, int data_type); + +/** Returns the size of one line of the data buffer. \n + * This depends if the components are packed. If packed includes all components, if not includes only one. + * + * \verbatim im.ImageLineSize(width: number, color_mode: number, data_type: number) -> linesize: number [in Lua 5] \endverbatim + * \ingroup imageutil */ +int imImageLineSize(int width, int color_mode, int data_type); + +/** Returns the number of elements of one line of the data buffer. \n + * This depends if the components are packed. If packed includes all components, if not includes only one. + * + * \verbatim im.ImageLineCount(width: number, color_mode: number) -> linecount: number [in Lua 5] \endverbatim + * \ingroup imageutil */ +int imImageLineCount(int width, int color_mode); + +/** Check if the combination color_mode+data_type is valid. + * + * \verbatim im.ImageCheckFormat(color_mode: number, data_type: number) -> check: boolean [in Lua 5] \endverbatim + * \ingroup imageutil */ +int imImageCheckFormat(int color_mode, int data_type); + + + +/** \defgroup colorutl Color Utilities + * \par + * See \ref im_util.h + * \ingroup util */ + +/** Encode RGB components in a long for palete usage. \n + * "long" definition is compatible with the CD library definition. + * + * \verbatim im.ColorEncode(red: number, green: number, blue: number) -> color: lightuserdata [in Lua 5] \endverbatim + * \ingroup colorutl */ +long imColorEncode(unsigned char red, unsigned char green, unsigned char blue); + +/** Decode RGB components from a long for palete usage. \n + * "long" definition is compatible with the CD library definition. + * + * \verbatim im.ColorDecode(color: lightuserdata) -> red: number, green: number, blue: number [in Lua 5] \endverbatim + * \ingroup colorutl */ +void imColorDecode(unsigned char *red, unsigned char *green, unsigned char *blue, long color); + + + +/** \defgroup colormodeutl Color Mode Utilities + * \par + * See \ref im_util.h + * \ingroup imagerep */ + +/** Returns the color mode name. + * + * \verbatim im.ColorModeSpaceName(color_mode: number) -> name: string [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +const char* imColorModeSpaceName(int color_mode); + +/** Returns the number of components of the color space including alpha. + * + * \verbatim im.ColorModeDepth(color_mode: number) -> depth: number [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +int imColorModeDepth(int color_mode); + +/** Returns the color space of the color mode. + * + * \verbatim im.ColorModeSpace(color_mode: number) -> color_space: number [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeSpace(_cm) (_cm & 0xFF) + +/** Check if the two color modes match. Only the color space is compared. + * + * \verbatim im.ColorModeMatch(color_mode1: number, color_mode2: number) -> match: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeMatch(_cm1, _cm2) (imColorModeSpace(_cm1) == imColorModeSpace(_cm2)) + +/** Check if the color mode has an alpha channel. + * + * \verbatim im.ColorModeHasAlpha(color_mode: number) -> has_alpha: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeHasAlpha(_cm) (_cm & IM_ALPHA) + +/** Check if the color mode components are packed in one plane. + * + * \verbatim im.ColorModeIsPacked(color_mode: number) -> is_packed: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeIsPacked(_cm) (_cm & IM_PACKED) + +/** Check if the color mode orients the image from top down to bottom. + * + * \verbatim im.ColorModeIsTopDown(color_mode: number) -> is_top_down: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +#define imColorModeIsTopDown(_cm) (_cm & IM_TOPDOWN) + +/** Returns the color space of the equivalent display bitmap image. \n + * Original packing and alpha are ignored. Returns IM_RGB, IM_GRAY, IM_MAP or IM_BINARY. + * + * \verbatim im.ColorModeToBitmap(color_mode: number) -> color_space: number [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +int imColorModeToBitmap(int color_mode); + +/** Check if the color mode and data_type defines a display bitmap image. + * + * \verbatim im.ColorModeIsBitmap(color_mode: number, data_type: number) -> is_bitmap: boolean [in Lua 5] \endverbatim + * \ingroup colormodeutl */ +int imColorModeIsBitmap(int color_mode, int data_type); + + + +/** \defgroup datatypeutl Data Type Utilities + * \par + * See \ref im_util.h + * \ingroup util + * @{ + */ + +typedef unsigned char imbyte; +typedef unsigned short imushort; + +#define IM_BYTECROP(_v) (_v < 0? 0: _v > 255? 255: _v) +#define IM_CROPMAX(_v, _max) (_v < 0? 0: _v > _max? _max: _v) + +/** @} */ + +/** Returns the size in bytes of a specified numeric data type. + * + * \verbatim im.DataTypeSize(data_type: number) -> size: number [in Lua 5] \endverbatim + * \ingroup datatypeutl */ +int imDataTypeSize(int data_type); + +/** Returns the numeric data type name given its identifier. + * + * \verbatim im.DataTypeName(data_type: number) -> name: string [in Lua 5] \endverbatim + * \ingroup datatypeutl */ +const char* imDataTypeName(int data_type); + +/** Returns the maximum value of an integer data type. For floating point returns 0. + * + * \verbatim im.DataTypeIntMax(data_type: number) -> int_max: number [in Lua 5] \endverbatim + * \ingroup datatypeutl */ +unsigned long imDataTypeIntMax(int data_type); + +/** Returns the minimum value of an integer data type. For floating point returns 0. + * + * \verbatim im.DataTypeIntMin(data_type: number) -> int_min: number [in Lua 5] \endverbatim + * \ingroup datatypeutl */ +long imDataTypeIntMin(int data_type); + + + +/** \defgroup bin Binary Data Utilities + * \par + * See \ref im_util.h + * \ingroup util */ + +/** CPU Byte Orders. + * \ingroup bin */ +enum imByteOrder +{ + IM_LITTLEENDIAN, /**< Little Endian - The most significant byte is on the right end of a word. Used by Intel processors. */ + IM_BIGENDIAN /**< Big Endian - The most significant byte is on the left end of a word. Used by Motorola processors, also is the network standard byte order. */ +}; + +/** Returns the current CPU byte order. + * \ingroup bin */ +int imBinCPUByteOrder(void); + +/** Changes the byte order of an array of 2, 4 or 8 byte values. + * \ingroup bin */ +void imBinSwapBytes(void *data, int count, int size); + +/** Changes the byte order of an array of 2 byte values. + * \ingroup bin */ +void imBinSwapBytes2(void *data, int count); + +/** Inverts the byte order of the 4 byte values + * \ingroup bin */ +void imBinSwapBytes4(void *data, int count); + +/** Inverts the byte order of the 8 byte values + * \ingroup bin */ +void imBinSwapBytes8(void *data, int count); + + + +/** \defgroup compress Data Compression Utilities + * \par + * Deflate compression support uses zlib version 1.2.3. \n + * http://www.zlib.org/ \n + * Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler + * \par + * LZF compression support uses libLZF version 1.51. \n + * http://liblzf.plan9.de/ \n + * Copyright (C) 2000-2005 Marc Alexander Lehmann + * See \ref im_util.h + * \ingroup util */ + +/** Compresses the data using the ZLIB Deflate compression. \n + * The destination buffer must be at least 0.1% larger than source_size plus 12 bytes. \n + * It compresses raw byte data. zip_quality can be 1 to 9. \n + * Returns the size of the compressed buffer or zero if failed. + * \ingroup compress */ +int imCompressDataZ(const void* src_data, int src_size, void* dst_data, int dst_size, int zip_quality); + +/** Uncompresses the data compressed with the ZLIB Deflate compression. \n + * Returns zero if failed. + * \ingroup compress */ +int imCompressDataUnZ(const void* src_data, int src_size, void* dst_data, int dst_size); + +/** Compresses the data using the libLZF compression. \n + * Returns the size of the compressed buffer or zero if failed. + * \ingroup compress */ +int imCompressDataLZF(const void* src_data, int src_size, void* dst_data, int dst_size, int zip_quality); + +/** Uncompresses the data compressed with the libLZF compression. + * Returns zero if failed. + * \ingroup compress */ +int imCompressDataUnLZF(const void* src_data, int src_size, void* dst_data, int dst_size); + + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/include/imlua.h b/include/imlua.h new file mode 100644 index 0000000..5714dff --- /dev/null +++ b/include/imlua.h @@ -0,0 +1,83 @@ +/** \file + * \brief IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IMLUA_H +#define __IMLUA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup imlua IM Lua 5 Binding + * \par + * Binding for the Lua 5 scripting language. \n + * Lua 5.1 Copyright (C) 1994-2005 Lua.org, PUC-Rio \n + * R. Ierusalimschy, L. H. de Figueiredo & W. Celes \n + * http://www.lua.org + * \par + * The name of the functions were changed because of the namespace "im" and because of the object orientation. \n + * As a general rule use: +\verbatim + imXxx -> im.Xxx + IM_XXX -> im.XXX + imFileXXX(ifile,... -> ifile:XXX(... + imImageXXX(image,... -> image:XXX(... +\endverbatim + * All the objects are garbage collected by the Lua garbage collector. + * \par + * See \ref imlua.h + * \ingroup util */ + +#ifdef LUA_NOOBJECT /* Lua 3 */ +void imlua_open(void); +#endif + +#ifdef LUA_TNONE /* Lua 5 */ + +/** Initializes the Lua binding of the main IM library. \n + * Returns 1 (leaves the "im" table on the top of the stack). + * You must link the application with the "imlua51" library. + * \ingroup imlua */ +int imlua_open(lua_State *L); +int luaopen_imlua(lua_State *L); + +/** Pushes an image as a metatable on the stack. + * \ingroup imlua */ +void imlua_pushimage(lua_State *L, imImage* image); + +/** Gets an image as a metatable from the stack, checks for correct type. + * \ingroup imlua */ +imImage* imlua_checkimage(lua_State *L, int param); + +/** Initializes the Lua binding of the capture library. \n + * Returns 1 (leaves the "im" table on the top of the stack). + * You must link the application with the "imlua_capture51" library. + * \ingroup imlua */ +int imlua_open_capture(lua_State *L); +int luaopen_imlua_capture(lua_State *L); + +/** Initializes the Lua binding of the process library. \n + * Returns 1 (leaves the "im" table on the top of the stack). + * You must link the application with the "imlua_process51" library. + * \ingroup imlua */ +int imlua_open_process(lua_State *L); +int luaopen_imlua_process(lua_State *L); + +/** Initializes the Lua binding of the fourier transform library. \n + * Returns 1 (leaves the "im" table on the top of the stack). + * You must link the application with the "imlua_fftw51" library. + * \ingroup imlua */ +int imlua_open_fftw(lua_State *L); +int luaopen_imlua_fftw(lua_State *L); + + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/old_im.h b/include/old_im.h new file mode 100644 index 0000000..f000221 --- /dev/null +++ b/include/old_im.h @@ -0,0 +1,59 @@ +/** \file + * \brief Old API + * + * See Copyright Notice in im_lib.h + */ + +#ifndef __IM_OLD_H +#define __IM_OLD_H + +#if defined(__cplusplus) +extern "C" { +#endif + +enum {IM_BMP, IM_PCX, IM_GIF, IM_TIF, IM_RAS, IM_SGI, IM_JPG, IM_LED, IM_TGA}; +enum {IM_NONE = 0x0000, IM_DEFAULT = 0x0100, IM_COMPRESSED = 0x0200}; + +#define IM_ERR_READ IM_ERR_ACCESS +#define IM_ERR_WRITE IM_ERR_ACCESS +#define IM_ERR_TYPE IM_ERR_DATA +#define IM_ERR_COMP IM_ERR_COMPRESS + +long imEncodeColor(unsigned char red, unsigned char green, unsigned char blue); +void imDecodeColor(unsigned char* red, unsigned char* green, unsigned char* blue, long palette); +int imFileFormat(char *filename, int* format); +int imImageInfo(char *filename, int *width, int *height, int *type, int *palette_count); +int imLoadRGB(char *filename, unsigned char *red, unsigned char *green, unsigned char *blue); +int imSaveRGB(int width, int height, int format, unsigned char *red, unsigned char *green, unsigned char *blue, char *filename); +int imLoadMap(char *filename, unsigned char *map, long *palette); +int imSaveMap(int width, int height, int format, unsigned char *map, int palette_count, long *palette, char *filename); +void imRGB2Map(int width, int height, unsigned char *red, unsigned char *green, unsigned char *blue, unsigned char *map, int palette_count, long *palette); +void imMap2RGB(int width, int height, unsigned char *map, int palette_count, long *colors, unsigned char *red, unsigned char *green, unsigned char *blue); +void imRGB2Gray(int width, int height, unsigned char *red, unsigned char *green, unsigned char *blue, unsigned char *map, long *grays); +void imMap2Gray(int width, int height, unsigned char *map, int palette_count, long *colors, unsigned char *grey_map, long *grays); +void imResize(int src_width, int src_height, unsigned char *src_map, int dst_width, int dst_height, unsigned char *dst_map); +void imStretch(int src_width, int src_height, unsigned char *src_map, int dst_width, int dst_height, unsigned char *dst_map); +typedef int (*imCallback)(char *filename); +int imRegisterCallback(imCallback cb, int cb_id, int format); + +#define IM_INTERRUPTED -1 +#define IM_ALL -1 +#define IM_COUNTER_CB 0 +typedef int (*imFileCounterCallback)(char *filename, int percent, int io); + +#define IM_RESOLUTION_CB 1 +typedef int (*imResolutionCallback)(char *filename, double* xres, double* yres, int* res_unit); + +enum {IM_RES_NONE, IM_RES_DPI, IM_RES_DPC}; + +#define IM_GIF_TRANSPARENT_COLOR_CB 0 +typedef int (*imGifTranspIndex)(char *filename, unsigned char *transp_index); + +#define IM_TIF_IMAGE_DESCRIPTION_CB 0 +typedef int (*imTiffImageDesc)(char *filename, char* img_desc); + +#if defined(__cplusplus) +} +#endif + +#endif |