diff options
author | Chris Xiong <chirs241097@gmail.com> | 2015-10-26 22:52:36 +0800 |
---|---|---|
committer | Chris Xiong <chirs241097@gmail.com> | 2015-10-26 22:52:36 +0800 |
commit | 3bd383baf6a17e734329e1fc677c7e86283db772 (patch) | |
tree | 69a9148087577f797624ceb9c71323a2563d6bb4 /archive/hge | |
parent | 543e4f570be9b279ba558ca61cc02cda251af384 (diff) | |
download | bullet-lab-remix-3bd383baf6a17e734329e1fc677c7e86283db772.tar.xz |
Added support for relative line numbers.
Added instructions for, brk and cont. (They are still untested...)
Parser code cleanup. Removed garbage output to stderr.
Reorganize the repository structure.
Updated BLR2 code move it into archive.
Added BLR1 files.
Diffstat (limited to 'archive/hge')
96 files changed, 46780 insertions, 0 deletions
diff --git a/archive/hge/CxImage/license.txt b/archive/hge/CxImage/license.txt new file mode 100644 index 0000000..1ea1f04 --- /dev/null +++ b/archive/hge/CxImage/license.txt @@ -0,0 +1,48 @@ +This copy of the CxImage notices is provided for your convenience. In case of
+any discrepancy between this copy and the notices in the file ximage.h that is
+included in the CxImage distribution, the latter shall prevail.
+
+If you modify CxImage you may insert additional notices immediately following
+this sentence.
+
+--------------------------------------------------------------------------------
+
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+CxImage version 7.0.0 31/Dec/2010
+
+CxImage : Copyright (C) 2001 - 2010, Davide Pizzolato
+
+Original CImage and CImageIterator implementation are:
+Copyright (C) 1995, Alejandro Aguilar Sierra (asierra(at)servidor(dot)unam(dot)mx)
+
+Covered code is provided under this license on an "as is" basis, without warranty
+of any kind, either expressed or implied, including, without limitation, warranties
+that the covered code is free of defects, merchantable, fit for a particular purpose
+or non-infringing. The entire risk as to the quality and performance of the covered
+code is with you. Should any covered code prove defective in any respect, you (not
+the initial developer or any other contributor) assume the cost of any necessary
+servicing, repair or correction. This disclaimer of warranty constitutes an essential
+part of this license. No use of any covered code is authorized hereunder except under
+this disclaimer.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, including commercial applications,
+freely and without fee, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+--------------------------------------------------------------------------------
+
+Other information: about CxImage, and the latest version, can be found at the
+CxImage home page: http://www.xdp.it
+
+--------------------------------------------------------------------------------
diff --git a/archive/hge/CxImage/stdint.h b/archive/hge/CxImage/stdint.h new file mode 100644 index 0000000..2e93323 --- /dev/null +++ b/archive/hge/CxImage/stdint.h @@ -0,0 +1,249 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include <limits.h> + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +/*
+#ifdef __cplusplus +extern "C" { +#endif +# include <wchar.h> +#ifdef __cplusplus +} +#endif +*/
+ +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/archive/hge/CxImage/tif_xfile.cpp b/archive/hge/CxImage/tif_xfile.cpp new file mode 100644 index 0000000..4d1d79a --- /dev/null +++ b/archive/hge/CxImage/tif_xfile.cpp @@ -0,0 +1,221 @@ +/*
+ * TIFF file IO, using CxFile.
+ */
+
+#ifdef WIN32
+ #include <windows.h>
+#endif
+#include <stdio.h>
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_TIF
+
+#include "../tiff/tiffiop.h"
+#include "../tiff/tiffvers.h"
+
+#include "xfile.h"
+
+static tsize_t
+_tiffReadProcEx(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (tsize_t)((CxFile*)fd)->Read(buf, 1, size);
+}
+
+static tsize_t
+_tiffWriteProcEx(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (tsize_t)((CxFile*)fd)->Write(buf, 1, size);
+}
+
+static toff_t
+_tiffSeekProcEx(thandle_t fd, toff_t off, int whence)
+{
+ if ( off == 0xFFFFFFFF )
+ return 0xFFFFFFFF;
+ if (!((CxFile*)fd)->Seek(off, whence))
+ return 0xFFFFFFFF;
+ if (whence == SEEK_SET)
+ return off;
+
+ return (toff_t)((CxFile*)fd)->Tell();
+}
+
+// Return nonzero if error
+static int
+_tiffCloseProcEx(thandle_t /*fd*/)
+{
+// return !((CxFile*)fd)->Close(); // "//" needed for memory files <DP>
+ return 0;
+}
+
+#include <sys/stat.h>
+
+static toff_t
+_tiffSizeProcEx(thandle_t fd)
+{
+ return ((CxFile*)fd)->Size();
+}
+
+static int
+_tiffMapProcEx(thandle_t /*fd*/, tdata_t* /*pbase*/, toff_t* /*psize*/)
+{
+ return (0);
+}
+
+static void
+_tiffUnmapProcEx(thandle_t /*fd*/, tdata_t /*base*/, toff_t /*size*/)
+{
+}
+
+// Open a TIFF file descriptor for read/writing.
+/*
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ FILE* stream = fopen(name, mode);
+ if (stream == NULL)
+ {
+ TIFFError(module, "%s: Cannot open", name);
+ return NULL;
+ }
+ return (TIFFFdOpen((int)stream, name, mode));
+}
+*/
+
+TIFF*
+_TIFFFdOpen(void* fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) fd,
+ _tiffReadProcEx, _tiffWriteProcEx, _tiffSeekProcEx, _tiffCloseProcEx,
+ _tiffSizeProcEx, _tiffMapProcEx, _tiffUnmapProcEx);
+ if (tif)
+ {
+ tif->tif_fd = (int)fd;
+ }
+ return (tif);
+}
+
+extern "C" TIFF* _TIFFOpenEx(CxFile* stream, const char* mode)
+{
+ return (_TIFFFdOpen(stream, "TIFF IMAGE", mode));
+}
+
+#ifdef __GNUC__
+extern char* malloc();
+extern char* realloc();
+#else
+#include <malloc.h>
+#endif
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+ return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+#ifndef UNICODE
+#define DbgPrint wvsprintf
+#define DbgPrint2 wsprintf
+#define DbgMsgBox MessageBox
+#else
+#define DbgPrint wvsprintfA
+#define DbgPrint2 wsprintfA
+#define DbgMsgBox MessageBoxA
+#endif
+
+static void
+Win32WarningHandler(const char* module, const char* fmt, va_list ap)
+{
+#ifdef _DEBUG
+#if (!defined(_CONSOLE) && !defined(_WIN32_WCE) && defined(WIN32))
+ LPSTR szTitle;
+ LPSTR szTmp;
+ LPCSTR szTitleText = "%s Warning";
+ LPCSTR szDefaultModule = "TIFFLIB";
+ szTmp = (module == NULL) ? (LPSTR)szDefaultModule : (LPSTR)module;
+ if ((szTitle = (LPSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmp) +
+ strlen(szTitleText) + strlen(fmt) + 128))) == NULL)
+ return;
+ DbgPrint2(szTitle, szTitleText, szTmp);
+ szTmp = szTitle + (strlen(szTitle)+2);
+ DbgPrint(szTmp, fmt, ap);
+ DbgMsgBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION);
+ LocalFree(szTitle);
+ return;
+#else
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+#endif
+#endif
+}
+TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
+
+static void
+Win32ErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+#ifdef _DEBUG
+#if (!defined(_CONSOLE) && !defined(_WIN32_WCE) && defined(WIN32))
+ LPSTR szTitle;
+ LPSTR szTmp;
+ LPCSTR szTitleText = "%s Error";
+ LPCSTR szDefaultModule = "TIFFLIB";
+ szTmp = (module == NULL) ? (LPSTR)szDefaultModule : (LPSTR)module;
+ if ((szTitle = (LPSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmp) +
+ strlen(szTitleText) + strlen(fmt) + 128))) == NULL)
+ return;
+ DbgPrint2(szTitle, szTitleText, szTmp);
+ szTmp = szTitle + (strlen(szTitle)+2);
+ DbgPrint(szTmp, fmt, ap);
+ DbgMsgBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION);
+ LocalFree(szTitle);
+ return;
+#else
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+#endif
+#endif
+}
+TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
+
+#endif
+
diff --git a/archive/hge/CxImage/xfile.h b/archive/hge/CxImage/xfile.h new file mode 100644 index 0000000..6de281c --- /dev/null +++ b/archive/hge/CxImage/xfile.h @@ -0,0 +1,79 @@ +/*
+ * File: xfile.h
+ * Purpose: General Purpose File Class
+ */
+/*
+ --------------------------------------------------------------------------------
+
+ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+ CxFile (c) 11/May/2002 Davide Pizzolato - www.xdp.it
+ CxFile version 2.00 23/Aug/2002
+ CxFile version 2.10 16/Dec/2007
+
+ Special thanks to Chris Shearer Cooper for new features, enhancements and bugfixes
+
+ Covered code is provided under this license on an "as is" basis, without warranty
+ of any kind, either expressed or implied, including, without limitation, warranties
+ that the covered code is free of defects, merchantable, fit for a particular purpose
+ or non-infringing. The entire risk as to the quality and performance of the covered
+ code is with you. Should any covered code prove defective in any respect, you (not
+ the initial developer or any other contributor) assume the cost of any necessary
+ servicing, repair or correction. This disclaimer of warranty constitutes an essential
+ part of this license. No use of any covered code is authorized hereunder except under
+ this disclaimer.
+
+ Permission is hereby granted to use, copy, modify, and distribute this
+ source code, or portions hereof, for any purpose, including commercial applications,
+ freely and without fee, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
+ --------------------------------------------------------------------------------
+ */
+#if !defined(__xfile_h)
+#define __xfile_h
+
+#if defined (WIN32) || defined (_WIN32_WCE)
+ #include <windows.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ximadef.h"
+
+class DLL_EXP CxFile
+{
+public:
+ CxFile(void) { };
+ virtual ~CxFile() { };
+
+ virtual bool Close() = 0;
+ virtual size_t Read(void *buffer, size_t size, size_t count) = 0;
+ virtual size_t Write(const void *buffer, size_t size, size_t count) = 0;
+ virtual bool Seek(int32_t offset, int32_t origin) = 0;
+ virtual int32_t Tell() = 0;
+ virtual int32_t Size() = 0;
+ virtual bool Flush() = 0;
+ virtual bool Eof() = 0;
+ virtual int32_t Error() = 0;
+ virtual bool PutC(uint8_t c)
+ {
+ // Default implementation
+ size_t nWrote = Write(&c, 1, 1);
+ return (bool)(nWrote == 1);
+ }
+ virtual int32_t GetC() = 0;
+ virtual char * GetS(char *string, int32_t n) = 0;
+ virtual int32_t Scanf(const char *format, void* output) = 0;
+};
+
+#endif //__xfile_h
diff --git a/archive/hge/CxImage/ximabmp.cpp b/archive/hge/CxImage/ximabmp.cpp new file mode 100644 index 0000000..c173c7d --- /dev/null +++ b/archive/hge/CxImage/ximabmp.cpp @@ -0,0 +1,448 @@ +/*
+ * File: ximabmp.cpp
+ * Purpose: Platform Independent BMP Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximabmp.h"
+
+#if CXIMAGE_SUPPORT_BMP
+
+#include "ximaiter.h"
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageBMP::Encode(CxFile * hFile)
+{
+
+ if (EncodeSafeCheck(hFile)) return false;
+
+ BITMAPFILEHEADER hdr;
+
+ hdr.bfType = 0x4d42; // 'BM' WINDOWS_BITMAP_SIGNATURE
+ hdr.bfSize = GetSize() + 14 /*sizeof(BITMAPFILEHEADER)*/;
+ hdr.bfReserved1 = hdr.bfReserved2 = 0;
+ hdr.bfOffBits = 14 /*sizeof(BITMAPFILEHEADER)*/ + head.biSize + GetPaletteSize();
+
+ hdr.bfType = m_ntohs(hdr.bfType);
+ hdr.bfSize = m_ntohl(hdr.bfSize);
+ hdr.bfOffBits = m_ntohl(hdr.bfOffBits);
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (GetNumColors()==0 && AlphaIsValid()){
+
+ BITMAPINFOHEADER infohdr;
+ memcpy(&infohdr,&head,sizeof(BITMAPINFOHEADER));
+ infohdr.biCompression = BI_RGB;
+ infohdr.biBitCount = 32;
+ uint32_t dwEffWidth = ((((infohdr.biBitCount * infohdr.biWidth) + 31) / 32) * 4);
+ infohdr.biSizeImage = dwEffWidth * infohdr.biHeight;
+
+ hdr.bfSize = infohdr.biSize + infohdr.biSizeImage + 14 /*sizeof(BITMAPFILEHEADER)*/;
+
+ hdr.bfSize = m_ntohl(hdr.bfSize);
+ bihtoh(&infohdr);
+
+ // Write the file header
+ hFile->Write(&hdr,min(14,sizeof(BITMAPFILEHEADER)),1);
+ hFile->Write(&infohdr,sizeof(BITMAPINFOHEADER),1);
+ //and DIB+ALPHA interlaced
+ uint8_t *srcalpha = AlphaGetPointer();
+ for(int32_t y = 0; y < infohdr.biHeight; ++y){
+ uint8_t *srcdib = GetBits(y);
+ for(int32_t x = 0; x < infohdr.biWidth; ++x){
+ hFile->Write(srcdib,3,1);
+ hFile->Write(srcalpha,1,1);
+ srcdib += 3;
+ ++srcalpha;
+ }
+ }
+
+ } else
+#endif //CXIMAGE_SUPPORT_ALPHA
+ {
+ // Write the file header
+ hFile->Write(&hdr,min(14,sizeof(BITMAPFILEHEADER)),1);
+ //copy attributes
+ memcpy(pDib,&head,sizeof(BITMAPINFOHEADER));
+ bihtoh((BITMAPINFOHEADER*)pDib);
+ // Write the DIB header and the pixels
+ hFile->Write(pDib,GetSize(),1);
+ bihtoh((BITMAPINFOHEADER*)pDib);
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageBMP::Decode(CxFile * hFile)
+{
+ if (hFile == NULL) return false;
+
+ BITMAPFILEHEADER bf;
+ uint32_t off = hFile->Tell(); //<CSC>
+ cx_try {
+ if (hFile->Read(&bf,min(14,sizeof(bf)),1)==0) cx_throw("Not a BMP");
+
+ bf.bfSize = m_ntohl(bf.bfSize);
+ bf.bfOffBits = m_ntohl(bf.bfOffBits);
+
+ if (m_ntohs(bf.bfType) != BFT_BITMAP) { //do we have a RC HEADER?
+ bf.bfOffBits = 0L;
+ hFile->Seek(off,SEEK_SET);
+ }
+
+ BITMAPINFOHEADER bmpHeader;
+ if (!DibReadBitmapInfo(hFile,&bmpHeader)); cx_throw("Error reading BMP info");
+ uint32_t dwCompression=bmpHeader.biCompression;
+ uint32_t dwBitCount=bmpHeader.biBitCount; //preserve for BI_BITFIELDS compression <Thomas Ernst>
+ bool bIsOldBmp = bmpHeader.biSize == sizeof(BITMAPCOREHEADER);
+
+ bool bTopDownDib = bmpHeader.biHeight<0; //<Flanders> check if it's a top-down bitmap
+ if (bTopDownDib) bmpHeader.biHeight=-bmpHeader.biHeight;
+
+ if (info.nEscape == -1) {
+ // Return output dimensions only
+ head.biWidth = bmpHeader.biWidth;
+ head.biHeight = bmpHeader.biHeight;
+ info.dwType = CXIMAGE_FORMAT_BMP;
+ cx_throw("output dimensions returned");
+ }
+
+ if (!Create(bmpHeader.biWidth,bmpHeader.biHeight,bmpHeader.biBitCount,CXIMAGE_FORMAT_BMP))
+ cx_throw("");
+
+ SetXDPI((int32_t) floor(bmpHeader.biXPelsPerMeter * 254.0 / 10000.0 + 0.5));
+ SetYDPI((int32_t) floor(bmpHeader.biYPelsPerMeter * 254.0 / 10000.0 + 0.5));
+
+ if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+ RGBQUAD *pRgb = GetPalette();
+ if (pRgb){
+ if (bIsOldBmp){
+ // convert a old color table (3 byte entries) to a new
+ // color table (4 byte entries)
+ hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1);
+ for (int32_t i=DibNumColors(&head)-1; i>=0; i--){
+ pRgb[i].rgbRed = ((RGBTRIPLE *)pRgb)[i].rgbtRed;
+ pRgb[i].rgbBlue = ((RGBTRIPLE *)pRgb)[i].rgbtBlue;
+ pRgb[i].rgbGreen = ((RGBTRIPLE *)pRgb)[i].rgbtGreen;
+ pRgb[i].rgbReserved = (uint8_t)0;
+ }
+ } else {
+ hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1);
+ //force rgbReserved=0, to avoid problems with some WinXp bitmaps
+ for (uint32_t i=0; i<head.biClrUsed; i++) pRgb[i].rgbReserved=0;
+ }
+ }
+
+ if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+ switch (dwBitCount) {
+ case 32 :
+ uint32_t bfmask[3];
+ if (dwCompression == BI_BITFIELDS)
+ {
+ hFile->Read(bfmask, 12, 1);
+ } else {
+ bfmask[0]=0x00FF0000;
+ bfmask[1]=0x0000FF00;
+ bfmask[2]=0x000000FF;
+ }
+ if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
+ if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB){
+ int32_t imagesize=4*head.biHeight*head.biWidth;
+ uint8_t* buff32=(uint8_t*)malloc(imagesize);
+ if (buff32){
+ hFile->Read(buff32, imagesize,1); // read in the pixels
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (dwCompression == BI_RGB){
+ AlphaCreate();
+ if (AlphaIsValid()){
+ bool bAlphaOk = false;
+ uint8_t* p;
+ for (int32_t y=0; y<head.biHeight; y++){
+ p = buff32 + 3 + head.biWidth * 4 * y;
+ for (int32_t x=0; x<head.biWidth; x++){
+ if (*p) bAlphaOk = true;
+ AlphaSet(x,y,*p);
+ p+=4;
+ }
+ }
+ // fix if alpha pixels are all zero
+ if (!bAlphaOk) AlphaInvert();
+ }
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ Bitfield2RGB(buff32,bfmask[0],bfmask[1],bfmask[2],32);
+ free(buff32);
+ } else cx_throw("can't allocate memory");
+ } else cx_throw("unknown compression");
+ break;
+ case 24 :
+ if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
+ if (dwCompression == BI_RGB){
+ hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels
+ } else cx_throw("unknown compression");
+ break;
+ case 16 :
+ {
+ uint32_t bfmask[3];
+ if (dwCompression == BI_BITFIELDS)
+ {
+ hFile->Read(bfmask, 12, 1);
+ } else {
+ bfmask[0]=0x7C00; bfmask[1]=0x3E0; bfmask[2]=0x1F; //RGB555
+ }
+ // bf.bfOffBits required after the bitfield mask <Cui Ying Jie>
+ if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
+ // read in the pixels
+ hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1);
+ // transform into RGB
+ Bitfield2RGB(info.pImage,bfmask[0],bfmask[1],bfmask[2],16);
+ break;
+ }
+ case 8 :
+ case 4 :
+ case 1 :
+ if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);
+ switch (dwCompression) {
+ case BI_RGB :
+ hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels
+ break;
+ case BI_RLE4 :
+ {
+ uint8_t status_byte = 0;
+ uint8_t second_byte = 0;
+ int32_t scanline = 0;
+ int32_t bits = 0;
+ BOOL low_nibble = FALSE;
+ CImageIterator iter(this);
+
+ for (BOOL bContinue = TRUE; bContinue && hFile->Read(&status_byte, sizeof(uint8_t), 1);) {
+
+ switch (status_byte) {
+ case RLE_COMMAND :
+ hFile->Read(&status_byte, sizeof(uint8_t), 1);
+ switch (status_byte) {
+ case RLE_ENDOFLINE :
+ bits = 0;
+ scanline++;
+ low_nibble = FALSE;
+ break;
+ case RLE_ENDOFBITMAP :
+ bContinue=FALSE;
+ break;
+ case RLE_DELTA :
+ {
+ // read the delta values
+ uint8_t delta_x;
+ uint8_t delta_y;
+ hFile->Read(&delta_x, sizeof(uint8_t), 1);
+ hFile->Read(&delta_y, sizeof(uint8_t), 1);
+ // apply them
+ bits += delta_x / 2;
+ scanline += delta_y;
+ break;
+ }
+ default :
+ hFile->Read(&second_byte, sizeof(uint8_t), 1);
+ uint8_t *sline = iter.GetRow(scanline);
+ for (int32_t i = 0; i < status_byte; i++) {
+ if ((uint8_t*)(sline+bits) < (uint8_t*)(info.pImage+head.biSizeImage)){
+ if (low_nibble) {
+ if (i&1)
+ *(sline + bits) |= (second_byte & 0x0f);
+ else
+ *(sline + bits) |= (second_byte & 0xf0)>>4;
+ bits++;
+ } else {
+ if (i&1)
+ *(sline + bits) = (uint8_t)(second_byte & 0x0f)<<4;
+ else
+ *(sline + bits) = (uint8_t)(second_byte & 0xf0);
+ }
+ }
+
+ if ((i & 1) && (i != (status_byte - 1)))
+ hFile->Read(&second_byte, sizeof(uint8_t), 1);
+
+ low_nibble = !low_nibble;
+ }
+ if ((((status_byte+1) >> 1) & 1 ) == 1)
+ hFile->Read(&second_byte, sizeof(uint8_t), 1);
+ break;
+ };
+ break;
+ default :
+ {
+ uint8_t *sline = iter.GetRow(scanline);
+ hFile->Read(&second_byte, sizeof(uint8_t), 1);
+ for (unsigned i = 0; i < status_byte; i++) {
+ if ((uint8_t*)(sline+bits) < (uint8_t*)(info.pImage+head.biSizeImage)){
+ if (low_nibble) {
+ if (i&1)
+ *(sline + bits) |= (second_byte & 0x0f);
+ else
+ *(sline + bits) |= (second_byte & 0xf0)>>4;
+ bits++;
+ } else {
+ if (i&1)
+ *(sline + bits) = (uint8_t)(second_byte & 0x0f)<<4;
+ else
+ *(sline + bits) = (uint8_t)(second_byte & 0xf0);
+ }
+ }
+ low_nibble = !low_nibble;
+ }
+ }
+ break;
+ };
+ }
+ break;
+ }
+ case BI_RLE8 :
+ {
+ uint8_t status_byte = 0;
+ uint8_t second_byte = 0;
+ int32_t scanline = 0;
+ int32_t bits = 0;
+ CImageIterator iter(this);
+
+ for (BOOL bContinue = TRUE; bContinue && hFile->Read(&status_byte, sizeof(uint8_t), 1);) {
+ switch (status_byte) {
+ case RLE_COMMAND :
+ hFile->Read(&status_byte, sizeof(uint8_t), 1);
+ switch (status_byte) {
+ case RLE_ENDOFLINE :
+ bits = 0;
+ scanline++;
+ break;
+ case RLE_ENDOFBITMAP :
+ bContinue=FALSE;
+ break;
+ case RLE_DELTA :
+ {
+ // read the delta values
+ uint8_t delta_x;
+ uint8_t delta_y;
+ hFile->Read(&delta_x, sizeof(uint8_t), 1);
+ hFile->Read(&delta_y, sizeof(uint8_t), 1);
+ // apply them
+ bits += delta_x;
+ scanline += delta_y;
+ break;
+ }
+ default :
+ hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(uint8_t) * status_byte, 1);
+ // align run length to even number of bytes
+ if ((status_byte & 1) == 1)
+ hFile->Read(&second_byte, sizeof(uint8_t), 1);
+ bits += status_byte;
+ break;
+ };
+ break;
+ default :
+ uint8_t *sline = iter.GetRow(scanline);
+ hFile->Read(&second_byte, sizeof(uint8_t), 1);
+ for (unsigned i = 0; i < status_byte; i++) {
+ if ((uint8_t*)(sline+bits) < (uint8_t*)(info.pImage+head.biSizeImage)){
+ *(sline + bits) = second_byte;
+ bits++;
+ } else {
+ break;
+ }
+ }
+ break;
+ };
+ }
+ break;
+ }
+ default :
+ cx_throw("compression type not supported");
+ }
+ }
+
+ if (bTopDownDib) Flip(); //<Flanders>
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_BMP) return true;
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/* ReadDibBitmapInfo()
+ *
+ * Will read a file in DIB format and return a global HANDLE to its
+ * BITMAPINFO. This function will work with both "old" and "new"
+ * bitmap formats, but will always return a "new" BITMAPINFO.
+ */
+bool CxImageBMP::DibReadBitmapInfo(CxFile* fh, BITMAPINFOHEADER *pdib)
+{
+ if ((fh==NULL)||(pdib==NULL)) return false;
+
+ if (fh->Read(pdib,sizeof(BITMAPINFOHEADER),1)==0) return false;
+
+ bihtoh(pdib);
+
+ switch (pdib->biSize) // what type of bitmap info is this?
+ {
+ case sizeof(BITMAPINFOHEADER):
+ break;
+
+ case 64: //sizeof(OS2_BMP_HEADER):
+ fh->Seek((int32_t)(64 - sizeof(BITMAPINFOHEADER)),SEEK_CUR);
+ break;
+
+ case 124: //sizeof(BITMAPV5HEADER):
+ fh->Seek((long)(124-sizeof(BITMAPINFOHEADER)), SEEK_CUR);
+ break;
+
+ case sizeof(BITMAPCOREHEADER):
+ {
+ BITMAPCOREHEADER bc = *(BITMAPCOREHEADER*)pdib;
+ pdib->biSize = bc.bcSize;
+ pdib->biWidth = (uint32_t)bc.bcWidth;
+ pdib->biHeight = (uint32_t)bc.bcHeight;
+ pdib->biPlanes = bc.bcPlanes;
+ pdib->biBitCount = bc.bcBitCount;
+ pdib->biCompression = BI_RGB;
+ pdib->biSizeImage = 0;
+ pdib->biXPelsPerMeter = 0;
+ pdib->biYPelsPerMeter = 0;
+ pdib->biClrUsed = 0;
+ pdib->biClrImportant = 0;
+
+ fh->Seek((int32_t)(sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER)), SEEK_CUR);
+ }
+ break;
+ default:
+ //give a last chance
+ if (pdib->biSize>(sizeof(BITMAPINFOHEADER))&&
+ (pdib->biSizeImage>=(uint32_t)(pdib->biHeight*((((pdib->biBitCount*pdib->biWidth)+31)/32)*4)))&&
+ (pdib->biPlanes==1)&&(pdib->biClrUsed==0))
+ {
+ if (pdib->biCompression==BI_RGB)
+ fh->Seek((int32_t)(pdib->biSize - sizeof(BITMAPINFOHEADER)),SEEK_CUR);
+ break;
+ }
+ return false;
+ }
+
+ FixBitmapInfo(pdib);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_BMP
+////////////////////////////////////////////////////////////////////////////////
diff --git a/archive/hge/CxImage/ximabmp.h b/archive/hge/CxImage/ximabmp.h new file mode 100644 index 0000000..c828de5 --- /dev/null +++ b/archive/hge/CxImage/ximabmp.h @@ -0,0 +1,79 @@ +/*
+ * File: ximabmp.h
+ * Purpose: BMP Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageBMP (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes
+ *
+ * original CImageBMP and CImageIterator implementation are:
+ * Copyright: (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>
+ *
+ * ==========================================================
+ */
+
+#if !defined(__ximaBMP_h)
+#define __ximaBMP_h
+
+#include "ximage.h"
+
+const int32_t RLE_COMMAND = 0;
+const int32_t RLE_ENDOFLINE = 0;
+const int32_t RLE_ENDOFBITMAP = 1;
+const int32_t RLE_DELTA = 2;
+
+#if !defined(BI_RLE8)
+ #define BI_RLE8 1L
+#endif
+#if !defined(BI_RLE4)
+ #define BI_RLE4 2L
+#endif
+
+#if CXIMAGE_SUPPORT_BMP
+
+class CxImageBMP: public CxImage
+{
+public:
+ CxImageBMP(): CxImage(CXIMAGE_FORMAT_BMP) {};
+
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+protected:
+ bool DibReadBitmapInfo(CxFile* fh, BITMAPINFOHEADER *pdib);
+};
+
+#define BFT_ICON 0x4349 /* 'IC' */
+#define BFT_BITMAP 0x4d42 /* 'BM' */
+#define BFT_CURSOR 0x5450 /* 'PT' */
+
+#ifndef WIDTHBYTES
+#define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
+#endif
+
+#endif
+
+#define DibWidthBytesN(lpbi, n) (uint32_t)WIDTHBYTES((uint32_t)(lpbi)->biWidth * (uint32_t)(n))
+#define DibWidthBytes(lpbi) DibWidthBytesN(lpbi, (lpbi)->biBitCount)
+
+#define DibSizeImage(lpbi) ((lpbi)->biSizeImage == 0 \
+ ? ((uint32_t)(uint32_t)DibWidthBytes(lpbi) * (uint32_t)(uint32_t)(lpbi)->biHeight) \
+ : (lpbi)->biSizeImage)
+
+#define DibNumColors(lpbi) ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
+ ? (int32_t)(1 << (int32_t)(lpbi)->biBitCount) \
+ : (int32_t)(lpbi)->biClrUsed)
+
+#define FixBitmapInfo(lpbi) if ((lpbi)->biSizeImage == 0) \
+ (lpbi)->biSizeImage = DibSizeImage(lpbi); \
+ if ((lpbi)->biClrUsed == 0) \
+ (lpbi)->biClrUsed = DibNumColors(lpbi); \
+
+#endif
diff --git a/archive/hge/CxImage/ximacfg.h b/archive/hge/CxImage/ximacfg.h new file mode 100644 index 0000000..875f517 --- /dev/null +++ b/archive/hge/CxImage/ximacfg.h @@ -0,0 +1,59 @@ +#if !defined(__ximaCFG_h)
+#define __ximaCFG_h
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported features
+#define CXIMAGE_SUPPORT_ALPHA 1
+#define CXIMAGE_SUPPORT_SELECTION 0
+#define CXIMAGE_SUPPORT_TRANSFORMATION 1
+#define CXIMAGE_SUPPORT_DSP 0
+#define CXIMAGE_SUPPORT_LAYERS 0
+#define CXIMAGE_SUPPORT_INTERPOLATION 1
+
+#define CXIMAGE_SUPPORT_DECODE 1
+#define CXIMAGE_SUPPORT_ENCODE 0 //<vho><T.Peck>
+#define CXIMAGE_SUPPORT_WINDOWS 0
+#define CXIMAGE_SUPPORT_EXIF 0
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported formats
+#define CXIMAGE_SUPPORT_BMP 1
+#define CXIMAGE_SUPPORT_GIF 1
+#define CXIMAGE_SUPPORT_JPG 1
+#define CXIMAGE_SUPPORT_PNG 1
+#define CXIMAGE_SUPPORT_ICO 0
+#define CXIMAGE_SUPPORT_TIF 0
+#define CXIMAGE_SUPPORT_TGA 0
+#define CXIMAGE_SUPPORT_PCX 1
+#define CXIMAGE_SUPPORT_WBMP 0
+#define CXIMAGE_SUPPORT_WMF 0
+
+#define CXIMAGE_SUPPORT_JP2 0
+#define CXIMAGE_SUPPORT_JPC 0
+#define CXIMAGE_SUPPORT_PGX 0
+#define CXIMAGE_SUPPORT_PNM 0
+#define CXIMAGE_SUPPORT_RAS 0
+
+#define CXIMAGE_SUPPORT_JBG 0 // GPL'd see ../jbig/copying.txt & ../jbig/patents.htm
+
+#define CXIMAGE_SUPPORT_MNG 0
+#define CXIMAGE_SUPPORT_SKA 0
+#define CXIMAGE_SUPPORT_RAW 0
+#define CXIMAGE_SUPPORT_PSD 0
+
+/////////////////////////////////////////////////////////////////////////////
+#define CXIMAGE_MAX_MEMORY 268435456
+
+#define CXIMAGE_DEFAULT_DPI 96
+
+#define CXIMAGE_ERR_NOFILE "null file handler"
+#define CXIMAGE_ERR_NOIMAGE "null image!!!"
+
+//#define CXIMAGE_SUPPORT_EXCEPTION_HANDLING 1
+//!!Uncomment the last line when releasing
+/////////////////////////////////////////////////////////////////////////////
+//color to grey mapping <H. Muelner> <jurgene>
+//#define RGB2GRAY(r,g,b) (((b)*114 + (g)*587 + (r)*299)/1000)
+#define RGB2GRAY(r,g,b) (((b)*117 + (g)*601 + (r)*306) >> 10)
+
+#endif
diff --git a/archive/hge/CxImage/ximadef.h b/archive/hge/CxImage/ximadef.h new file mode 100644 index 0000000..372ec13 --- /dev/null +++ b/archive/hge/CxImage/ximadef.h @@ -0,0 +1,205 @@ +#if !defined(__ximadefs_h)
+#define __ximadefs_h
+
+#include "ximacfg.h"
+
+#if /*defined(_AFXDLL)||*/defined(_USRDLL)
+ #define DLL_EXP __declspec(dllexport)
+#elif defined(_MSC_VER)&&(_MSC_VER<1200)
+ #define DLL_EXP __declspec(dllimport)
+#else
+ #define DLL_EXP
+#endif
+
+
+#if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+ #define cx_try try
+ #define cx_throw(message) throw(message)
+ #define cx_catch catch (const char *message)
+#else
+ #define cx_try bool cx_error=false;
+ #define cx_throw(message) {cx_error=true; if(strcmp(message,"")) strncpy(info.szLastError,message,255); goto cx_error_catch;}
+ #define cx_catch cx_error_catch: char message[]=""; if(cx_error)
+#endif
+
+
+#if CXIMAGE_SUPPORT_JP2 || CXIMAGE_SUPPORT_JPC || CXIMAGE_SUPPORT_PGX || CXIMAGE_SUPPORT_PNM || CXIMAGE_SUPPORT_RAS
+ #define CXIMAGE_SUPPORT_JASPER 1
+#else
+ #define CXIMAGE_SUPPORT_JASPER 0
+#endif
+
+#if CXIMAGE_SUPPORT_DSP
+#undef CXIMAGE_SUPPORT_TRANSFORMATION
+ #define CXIMAGE_SUPPORT_TRANSFORMATION 1
+#endif
+
+#if CXIMAGE_SUPPORT_TRANSFORMATION || CXIMAGE_SUPPORT_TIF || CXIMAGE_SUPPORT_TGA || CXIMAGE_SUPPORT_BMP || CXIMAGE_SUPPORT_WINDOWS
+ #define CXIMAGE_SUPPORT_BASICTRANSFORMATIONS 1
+#endif
+
+#if CXIMAGE_SUPPORT_DSP || CXIMAGE_SUPPORT_TRANSFORMATION
+#undef CXIMAGE_SUPPORT_INTERPOLATION
+ #define CXIMAGE_SUPPORT_INTERPOLATION 1
+#endif
+
+#if defined (_WIN32_WCE)
+ #undef CXIMAGE_SUPPORT_WMF
+ #define CXIMAGE_SUPPORT_WMF 0
+#endif
+
+#if !defined(WIN32) && !defined(_WIN32_WCE)
+ #undef CXIMAGE_SUPPORT_WINDOWS
+ #define CXIMAGE_SUPPORT_WINDOWS 0
+#endif
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#ifndef PI
+ #define PI 3.141592653589793f
+#endif
+
+
+#if defined(WIN32) || defined(_WIN32_WCE)
+#include <windows.h>
+#include <tchar.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+
+#ifdef __BORLANDC__
+
+#ifndef _COMPLEX_DEFINED
+
+typedef struct tagcomplex {
+ double x,y;
+} _complex;
+
+#endif
+
+#define _cabs(c) sqrt(c.x*c.x+c.y*c.y)
+
+#endif
+
+#if defined(WIN32) || defined(_WIN32_WCE)
+ #include "stdint.h"
+#endif
+
+#if !defined(WIN32) && !defined(_WIN32_WCE)
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+typedef uint32_t COLORREF;
+typedef void* HANDLE;
+typedef void* HRGN;
+
+#ifndef BOOL
+#define BOOL bool
+#endif
+
+#ifndef TRUE
+#define TRUE true
+#endif
+
+#ifndef FALSE
+#define FALSE false
+#endif
+
+#ifndef TCHAR
+#define TCHAR char
+#define _T
+#endif
+
+typedef struct tagRECT
+{
+ int32_t left;
+ int32_t top;
+ int32_t right;
+ int32_t bottom;
+} RECT;
+
+typedef struct tagPOINT
+{
+ int32_t x;
+ int32_t y;
+} POINT;
+
+typedef struct tagRGBQUAD {
+ uint8_t rgbBlue;
+ uint8_t rgbGreen;
+ uint8_t rgbRed;
+ uint8_t rgbReserved;
+} RGBQUAD;
+
+#pragma pack(1)
+
+typedef struct tagBITMAPINFOHEADER{
+ uint32_t biSize;
+ int32_t biWidth;
+ int32_t biHeight;
+ uint16_t biPlanes;
+ uint16_t biBitCount;
+ uint32_t biCompression;
+ uint32_t biSizeImage;
+ int32_t biXPelsPerMeter;
+ int32_t biYPelsPerMeter;
+ uint32_t biClrUsed;
+ uint32_t biClrImportant;
+} BITMAPINFOHEADER;
+
+typedef struct tagBITMAPFILEHEADER {
+ uint16_t bfType;
+ uint32_t bfSize;
+ uint16_t bfReserved1;
+ uint16_t bfReserved2;
+ uint32_t bfOffBits;
+} BITMAPFILEHEADER;
+
+typedef struct tagBITMAPCOREHEADER {
+ uint32_t bcSize;
+ uint16_t bcWidth;
+ uint16_t bcHeight;
+ uint16_t bcPlanes;
+ uint16_t bcBitCount;
+} BITMAPCOREHEADER;
+
+typedef struct tagRGBTRIPLE {
+ uint8_t rgbtBlue;
+ uint8_t rgbtGreen;
+ uint8_t rgbtRed;
+} RGBTRIPLE;
+
+#pragma pack()
+
+#define BI_RGB 0L
+#define BI_RLE8 1L
+#define BI_RLE4 2L
+#define BI_BITFIELDS 3L
+
+#define GetRValue(rgb) ((uint8_t)(rgb))
+#define GetGValue(rgb) ((uint8_t)(((uint16_t)(rgb)) >> 8))
+#define GetBValue(rgb) ((uint8_t)((rgb)>>16))
+#define RGB(r,g,b) ((COLORREF)(((uint8_t)(r)|((uint16_t)((uint8_t)(g))<<8))|(((uint32_t)(uint8_t)(b))<<16)))
+
+#ifndef _COMPLEX_DEFINED
+
+typedef struct tagcomplex {
+ double x,y;
+} _complex;
+
+#endif
+
+#define _cabs(c) sqrt(c.x*c.x+c.y*c.y)
+
+#endif
+
+#endif //__ximadefs
diff --git a/archive/hge/CxImage/ximadsp.cpp b/archive/hge/CxImage/ximadsp.cpp new file mode 100644 index 0000000..df73136 --- /dev/null +++ b/archive/hge/CxImage/ximadsp.cpp @@ -0,0 +1,3771 @@ +// xImaDsp.cpp : DSP functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+#include "ximaiter.h"
+
+#if CXIMAGE_SUPPORT_DSP
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Converts the image to B&W.
+ * The OptimalThreshold() function can be used for calculating the optimal threshold.
+ * \param level: the lightness threshold.
+ * \return true if everything is ok
+ */
+bool CxImage::Threshold(uint8_t level)
+{
+ if (!pDib) return false;
+ if (head.biBitCount == 1) return true;
+
+ GrayScale();
+
+ CxImage tmp(head.biWidth,head.biHeight,1);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+ if (BlindGetPixelIndex(x,y)>level)
+ tmp.BlindSetPixelIndex(x,y,1);
+ else
+ tmp.BlindSetPixelIndex(x,y,0);
+ }
+ }
+ tmp.SetPaletteColor(0,0,0,0);
+ tmp.SetPaletteColor(1,255,255,255);
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Converts the image to B&W, using a threshold mask
+ * \param pThresholdMask: the lightness threshold mask.
+ * the pThresholdMask image must be grayscale with same with and height of the current image
+ * \return true if everything is ok
+ */
+bool CxImage::Threshold(CxImage* pThresholdMask)
+{
+ if (!pDib) return false;
+ if (head.biBitCount == 1) return true;
+
+ if (!pThresholdMask) return false;
+
+ if (!pThresholdMask->IsValid() ||
+ !pThresholdMask->IsGrayScale() ||
+ pThresholdMask->GetWidth() != GetWidth() ||
+ pThresholdMask->GetHeight() != GetHeight()){
+ strcpy(info.szLastError,"invalid ThresholdMask");
+ return false;
+ }
+
+ GrayScale();
+
+ CxImage tmp(head.biWidth,head.biHeight,1);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+ if (BlindGetPixelIndex(x,y)>pThresholdMask->BlindGetPixelIndex(x,y))
+ tmp.BlindSetPixelIndex(x,y,1);
+ else
+ tmp.BlindSetPixelIndex(x,y,0);
+ }
+ }
+ tmp.SetPaletteColor(0,0,0,0);
+ tmp.SetPaletteColor(1,255,255,255);
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Filters only the pixels with a lightness less (or more) than the threshold level,
+ * and preserves the colors for the unfiltered pixels.
+ * \param level = the lightness threshold.
+ * \param bDirection = false: filter dark pixels, true: filter light pixels
+ * \param nBkgndColor = filtered pixels are set to nBkgndColor color
+ * \param bSetAlpha = if true, sets also the alpha component for the filtered pixels, with nBkgndColor.rgbReserved
+ * \return true if everything is ok
+ * \author [DP], [wangsongtao]
+ */
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::Threshold2(uint8_t level, bool bDirection, RGBQUAD nBkgndColor, bool bSetAlpha)
+{
+ if (!pDib) return false;
+ if (head.biBitCount == 1) return true;
+
+ CxImage tmp(*this, true, false, false);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ tmp.GrayScale();
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ uint8_t i = tmp.BlindGetPixelIndex(x,y);
+ if (!bDirection && i<level) BlindSetPixelColor(x,y,nBkgndColor,bSetAlpha);
+ if (bDirection && i>=level) BlindSetPixelColor(x,y,nBkgndColor,bSetAlpha);
+ }
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract RGB channels from the image. Each channel is an 8 bit grayscale image.
+ * \param r,g,b: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitRGB(CxImage* r,CxImage* g,CxImage* b)
+{
+ if (!pDib) return false;
+ if (r==NULL && g==NULL && b==NULL) return false;
+
+ CxImage tmpr(head.biWidth,head.biHeight,8);
+ CxImage tmpg(head.biWidth,head.biHeight,8);
+ CxImage tmpb(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(int32_t y=0; y<head.biHeight; y++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ color = BlindGetPixelColor(x,y);
+ if (r) tmpr.BlindSetPixelIndex(x,y,color.rgbRed);
+ if (g) tmpg.BlindSetPixelIndex(x,y,color.rgbGreen);
+ if (b) tmpb.BlindSetPixelIndex(x,y,color.rgbBlue);
+ }
+ }
+
+ if (r) tmpr.SetGrayPalette();
+ if (g) tmpg.SetGrayPalette();
+ if (b) tmpb.SetGrayPalette();
+
+ /*for(int32_t j=0; j<256; j++){
+ uint8_t i=(uint8_t)j;
+ if (r) tmpr.SetPaletteColor(i,i,0,0);
+ if (g) tmpg.SetPaletteColor(i,0,i,0);
+ if (b) tmpb.SetPaletteColor(i,0,0,i);
+ }*/
+
+ if (r) r->Transfer(tmpr);
+ if (g) g->Transfer(tmpg);
+ if (b) b->Transfer(tmpb);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract CMYK channels from the image. Each channel is an 8 bit grayscale image.
+ * \param c,m,y,k: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitCMYK(CxImage* c,CxImage* m,CxImage* y,CxImage* k)
+{
+ if (!pDib) return false;
+ if (c==NULL && m==NULL && y==NULL && k==NULL) return false;
+
+ CxImage tmpc(head.biWidth,head.biHeight,8);
+ CxImage tmpm(head.biWidth,head.biHeight,8);
+ CxImage tmpy(head.biWidth,head.biHeight,8);
+ CxImage tmpk(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(int32_t yy=0; yy<head.biHeight; yy++){
+ for(int32_t xx=0; xx<head.biWidth; xx++){
+ color = BlindGetPixelColor(xx,yy);
+ if (c) tmpc.BlindSetPixelIndex(xx,yy,(uint8_t)(255-color.rgbRed));
+ if (m) tmpm.BlindSetPixelIndex(xx,yy,(uint8_t)(255-color.rgbGreen));
+ if (y) tmpy.BlindSetPixelIndex(xx,yy,(uint8_t)(255-color.rgbBlue));
+ if (k) tmpk.BlindSetPixelIndex(xx,yy,(uint8_t)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue));
+ }
+ }
+
+ if (c) tmpc.SetGrayPalette();
+ if (m) tmpm.SetGrayPalette();
+ if (y) tmpy.SetGrayPalette();
+ if (k) tmpk.SetGrayPalette();
+
+ if (c) c->Transfer(tmpc);
+ if (m) m->Transfer(tmpm);
+ if (y) y->Transfer(tmpy);
+ if (k) k->Transfer(tmpk);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract YUV channels from the image. Each channel is an 8 bit grayscale image.
+ * \param y,u,v: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitYUV(CxImage* y,CxImage* u,CxImage* v)
+{
+ if (!pDib) return false;
+ if (y==NULL && u==NULL && v==NULL) return false;
+
+ CxImage tmpy(head.biWidth,head.biHeight,8);
+ CxImage tmpu(head.biWidth,head.biHeight,8);
+ CxImage tmpv(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(int32_t yy=0; yy<head.biHeight; yy++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ color = RGBtoYUV(BlindGetPixelColor(x,yy));
+ if (y) tmpy.BlindSetPixelIndex(x,yy,color.rgbRed);
+ if (u) tmpu.BlindSetPixelIndex(x,yy,color.rgbGreen);
+ if (v) tmpv.BlindSetPixelIndex(x,yy,color.rgbBlue);
+ }
+ }
+
+ if (y) tmpy.SetGrayPalette();
+ if (u) tmpu.SetGrayPalette();
+ if (v) tmpv.SetGrayPalette();
+
+ if (y) y->Transfer(tmpy);
+ if (u) u->Transfer(tmpu);
+ if (v) v->Transfer(tmpv);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract YIQ channels from the image. Each channel is an 8 bit grayscale image.
+ * \param y,i,q: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitYIQ(CxImage* y,CxImage* i,CxImage* q)
+{
+ if (!pDib) return false;
+ if (y==NULL && i==NULL && q==NULL) return false;
+
+ CxImage tmpy(head.biWidth,head.biHeight,8);
+ CxImage tmpi(head.biWidth,head.biHeight,8);
+ CxImage tmpq(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(int32_t yy=0; yy<head.biHeight; yy++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ color = RGBtoYIQ(BlindGetPixelColor(x,yy));
+ if (y) tmpy.BlindSetPixelIndex(x,yy,color.rgbRed);
+ if (i) tmpi.BlindSetPixelIndex(x,yy,color.rgbGreen);
+ if (q) tmpq.BlindSetPixelIndex(x,yy,color.rgbBlue);
+ }
+ }
+
+ if (y) tmpy.SetGrayPalette();
+ if (i) tmpi.SetGrayPalette();
+ if (q) tmpq.SetGrayPalette();
+
+ if (y) y->Transfer(tmpy);
+ if (i) i->Transfer(tmpi);
+ if (q) q->Transfer(tmpq);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract XYZ channels from the image. Each channel is an 8 bit grayscale image.
+ * \param x,y,z: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitXYZ(CxImage* x,CxImage* y,CxImage* z)
+{
+ if (!pDib) return false;
+ if (x==NULL && y==NULL && z==NULL) return false;
+
+ CxImage tmpx(head.biWidth,head.biHeight,8);
+ CxImage tmpy(head.biWidth,head.biHeight,8);
+ CxImage tmpz(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(int32_t yy=0; yy<head.biHeight; yy++){
+ for(int32_t xx=0; xx<head.biWidth; xx++){
+ color = RGBtoXYZ(BlindGetPixelColor(xx,yy));
+ if (x) tmpx.BlindSetPixelIndex(xx,yy,color.rgbRed);
+ if (y) tmpy.BlindSetPixelIndex(xx,yy,color.rgbGreen);
+ if (z) tmpz.BlindSetPixelIndex(xx,yy,color.rgbBlue);
+ }
+ }
+
+ if (x) tmpx.SetGrayPalette();
+ if (y) tmpy.SetGrayPalette();
+ if (z) tmpz.SetGrayPalette();
+
+ if (x) x->Transfer(tmpx);
+ if (y) y->Transfer(tmpy);
+ if (z) z->Transfer(tmpz);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Extract HSL channels from the image. Each channel is an 8 bit grayscale image.
+ * \param h,s,l: pointers to CxImage objects, to store the splited channels
+ * \return true if everything is ok
+ */
+bool CxImage::SplitHSL(CxImage* h,CxImage* s,CxImage* l)
+{
+ if (!pDib) return false;
+ if (h==NULL && s==NULL && l==NULL) return false;
+
+ CxImage tmph(head.biWidth,head.biHeight,8);
+ CxImage tmps(head.biWidth,head.biHeight,8);
+ CxImage tmpl(head.biWidth,head.biHeight,8);
+
+ RGBQUAD color;
+ for(int32_t y=0; y<head.biHeight; y++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ color = RGBtoHSL(BlindGetPixelColor(x,y));
+ if (h) tmph.BlindSetPixelIndex(x,y,color.rgbRed);
+ if (s) tmps.BlindSetPixelIndex(x,y,color.rgbGreen);
+ if (l) tmpl.BlindSetPixelIndex(x,y,color.rgbBlue);
+ }
+ }
+
+ if (h) tmph.SetGrayPalette();
+ if (s) tmps.SetGrayPalette();
+ if (l) tmpl.SetGrayPalette();
+
+ /* pseudo-color generator for hue channel (visual debug)
+ if (h) for(int32_t j=0; j<256; j++){
+ uint8_t i=(uint8_t)j;
+ RGBQUAD hsl={120,240,i,0};
+ tmph.SetPaletteColor(i,HSLtoRGB(hsl));
+ }*/
+
+ if (h) h->Transfer(tmph);
+ if (s) s->Transfer(tmps);
+ if (l) l->Transfer(tmpl);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#define HSLMAX 255 /* H,L, and S vary over 0-HSLMAX */
+#define RGBMAX 255 /* R,G, and B vary over 0-RGBMAX */
+ /* HSLMAX BEST IF DIVISIBLE BY 6 */
+ /* RGBMAX, HSLMAX must each fit in a uint8_t. */
+/* Hue is undefined if Saturation is 0 (grey-scale) */
+/* This value determines where the Hue scrollbar is */
+/* initially set for achromatic colors */
+#define HSLUNDEFINED (HSLMAX*2/3)
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoHSL(RGBQUAD lRGBColor)
+{
+ uint8_t R,G,B; /* input RGB values */
+ uint8_t H,L,S; /* output HSL values */
+ uint8_t cMax,cMin; /* max and min RGB values */
+ uint16_t Rdelta,Gdelta,Bdelta; /* intermediate value: % of spread from max*/
+
+ R = lRGBColor.rgbRed; /* get R, G, and B out of uint32_t */
+ G = lRGBColor.rgbGreen;
+ B = lRGBColor.rgbBlue;
+
+ cMax = max( max(R,G), B); /* calculate lightness */
+ cMin = min( min(R,G), B);
+ L = (uint8_t)((((cMax+cMin)*HSLMAX)+RGBMAX)/(2*RGBMAX));
+
+ if (cMax==cMin){ /* r=g=b --> achromatic case */
+ S = 0; /* saturation */
+ H = HSLUNDEFINED; /* hue */
+ } else { /* chromatic case */
+ if (L <= (HSLMAX/2)) /* saturation */
+ S = (uint8_t)((((cMax-cMin)*HSLMAX)+((cMax+cMin)/2))/(cMax+cMin));
+ else
+ S = (uint8_t)((((cMax-cMin)*HSLMAX)+((2*RGBMAX-cMax-cMin)/2))/(2*RGBMAX-cMax-cMin));
+ /* hue */
+ Rdelta = (uint16_t)((((cMax-R)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));
+ Gdelta = (uint16_t)((((cMax-G)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));
+ Bdelta = (uint16_t)((((cMax-B)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));
+
+ if (R == cMax)
+ H = (uint8_t)(Bdelta - Gdelta);
+ else if (G == cMax)
+ H = (uint8_t)((HSLMAX/3) + Rdelta - Bdelta);
+ else /* B == cMax */
+ H = (uint8_t)(((2*HSLMAX)/3) + Gdelta - Rdelta);
+
+// if (H < 0) H += HSLMAX; //always false
+ if (H > HSLMAX) H -= HSLMAX;
+ }
+ RGBQUAD hsl={L,S,H,0};
+ return hsl;
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::HueToRGB(float n1,float n2, float hue)
+{
+ //<F. Livraghi> fixed implementation for HSL2RGB routine
+ float rValue;
+
+ if (hue > 360)
+ hue = hue - 360;
+ else if (hue < 0)
+ hue = hue + 360;
+
+ if (hue < 60)
+ rValue = n1 + (n2-n1)*hue/60.0f;
+ else if (hue < 180)
+ rValue = n2;
+ else if (hue < 240)
+ rValue = n1+(n2-n1)*(240-hue)/60;
+ else
+ rValue = n1;
+
+ return rValue;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::HSLtoRGB(COLORREF cHSLColor)
+{
+ return HSLtoRGB(RGBtoRGBQUAD(cHSLColor));
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::HSLtoRGB(RGBQUAD lHSLColor)
+{
+ //<F. Livraghi> fixed implementation for HSL2RGB routine
+ float h,s,l;
+ float m1,m2;
+ uint8_t r,g,b;
+
+ h = (float)lHSLColor.rgbRed * 360.0f/255.0f;
+ s = (float)lHSLColor.rgbGreen/255.0f;
+ l = (float)lHSLColor.rgbBlue/255.0f;
+
+ if (l <= 0.5) m2 = l * (1+s);
+ else m2 = l + s - l*s;
+
+ m1 = 2 * l - m2;
+
+ if (s == 0) {
+ r=g=b=(uint8_t)(l*255.0f);
+ } else {
+ r = (uint8_t)(HueToRGB(m1,m2,h+120) * 255.0f);
+ g = (uint8_t)(HueToRGB(m1,m2,h) * 255.0f);
+ b = (uint8_t)(HueToRGB(m1,m2,h-120) * 255.0f);
+ }
+
+ RGBQUAD rgb = {b,g,r,0};
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::YUVtoRGB(RGBQUAD lYUVColor)
+{
+ int32_t U,V,R,G,B;
+ float Y = lYUVColor.rgbRed;
+ U = lYUVColor.rgbGreen - 128;
+ V = lYUVColor.rgbBlue - 128;
+
+// R = (int32_t)(1.164 * Y + 2.018 * U);
+// G = (int32_t)(1.164 * Y - 0.813 * V - 0.391 * U);
+// B = (int32_t)(1.164 * Y + 1.596 * V);
+ R = (int32_t)( Y + 1.403f * V);
+ G = (int32_t)( Y - 0.344f * U - 0.714f * V);
+ B = (int32_t)( Y + 1.770f * U);
+
+ R= min(255,max(0,R));
+ G= min(255,max(0,G));
+ B= min(255,max(0,B));
+ RGBQUAD rgb={(uint8_t)B,(uint8_t)G,(uint8_t)R,0};
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoYUV(RGBQUAD lRGBColor)
+{
+ int32_t Y,U,V,R,G,B;
+ R = lRGBColor.rgbRed;
+ G = lRGBColor.rgbGreen;
+ B = lRGBColor.rgbBlue;
+
+// Y = (int32_t)( 0.257 * R + 0.504 * G + 0.098 * B);
+// U = (int32_t)( 0.439 * R - 0.368 * G - 0.071 * B + 128);
+// V = (int32_t)(-0.148 * R - 0.291 * G + 0.439 * B + 128);
+ Y = (int32_t)(0.299f * R + 0.587f * G + 0.114f * B);
+ U = (int32_t)((B-Y) * 0.565f + 128);
+ V = (int32_t)((R-Y) * 0.713f + 128);
+
+ Y= min(255,max(0,Y));
+ U= min(255,max(0,U));
+ V= min(255,max(0,V));
+ RGBQUAD yuv={(uint8_t)V,(uint8_t)U,(uint8_t)Y,0};
+ return yuv;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::YIQtoRGB(RGBQUAD lYIQColor)
+{
+ int32_t I,Q,R,G,B;
+ float Y = lYIQColor.rgbRed;
+ I = lYIQColor.rgbGreen - 128;
+ Q = lYIQColor.rgbBlue - 128;
+
+ R = (int32_t)( Y + 0.956f * I + 0.621f * Q);
+ G = (int32_t)( Y - 0.273f * I - 0.647f * Q);
+ B = (int32_t)( Y - 1.104f * I + 1.701f * Q);
+
+ R= min(255,max(0,R));
+ G= min(255,max(0,G));
+ B= min(255,max(0,B));
+ RGBQUAD rgb={(uint8_t)B,(uint8_t)G,(uint8_t)R,0};
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoYIQ(RGBQUAD lRGBColor)
+{
+ int32_t Y,I,Q,R,G,B;
+ R = lRGBColor.rgbRed;
+ G = lRGBColor.rgbGreen;
+ B = lRGBColor.rgbBlue;
+
+ Y = (int32_t)( 0.2992f * R + 0.5868f * G + 0.1140f * B);
+ I = (int32_t)( 0.5960f * R - 0.2742f * G - 0.3219f * B + 128);
+ Q = (int32_t)( 0.2109f * R - 0.5229f * G + 0.3120f * B + 128);
+
+ Y= min(255,max(0,Y));
+ I= min(255,max(0,I));
+ Q= min(255,max(0,Q));
+ RGBQUAD yiq={(uint8_t)Q,(uint8_t)I,(uint8_t)Y,0};
+ return yiq;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::XYZtoRGB(RGBQUAD lXYZColor)
+{
+ int32_t X,Y,Z,R,G,B;
+ X = lXYZColor.rgbRed;
+ Y = lXYZColor.rgbGreen;
+ Z = lXYZColor.rgbBlue;
+ double k=1.088751;
+
+ R = (int32_t)( 3.240479f * X - 1.537150f * Y - 0.498535f * Z * k);
+ G = (int32_t)( -0.969256f * X + 1.875992f * Y + 0.041556f * Z * k);
+ B = (int32_t)( 0.055648f * X - 0.204043f * Y + 1.057311f * Z * k);
+
+ R= min(255,max(0,R));
+ G= min(255,max(0,G));
+ B= min(255,max(0,B));
+ RGBQUAD rgb={(uint8_t)B,(uint8_t)G,(uint8_t)R,0};
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoXYZ(RGBQUAD lRGBColor)
+{
+ int32_t X,Y,Z,R,G,B;
+ R = lRGBColor.rgbRed;
+ G = lRGBColor.rgbGreen;
+ B = lRGBColor.rgbBlue;
+
+ X = (int32_t)( 0.412453f * R + 0.357580f * G + 0.180423f * B);
+ Y = (int32_t)( 0.212671f * R + 0.715160f * G + 0.072169f * B);
+ Z = (int32_t)((0.019334f * R + 0.119193f * G + 0.950227f * B)*0.918483657f);
+
+ //X= min(255,max(0,X));
+ //Y= min(255,max(0,Y));
+ //Z= min(255,max(0,Z));
+ RGBQUAD xyz={(uint8_t)Z,(uint8_t)Y,(uint8_t)X,0};
+ return xyz;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Generates a "rainbow" palette with saturated colors
+ * \param correction: 1 generates a single hue spectrum. 0.75 is nice for scientific applications.
+ */
+void CxImage::HuePalette(float correction)
+{
+ if (head.biClrUsed==0) return;
+
+ for(uint32_t j=0; j<head.biClrUsed; j++){
+ uint8_t i=(uint8_t)(j*correction*(255/(head.biClrUsed-1)));
+ RGBQUAD hsl={120,240,i,0};
+ SetPaletteColor((uint8_t)j,HSLtoRGB(hsl));
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Replaces the original hue and saturation values.
+ * \param hue: hue
+ * \param sat: saturation
+ * \param blend: can be from 0 (no effect) to 1 (full effect)
+ * \return true if everything is ok
+ */
+bool CxImage::Colorize(uint8_t hue, uint8_t sat, float blend)
+{
+ if (!pDib) return false;
+
+ if (blend < 0.0f) blend = 0.0f;
+ if (blend > 1.0f) blend = 1.0f;
+ int32_t a0 = (int32_t)(256*blend);
+ int32_t a1 = 256 - a0;
+
+ bool bFullBlend = false;
+ if (blend > 0.999f) bFullBlend = true;
+
+ RGBQUAD color,hsl;
+ if (head.biClrUsed==0){
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ if (bFullBlend){
+ color = RGBtoHSL(BlindGetPixelColor(x,y));
+ color.rgbRed=hue;
+ color.rgbGreen=sat;
+ BlindSetPixelColor(x,y,HSLtoRGB(color));
+ } else {
+ color = BlindGetPixelColor(x,y);
+ hsl.rgbRed=hue;
+ hsl.rgbGreen=sat;
+ hsl.rgbBlue = (uint8_t)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);
+ hsl = HSLtoRGB(hsl);
+ //BlendPixelColor(x,y,hsl,blend);
+ //color.rgbRed = (uint8_t)(hsl.rgbRed * blend + color.rgbRed * (1.0f - blend));
+ //color.rgbBlue = (uint8_t)(hsl.rgbBlue * blend + color.rgbBlue * (1.0f - blend));
+ //color.rgbGreen = (uint8_t)(hsl.rgbGreen * blend + color.rgbGreen * (1.0f - blend));
+ color.rgbRed = (uint8_t)((hsl.rgbRed * a0 + color.rgbRed * a1)>>8);
+ color.rgbBlue = (uint8_t)((hsl.rgbBlue * a0 + color.rgbBlue * a1)>>8);
+ color.rgbGreen = (uint8_t)((hsl.rgbGreen * a0 + color.rgbGreen * a1)>>8);
+ BlindSetPixelColor(x,y,color);
+ }
+ }
+ }
+ }
+ } else {
+ for(uint32_t j=0; j<head.biClrUsed; j++){
+ if (bFullBlend){
+ color = RGBtoHSL(GetPaletteColor((uint8_t)j));
+ color.rgbRed=hue;
+ color.rgbGreen=sat;
+ SetPaletteColor((uint8_t)j,HSLtoRGB(color));
+ } else {
+ color = GetPaletteColor((uint8_t)j);
+ hsl.rgbRed=hue;
+ hsl.rgbGreen=sat;
+ hsl.rgbBlue = (uint8_t)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);
+ hsl = HSLtoRGB(hsl);
+ color.rgbRed = (uint8_t)(hsl.rgbRed * blend + color.rgbRed * (1.0f - blend));
+ color.rgbBlue = (uint8_t)(hsl.rgbBlue * blend + color.rgbBlue * (1.0f - blend));
+ color.rgbGreen = (uint8_t)(hsl.rgbGreen * blend + color.rgbGreen * (1.0f - blend));
+ SetPaletteColor((uint8_t)j,color);
+ }
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Changes the brightness and the contrast of the image.
+ * \param brightness: can be from -255 to 255, if brightness is negative, the image becomes dark.
+ * \param contrast: can be from -100 to 100, the neutral value is 0.
+ * \return true if everything is ok
+ */
+bool CxImage::Light(int32_t brightness, int32_t contrast)
+{
+ if (!pDib) return false;
+ float c=(100 + contrast)/100.0f;
+ brightness+=128;
+
+ uint8_t cTable[256]; //<nipper>
+ for (int32_t i=0;i<256;i++) {
+ cTable[i] = (uint8_t)max(0,min(255,(int32_t)((i-128)*c + brightness + 0.5f)));
+ }
+
+ return Lut(cTable);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return mean lightness of the image. Useful with Threshold() and Light()
+ */
+float CxImage::Mean()
+{
+ if (!pDib) return 0;
+
+ CxImage tmp(*this,true);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ tmp.GrayScale();
+ float sum=0;
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+ if (xmin==xmax || ymin==ymax) return (float)0.0;
+
+ uint8_t *iSrc=tmp.info.pImage;
+ iSrc += tmp.info.dwEffWidth*ymin; // necessary for selections <Admir Hodzic>
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin)); //<zhanghk><Anatoly Ivasyuk>
+ for(int32_t x=xmin; x<xmax; x++){
+ sum+=iSrc[x];
+ }
+ iSrc+=tmp.info.dwEffWidth;
+ }
+ return sum/(xmax-xmin)/(ymax-ymin);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * 2D linear filter
+ * \param kernel: convolving matrix, in row format.
+ * \param Ksize: size of the kernel.
+ * \param Kfactor: normalization constant.
+ * \param Koffset: bias.
+ * \verbatim Example: the "soften" filter uses this kernel:
+ 1 1 1
+ 1 8 1
+ 1 1 1
+ the function needs: kernel={1,1,1,1,8,1,1,1,1}; Ksize=3; Kfactor=16; Koffset=0; \endverbatim
+ * \return true if everything is ok
+ */
+bool CxImage::Filter(int32_t* kernel, int32_t Ksize, int32_t Kfactor, int32_t Koffset)
+{
+ if (!pDib) return false;
+
+ int32_t k2 = Ksize/2;
+ int32_t kmax= Ksize-k2;
+ int32_t r,g,b,i;
+ int32_t ksumcur,ksumtot;
+ RGBQUAD c;
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ ksumtot = 0;
+ for(int32_t j=-k2;j<kmax;j++){
+ for(int32_t k=-k2;k<kmax;k++){
+ ksumtot += kernel[(j+k2)+Ksize*(k+k2)];
+ }
+ }
+
+ if ((head.biBitCount==8) && IsGrayScale())
+ {
+ uint8_t* cPtr;
+ uint8_t* cPtr2;
+ int32_t iCount;
+ int32_t iY, iY2, iY1;
+ cPtr = info.pImage;
+ cPtr2 = (uint8_t *)tmp.info.pImage;
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ iY1 = y*info.dwEffWidth+xmin;
+ for(int32_t x=xmin; x<xmax; x++, iY1++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ b=ksumcur=0;
+ iCount = 0;
+ iY2 = ((y-k2)*info.dwEffWidth);
+ for(int32_t j=-k2;j<kmax;j++, iY2+=info.dwEffWidth)
+ {
+ if (0>(y+j) || (y+j)>=head.biHeight) continue;
+ iY = iY2+x;
+ for(int32_t k=-k2;k<kmax;k++, iCount++)
+ {
+ if (0>(x+k) || (x+k)>=head.biWidth) continue;
+ i=kernel[iCount];
+ b += cPtr[iY+k] * i;
+ ksumcur += i;
+ }
+ }
+ if (Kfactor==0 || ksumcur==0){
+ cPtr2[iY1] = (uint8_t)min(255, max(0,(int32_t)(b + Koffset)));
+ } else if (ksumtot == ksumcur) {
+ cPtr2[iY1] = (uint8_t)min(255, max(0,(int32_t)(b/Kfactor + Koffset)));
+ } else {
+ cPtr2[iY1] = (uint8_t)min(255, max(0,(int32_t)((b*ksumtot)/(ksumcur*Kfactor) + Koffset)));
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+ #if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+ #endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ r=b=g=ksumcur=0;
+ for(int32_t j=-k2;j<kmax;j++){
+ for(int32_t k=-k2;k<kmax;k++){
+ if (!IsInside(x+j,y+k)) continue;
+ c = BlindGetPixelColor(x+j,y+k);
+ i = kernel[(j+k2)+Ksize*(k+k2)];
+ r += c.rgbRed * i;
+ g += c.rgbGreen * i;
+ b += c.rgbBlue * i;
+ ksumcur += i;
+ }
+ }
+ if (Kfactor==0 || ksumcur==0){
+ c.rgbRed = (uint8_t)min(255, max(0,(int32_t)(r + Koffset)));
+ c.rgbGreen = (uint8_t)min(255, max(0,(int32_t)(g + Koffset)));
+ c.rgbBlue = (uint8_t)min(255, max(0,(int32_t)(b + Koffset)));
+ } else if (ksumtot == ksumcur) {
+ c.rgbRed = (uint8_t)min(255, max(0,(int32_t)(r/Kfactor + Koffset)));
+ c.rgbGreen = (uint8_t)min(255, max(0,(int32_t)(g/Kfactor + Koffset)));
+ c.rgbBlue = (uint8_t)min(255, max(0,(int32_t)(b/Kfactor + Koffset)));
+ } else {
+ c.rgbRed = (uint8_t)min(255, max(0,(int32_t)((r*ksumtot)/(ksumcur*Kfactor) + Koffset)));
+ c.rgbGreen = (uint8_t)min(255, max(0,(int32_t)((g*ksumtot)/(ksumcur*Kfactor) + Koffset)));
+ c.rgbBlue = (uint8_t)min(255, max(0,(int32_t)((b*ksumtot)/(ksumcur*Kfactor) + Koffset)));
+ }
+ tmp.BlindSetPixelColor(x,y,c);
+ }
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enhance the dark areas of the image
+ * \param Ksize: size of the kernel.
+ * \return true if everything is ok
+ */
+bool CxImage::Erode(int32_t Ksize)
+{
+ if (!pDib) return false;
+
+ int32_t k2 = Ksize/2;
+ int32_t kmax= Ksize-k2;
+ uint8_t r,g,b;
+ RGBQUAD c;
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ r=b=g=255;
+ for(int32_t j=-k2;j<kmax;j++){
+ for(int32_t k=-k2;k<kmax;k++){
+ if (!IsInside(x+j,y+k)) continue;
+ c = BlindGetPixelColor(x+j,y+k);
+ if (c.rgbRed < r) r=c.rgbRed;
+ if (c.rgbGreen < g) g=c.rgbGreen;
+ if (c.rgbBlue < b) b=c.rgbBlue;
+ }
+ }
+ c.rgbRed = r;
+ c.rgbGreen = g;
+ c.rgbBlue = b;
+ tmp.BlindSetPixelColor(x,y,c);
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enhance the light areas of the image
+ * \param Ksize: size of the kernel.
+ * \return true if everything is ok
+ */
+bool CxImage::Dilate(int32_t Ksize)
+{
+ if (!pDib) return false;
+
+ int32_t k2 = Ksize/2;
+ int32_t kmax= Ksize-k2;
+ uint8_t r,g,b;
+ RGBQUAD c;
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ r=b=g=0;
+ for(int32_t j=-k2;j<kmax;j++){
+ for(int32_t k=-k2;k<kmax;k++){
+ if (!IsInside(x+j,y+k)) continue;
+ c = BlindGetPixelColor(x+j,y+k);
+ if (c.rgbRed > r) r=c.rgbRed;
+ if (c.rgbGreen > g) g=c.rgbGreen;
+ if (c.rgbBlue > b) b=c.rgbBlue;
+ }
+ }
+ c.rgbRed = r;
+ c.rgbGreen = g;
+ c.rgbBlue = b;
+ tmp.BlindSetPixelColor(x,y,c);
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enhance the variations between adjacent pixels.
+ * Similar results can be achieved using Filter(),
+ * but the algorithms are different both in Edge() and in Contour().
+ * \param Ksize: size of the kernel.
+ * \return true if everything is ok
+ */
+bool CxImage::Edge(int32_t Ksize)
+{
+ if (!pDib) return false;
+
+ int32_t k2 = Ksize/2;
+ int32_t kmax= Ksize-k2;
+ uint8_t r,g,b,rr,gg,bb;
+ RGBQUAD c;
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ r=b=g=0;
+ rr=bb=gg=255;
+ for(int32_t j=-k2;j<kmax;j++){
+ for(int32_t k=-k2;k<kmax;k++){
+ if (!IsInside(x+j,y+k)) continue;
+ c = BlindGetPixelColor(x+j,y+k);
+ if (c.rgbRed > r) r=c.rgbRed;
+ if (c.rgbGreen > g) g=c.rgbGreen;
+ if (c.rgbBlue > b) b=c.rgbBlue;
+
+ if (c.rgbRed < rr) rr=c.rgbRed;
+ if (c.rgbGreen < gg) gg=c.rgbGreen;
+ if (c.rgbBlue < bb) bb=c.rgbBlue;
+ }
+ }
+ c.rgbRed = (uint8_t)(255-abs(r-rr));
+ c.rgbGreen = (uint8_t)(255-abs(g-gg));
+ c.rgbBlue = (uint8_t)(255-abs(b-bb));
+ tmp.BlindSetPixelColor(x,y,c);
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Blends two images
+ * \param imgsrc2: image to be mixed with this
+ * \param op: blending method; see ImageOpType
+ * \param lXOffset, lYOffset: image displacement
+ * \param bMixAlpha: if true and imgsrc2 has a valid alpha layer, it will be mixed in the destination image.
+ * \return true if everything is ok
+ * \author [Mwolski],[brunom]
+ */
+void CxImage::Mix(CxImage & imgsrc2, ImageOpType op, int32_t lXOffset, int32_t lYOffset, bool bMixAlpha)
+{
+ int32_t lWide = min(GetWidth(),imgsrc2.GetWidth()-lXOffset);
+ int32_t lHeight = min(GetHeight(),imgsrc2.GetHeight()-lYOffset);
+
+ bool bEditAlpha = false;
+
+#if CXIMAGE_SUPPORT_ALPHA
+ bEditAlpha = imgsrc2.AlphaIsValid() & bMixAlpha;
+ if (bEditAlpha && AlphaIsValid()==false){
+ AlphaCreate();
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ RGBQUAD rgbBackgrnd1 = GetTransColor();
+ RGBQUAD rgb1, rgb2, rgbDest;
+
+ for(int32_t lY=0;lY<lHeight;lY++)
+ {
+ info.nProgress = (int32_t)(100*lY/head.biHeight);
+ if (info.nEscape) break;
+
+ for(int32_t lX=0;lX<lWide;lX++)
+ {
+#if CXIMAGE_SUPPORT_SELECTION
+ if (SelectionIsInside(lX,lY) && imgsrc2.SelectionIsInside(lX+lXOffset,lY+lYOffset))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ rgb1 = GetPixelColor(lX,lY);
+ rgb2 = imgsrc2.GetPixelColor(lX+lXOffset,lY+lYOffset);
+ switch(op)
+ {
+ case OpAvg:
+ rgbDest.rgbBlue = (uint8_t)((rgb1.rgbBlue+rgb2.rgbBlue)/2);
+ rgbDest.rgbGreen = (uint8_t)((rgb1.rgbGreen+rgb2.rgbGreen)/2);
+ rgbDest.rgbRed = (uint8_t)((rgb1.rgbRed+rgb2.rgbRed)/2);
+ if (bEditAlpha) rgbDest.rgbReserved = (uint8_t)((rgb1.rgbReserved+rgb2.rgbReserved)/2);
+ break;
+ case OpAdd:
+ rgbDest.rgbBlue = (uint8_t)max(0,min(255,rgb1.rgbBlue+rgb2.rgbBlue));
+ rgbDest.rgbGreen = (uint8_t)max(0,min(255,rgb1.rgbGreen+rgb2.rgbGreen));
+ rgbDest.rgbRed = (uint8_t)max(0,min(255,rgb1.rgbRed+rgb2.rgbRed));
+ if (bEditAlpha) rgbDest.rgbReserved = (uint8_t)max(0,min(255,rgb1.rgbReserved+rgb2.rgbReserved));
+ break;
+ case OpSub:
+ rgbDest.rgbBlue = (uint8_t)max(0,min(255,rgb1.rgbBlue-rgb2.rgbBlue));
+ rgbDest.rgbGreen = (uint8_t)max(0,min(255,rgb1.rgbGreen-rgb2.rgbGreen));
+ rgbDest.rgbRed = (uint8_t)max(0,min(255,rgb1.rgbRed-rgb2.rgbRed));
+ if (bEditAlpha) rgbDest.rgbReserved = (uint8_t)max(0,min(255,rgb1.rgbReserved-rgb2.rgbReserved));
+ break;
+ case OpAnd:
+ rgbDest.rgbBlue = (uint8_t)(rgb1.rgbBlue&rgb2.rgbBlue);
+ rgbDest.rgbGreen = (uint8_t)(rgb1.rgbGreen&rgb2.rgbGreen);
+ rgbDest.rgbRed = (uint8_t)(rgb1.rgbRed&rgb2.rgbRed);
+ if (bEditAlpha) rgbDest.rgbReserved = (uint8_t)(rgb1.rgbReserved&rgb2.rgbReserved);
+ break;
+ case OpXor:
+ rgbDest.rgbBlue = (uint8_t)(rgb1.rgbBlue^rgb2.rgbBlue);
+ rgbDest.rgbGreen = (uint8_t)(rgb1.rgbGreen^rgb2.rgbGreen);
+ rgbDest.rgbRed = (uint8_t)(rgb1.rgbRed^rgb2.rgbRed);
+ if (bEditAlpha) rgbDest.rgbReserved = (uint8_t)(rgb1.rgbReserved^rgb2.rgbReserved);
+ break;
+ case OpOr:
+ rgbDest.rgbBlue = (uint8_t)(rgb1.rgbBlue|rgb2.rgbBlue);
+ rgbDest.rgbGreen = (uint8_t)(rgb1.rgbGreen|rgb2.rgbGreen);
+ rgbDest.rgbRed = (uint8_t)(rgb1.rgbRed|rgb2.rgbRed);
+ if (bEditAlpha) rgbDest.rgbReserved = (uint8_t)(rgb1.rgbReserved|rgb2.rgbReserved);
+ break;
+ case OpMask:
+ if(rgb2.rgbBlue==0 && rgb2.rgbGreen==0 && rgb2.rgbRed==0)
+ rgbDest = rgbBackgrnd1;
+ else
+ rgbDest = rgb1;
+ break;
+ case OpSrcCopy:
+ if(IsTransparent(lX,lY))
+ rgbDest = rgb2;
+ else // copy straight over
+ rgbDest = rgb1;
+ break;
+ case OpDstCopy:
+ if(imgsrc2.IsTransparent(lX+lXOffset,lY+lYOffset))
+ rgbDest = rgb1;
+ else // copy straight over
+ rgbDest = rgb2;
+ break;
+ case OpScreen:
+ {
+ uint8_t a,a1;
+
+ if (imgsrc2.IsTransparent(lX+lXOffset,lY+lYOffset)){
+ a=0;
+#if CXIMAGE_SUPPORT_ALPHA
+ } else if (imgsrc2.AlphaIsValid()){
+ a=imgsrc2.AlphaGet(lX+lXOffset,lY+lYOffset);
+ a =(uint8_t)((a*imgsrc2.info.nAlphaMax)/255);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ } else {
+ a=255;
+ }
+
+ if (a==0){ //transparent
+ rgbDest = rgb1;
+ } else if (a==255){ //opaque
+ rgbDest = rgb2;
+ } else { //blend
+ a1 = (uint8_t)~a;
+ rgbDest.rgbBlue = (uint8_t)((rgb1.rgbBlue*a1+rgb2.rgbBlue*a)/255);
+ rgbDest.rgbGreen = (uint8_t)((rgb1.rgbGreen*a1+rgb2.rgbGreen*a)/255);
+ rgbDest.rgbRed = (uint8_t)((rgb1.rgbRed*a1+rgb2.rgbRed*a)/255);
+ }
+
+ if (bEditAlpha) rgbDest.rgbReserved = (uint8_t)((rgb1.rgbReserved*a)/255);
+ }
+ break;
+ case OpSrcBlend:
+ if(IsTransparent(lX,lY))
+ rgbDest = rgb2;
+ else
+ {
+ int32_t lBDiff = abs(rgb1.rgbBlue - rgbBackgrnd1.rgbBlue);
+ int32_t lGDiff = abs(rgb1.rgbGreen - rgbBackgrnd1.rgbGreen);
+ int32_t lRDiff = abs(rgb1.rgbRed - rgbBackgrnd1.rgbRed);
+
+ double lAverage = (lBDiff+lGDiff+lRDiff)/3;
+ double lThresh = 16;
+ double dLarge = lAverage/lThresh;
+ double dSmall = (lThresh-lAverage)/lThresh;
+ double dSmallAmt = dSmall*((double)rgb2.rgbBlue);
+
+ if( lAverage < lThresh+1){
+ rgbDest.rgbBlue = (uint8_t)max(0,min(255,(int32_t)(dLarge*((double)rgb1.rgbBlue) +
+ dSmallAmt)));
+ rgbDest.rgbGreen = (uint8_t)max(0,min(255,(int32_t)(dLarge*((double)rgb1.rgbGreen) +
+ dSmallAmt)));
+ rgbDest.rgbRed = (uint8_t)max(0,min(255,(int32_t)(dLarge*((double)rgb1.rgbRed) +
+ dSmallAmt)));
+ }
+ else
+ rgbDest = rgb1;
+ }
+ break;
+ case OpBlendAlpha: //[brunom]
+ if(rgb2.rgbReserved != 0)
+ {
+ // The lower value is almost transparent, or the overlying
+ // almost transparent can not directly overlying the value taken
+ if( (rgb1.rgbReserved < 5) || (rgb2.rgbReserved > 250) ){
+ rgbDest = rgb2;
+ } else {
+ // Alpha Blending with associative calculation merge
+ // (http://en.wikipedia.org/wiki/Alpha_compositing)
+ int32_t a0,a1,a2;
+ // Transparency of the superimposed image
+ a2 = rgb2.rgbReserved;
+ // Calculation transparency of the underlying image
+ a1 = (rgb1.rgbReserved * (255 - a2)) >> 8;
+ // total transparency of the new pixel
+ a0 = a2 + a1;
+ // New transparency assume (a0 == 0 is the restriction s.o. (range 5-250) intercepted)
+ if (bEditAlpha) rgbDest.rgbReserved = a0;
+ // each color channel to calculate
+ rgbDest.rgbBlue = (BYTE)((rgb2.rgbBlue * a2 + a1 * rgb1.rgbBlue )/a0);
+ rgbDest.rgbGreen = (BYTE)((rgb2.rgbGreen * a2 + a1 * rgb1.rgbGreen)/a0);
+ rgbDest.rgbRed = (BYTE)((rgb2.rgbRed * a2 + a1 * rgb1.rgbRed )/a0);
+ }
+ } else {
+ rgbDest = rgb1;
+ rgbDest.rgbReserved = 0;
+ }
+ break;
+ default:
+ return;
+ }
+ SetPixelColor(lX,lY,rgbDest,bEditAlpha);
+ }
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+// thanks to Kenneth Ballard
+void CxImage::MixFrom(CxImage & imagesrc2, int32_t lXOffset, int32_t lYOffset)
+{
+ int32_t width = imagesrc2.GetWidth();
+ int32_t height = imagesrc2.GetHeight();
+
+ int32_t x, y;
+
+ if (imagesrc2.IsTransparent()) {
+ for(x = 0; x < width; x++) {
+ for(y = 0; y < height; y++) {
+ if(!imagesrc2.IsTransparent(x,y)){
+ SetPixelColor(x + lXOffset, y + lYOffset, imagesrc2.BlindGetPixelColor(x, y));
+ }
+ }
+ }
+ } else { //no transparency so just set it <Matt>
+ for(x = 0; x < width; x++) {
+ for(y = 0; y < height; y++) {
+ SetPixelColor(x + lXOffset, y + lYOffset, imagesrc2.BlindGetPixelColor(x, y));
+ }
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adjusts separately the red, green, and blue values in the image.
+ * \param r, g, b: can be from -255 to +255.
+ * \return true if everything is ok
+ */
+bool CxImage::ShiftRGB(int32_t r, int32_t g, int32_t b)
+{
+ if (!pDib) return false;
+ RGBQUAD color;
+ if (head.biClrUsed==0){
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ color = BlindGetPixelColor(x,y);
+ color.rgbRed = (uint8_t)max(0,min(255,(int32_t)(color.rgbRed + r)));
+ color.rgbGreen = (uint8_t)max(0,min(255,(int32_t)(color.rgbGreen + g)));
+ color.rgbBlue = (uint8_t)max(0,min(255,(int32_t)(color.rgbBlue + b)));
+ BlindSetPixelColor(x,y,color);
+ }
+ }
+ }
+ } else {
+ for(uint32_t j=0; j<head.biClrUsed; j++){
+ color = GetPaletteColor((uint8_t)j);
+ color.rgbRed = (uint8_t)max(0,min(255,(int32_t)(color.rgbRed + r)));
+ color.rgbGreen = (uint8_t)max(0,min(255,(int32_t)(color.rgbGreen + g)));
+ color.rgbBlue = (uint8_t)max(0,min(255,(int32_t)(color.rgbBlue + b)));
+ SetPaletteColor((uint8_t)j,color);
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adjusts the color balance of the image
+ * \param gamma can be from 0.1 to 5.
+ * \return true if everything is ok
+ * \sa GammaRGB
+ */
+bool CxImage::Gamma(float gamma)
+{
+ if (!pDib) return false;
+
+ if (gamma <= 0.0f) return false;
+
+ double dinvgamma = 1/gamma;
+ double dMax = pow(255.0, dinvgamma) / 255.0;
+
+ uint8_t cTable[256]; //<nipper>
+ for (int32_t i=0;i<256;i++) {
+ cTable[i] = (uint8_t)max(0,min(255,(int32_t)( pow((double)i, dinvgamma) / dMax)));
+ }
+
+ return Lut(cTable);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adjusts the color balance indipendent for each color channel
+ * \param gammaR, gammaG, gammaB can be from 0.1 to 5.
+ * \return true if everything is ok
+ * \sa Gamma
+ */
+bool CxImage::GammaRGB(float gammaR, float gammaG, float gammaB)
+{
+ if (!pDib) return false;
+
+ if (gammaR <= 0.0f) return false;
+ if (gammaG <= 0.0f) return false;
+ if (gammaB <= 0.0f) return false;
+
+ double dinvgamma, dMax;
+ int32_t i;
+
+ dinvgamma = 1/gammaR;
+ dMax = pow(255.0, dinvgamma) / 255.0;
+ uint8_t cTableR[256];
+ for (i=0;i<256;i++) {
+ cTableR[i] = (uint8_t)max(0,min(255,(int32_t)( pow((double)i, dinvgamma) / dMax)));
+ }
+
+ dinvgamma = 1/gammaG;
+ dMax = pow(255.0, dinvgamma) / 255.0;
+ uint8_t cTableG[256];
+ for (i=0;i<256;i++) {
+ cTableG[i] = (uint8_t)max(0,min(255,(int32_t)( pow((double)i, dinvgamma) / dMax)));
+ }
+
+ dinvgamma = 1/gammaB;
+ dMax = pow(255.0, dinvgamma) / 255.0;
+ uint8_t cTableB[256];
+ for (i=0;i<256;i++) {
+ cTableB[i] = (uint8_t)max(0,min(255,(int32_t)( pow((double)i, dinvgamma) / dMax)));
+ }
+
+ return Lut(cTableR, cTableG, cTableB);
+}
+////////////////////////////////////////////////////////////////////////////////
+
+//#if !defined (_WIN32_WCE)
+/**
+ * Adjusts the intensity of each pixel to the median intensity of its surrounding pixels.
+ * \param Ksize: size of the kernel.
+ * \return true if everything is ok
+ */
+bool CxImage::Median(int32_t Ksize)
+{
+ if (!pDib) return false;
+
+ int32_t k2 = Ksize/2;
+ int32_t kmax= Ksize-k2;
+ int32_t i,j,k;
+
+ RGBQUAD* kernel = (RGBQUAD*)malloc(Ksize*Ksize*sizeof(RGBQUAD));
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ for(j=-k2, i=0;j<kmax;j++)
+ for(k=-k2;k<kmax;k++)
+ if (IsInside(x+j,y+k))
+ kernel[i++]=BlindGetPixelColor(x+j,y+k);
+
+ qsort(kernel, i, sizeof(RGBQUAD), CompareColors);
+ tmp.SetPixelColor(x,y,kernel[i/2]);
+ }
+ }
+ }
+ free(kernel);
+ Transfer(tmp);
+ return true;
+}
+//#endif //_WIN32_WCE
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds an uniform noise to the image
+ * \param level: can be from 0 (no noise) to 255 (lot of noise).
+ * \return true if everything is ok
+ */
+bool CxImage::Noise(int32_t level)
+{
+ if (!pDib) return false;
+ RGBQUAD color;
+
+ int32_t xmin,xmax,ymin,ymax,n;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin)); //<zhanghk><Anatoly Ivasyuk>
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ color = BlindGetPixelColor(x,y);
+ n=(int32_t)((rand()/(float)RAND_MAX - 0.5)*level);
+ color.rgbRed = (uint8_t)max(0,min(255,(int32_t)(color.rgbRed + n)));
+ n=(int32_t)((rand()/(float)RAND_MAX - 0.5)*level);
+ color.rgbGreen = (uint8_t)max(0,min(255,(int32_t)(color.rgbGreen + n)));
+ n=(int32_t)((rand()/(float)RAND_MAX - 0.5)*level);
+ color.rgbBlue = (uint8_t)max(0,min(255,(int32_t)(color.rgbBlue + n)));
+ BlindSetPixelColor(x,y,color);
+ }
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Computes the bidimensional FFT or DFT of the image.
+ * - The images are processed as grayscale
+ * - If the dimensions of the image are a power of, 2 the FFT is performed automatically.
+ * - If dstReal and/or dstImag are NULL, the resulting images replaces the original(s).
+ * - Note: with 8 bits there is a HUGE loss in the dynamics. The function tries
+ * to keep an acceptable SNR, but 8bit = 48dB...
+ *
+ * \param srcReal, srcImag: source images: One can be NULL, but not both
+ * \param dstReal, dstImag: destination images. Can be NULL.
+ * \param direction: 1 = forward, -1 = inverse.
+ * \param bForceFFT: if true, the images are resampled to make the dimensions a power of 2.
+ * \param bMagnitude: if true, the real part returns the magnitude, the imaginary part returns the phase
+ * \return true if everything is ok
+ */
+bool CxImage::FFT2(CxImage* srcReal, CxImage* srcImag, CxImage* dstReal, CxImage* dstImag,
+ int32_t direction, bool bForceFFT, bool bMagnitude)
+{
+ //check if there is something to convert
+ if (srcReal==NULL && srcImag==NULL) return false;
+
+ int32_t w,h;
+ //get width and height
+ if (srcReal) {
+ w=srcReal->GetWidth();
+ h=srcReal->GetHeight();
+ } else {
+ w=srcImag->GetWidth();
+ h=srcImag->GetHeight();
+ }
+
+ bool bXpow2 = IsPowerof2(w);
+ bool bYpow2 = IsPowerof2(h);
+ //if bForceFFT, width AND height must be powers of 2
+ if (bForceFFT && !(bXpow2 && bYpow2)) {
+ int32_t i;
+
+ i=0;
+ while((1<<i)<w) i++;
+ w=1<<i;
+ bXpow2=true;
+
+ i=0;
+ while((1<<i)<h) i++;
+ h=1<<i;
+ bYpow2=true;
+ }
+
+ // I/O images for FFT
+ CxImage *tmpReal,*tmpImag;
+
+ // select output
+ tmpReal = (dstReal) ? dstReal : srcReal;
+ tmpImag = (dstImag) ? dstImag : srcImag;
+
+ // src!=dst -> copy the image
+ if (srcReal && dstReal) tmpReal->Copy(*srcReal,true,false,false);
+ if (srcImag && dstImag) tmpImag->Copy(*srcImag,true,false,false);
+
+ // dst&&src are empty -> create new one, else turn to GrayScale
+ if (srcReal==0 && dstReal==0){
+ tmpReal = new CxImage(w,h,8);
+ tmpReal->Clear(0);
+ tmpReal->SetGrayPalette();
+ } else {
+ if (!tmpReal->IsGrayScale()) tmpReal->GrayScale();
+ }
+ if (srcImag==0 && dstImag==0){
+ tmpImag = new CxImage(w,h,8);
+ tmpImag->Clear(0);
+ tmpImag->SetGrayPalette();
+ } else {
+ if (!tmpImag->IsGrayScale()) tmpImag->GrayScale();
+ }
+
+ if (!(tmpReal->IsValid() && tmpImag->IsValid())){
+ if (srcReal==0 && dstReal==0) delete tmpReal;
+ if (srcImag==0 && dstImag==0) delete tmpImag;
+ return false;
+ }
+
+ //resample for FFT, if necessary
+ tmpReal->Resample(w,h,0);
+ tmpImag->Resample(w,h,0);
+
+ //ok, here we have 2 (w x h), grayscale images ready for a FFT
+
+ double* real;
+ double* imag;
+ int32_t j,k,m;
+
+ _complex **grid;
+ //double mean = tmpReal->Mean();
+ /* Allocate memory for the grid */
+ grid = (_complex **)malloc(w * sizeof(_complex));
+ for (k=0;k<w;k++) {
+ grid[k] = (_complex *)malloc(h * sizeof(_complex));
+ }
+ for (j=0;j<h;j++) {
+ for (k=0;k<w;k++) {
+ grid[k][j].x = tmpReal->GetPixelIndex(k,j)-128;
+ grid[k][j].y = tmpImag->GetPixelIndex(k,j)-128;
+ }
+ }
+
+ //DFT buffers
+ double *real2,*imag2;
+ real2 = (double*)malloc(max(w,h) * sizeof(double));
+ imag2 = (double*)malloc(max(w,h) * sizeof(double));
+
+ /* Transform the rows */
+ real = (double *)malloc(w * sizeof(double));
+ imag = (double *)malloc(w * sizeof(double));
+
+ m=0;
+ while((1<<m)<w) m++;
+
+ for (j=0;j<h;j++) {
+ for (k=0;k<w;k++) {
+ real[k] = grid[k][j].x;
+ imag[k] = grid[k][j].y;
+ }
+
+ if (bXpow2) FFT(direction,m,real,imag);
+ else DFT(direction,w,real,imag,real2,imag2);
+
+ for (k=0;k<w;k++) {
+ grid[k][j].x = real[k];
+ grid[k][j].y = imag[k];
+ }
+ }
+ free(real);
+ free(imag);
+
+ /* Transform the columns */
+ real = (double *)malloc(h * sizeof(double));
+ imag = (double *)malloc(h * sizeof(double));
+
+ m=0;
+ while((1<<m)<h) m++;
+
+ for (k=0;k<w;k++) {
+ for (j=0;j<h;j++) {
+ real[j] = grid[k][j].x;
+ imag[j] = grid[k][j].y;
+ }
+
+ if (bYpow2) FFT(direction,m,real,imag);
+ else DFT(direction,h,real,imag,real2,imag2);
+
+ for (j=0;j<h;j++) {
+ grid[k][j].x = real[j];
+ grid[k][j].y = imag[j];
+ }
+ }
+ free(real);
+ free(imag);
+
+ free(real2);
+ free(imag2);
+
+ /* converting from double to byte, there is a HUGE loss in the dynamics
+ "nn" tries to keep an acceptable SNR, but 8bit=48dB: don't ask more */
+ double nn=pow((double)2,(double)log((double)max(w,h))/(double)log((double)2)-4);
+ //reversed gain for reversed transform
+ if (direction==-1) nn=1/nn;
+ //bMagnitude : just to see it on the screen
+ if (bMagnitude) nn*=4;
+
+ for (j=0;j<h;j++) {
+ for (k=0;k<w;k++) {
+ if (bMagnitude){
+ tmpReal->SetPixelIndex(k,j,(uint8_t)max(0,min(255,(nn*(3+log(_cabs(grid[k][j])))))));
+ if (grid[k][j].x==0){
+ tmpImag->SetPixelIndex(k,j,(uint8_t)max(0,min(255,(128+(atan(grid[k][j].y/0.0000000001)*nn)))));
+ } else {
+ tmpImag->SetPixelIndex(k,j,(uint8_t)max(0,min(255,(128+(atan(grid[k][j].y/grid[k][j].x)*nn)))));
+ }
+ } else {
+ tmpReal->SetPixelIndex(k,j,(uint8_t)max(0,min(255,(128 + grid[k][j].x*nn))));
+ tmpImag->SetPixelIndex(k,j,(uint8_t)max(0,min(255,(128 + grid[k][j].y*nn))));
+ }
+ }
+ }
+
+ for (k=0;k<w;k++) free (grid[k]);
+ free (grid);
+
+ if (srcReal==0 && dstReal==0) delete tmpReal;
+ if (srcImag==0 && dstImag==0) delete tmpImag;
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::IsPowerof2(int32_t x)
+{
+ int32_t i=0;
+ while ((1<<i)<x) i++;
+ if (x==(1<<i)) return true;
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ This computes an in-place complex-to-complex FFT
+ x and y are the real and imaginary arrays of n=2^m points.
+ o(n)=n*log2(n)
+ dir = 1 gives forward transform
+ dir = -1 gives reverse transform
+ Written by Paul Bourke, July 1998
+ FFT algorithm by Cooley and Tukey, 1965
+*/
+bool CxImage::FFT(int32_t dir,int32_t m,double *x,double *y)
+{
+ int32_t nn,i,i1,j,k,i2,l,l1,l2;
+ double c1,c2,tx,ty,t1,t2,u1,u2,z;
+
+ /* Calculate the number of points */
+ nn = 1<<m;
+
+ /* Do the bit reversal */
+ i2 = nn >> 1;
+ j = 0;
+ for (i=0;i<nn-1;i++) {
+ if (i < j) {
+ tx = x[i];
+ ty = y[i];
+ x[i] = x[j];
+ y[i] = y[j];
+ x[j] = tx;
+ y[j] = ty;
+ }
+ k = i2;
+ while (k <= j) {
+ j -= k;
+ k >>= 1;
+ }
+ j += k;
+ }
+
+ /* Compute the FFT */
+ c1 = -1.0;
+ c2 = 0.0;
+ l2 = 1;
+ for (l=0;l<m;l++) {
+ l1 = l2;
+ l2 <<= 1;
+ u1 = 1.0;
+ u2 = 0.0;
+ for (j=0;j<l1;j++) {
+ for (i=j;i<nn;i+=l2) {
+ i1 = i + l1;
+ t1 = u1 * x[i1] - u2 * y[i1];
+ t2 = u1 * y[i1] + u2 * x[i1];
+ x[i1] = x[i] - t1;
+ y[i1] = y[i] - t2;
+ x[i] += t1;
+ y[i] += t2;
+ }
+ z = u1 * c1 - u2 * c2;
+ u2 = u1 * c2 + u2 * c1;
+ u1 = z;
+ }
+ c2 = sqrt((1.0 - c1) / 2.0);
+ if (dir == 1)
+ c2 = -c2;
+ c1 = sqrt((1.0 + c1) / 2.0);
+ }
+
+ /* Scaling for forward transform */
+ if (dir == 1) {
+ for (i=0;i<nn;i++) {
+ x[i] /= (double)nn;
+ y[i] /= (double)nn;
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ Direct fourier transform o(n)=n^2
+ Written by Paul Bourke, July 1998
+*/
+bool CxImage::DFT(int32_t dir,int32_t m,double *x1,double *y1,double *x2,double *y2)
+{
+ int32_t i,k;
+ double arg;
+ double cosarg,sinarg;
+
+ for (i=0;i<m;i++) {
+ x2[i] = 0;
+ y2[i] = 0;
+ arg = - dir * 2.0 * PI * i / (double)m;
+ for (k=0;k<m;k++) {
+ cosarg = cos(k * arg);
+ sinarg = sin(k * arg);
+ x2[i] += (x1[k] * cosarg - y1[k] * sinarg);
+ y2[i] += (x1[k] * sinarg + y1[k] * cosarg);
+ }
+ }
+
+ /* Copy the data back */
+ if (dir == 1) {
+ for (i=0;i<m;i++) {
+ x1[i] = x2[i] / m;
+ y1[i] = y2[i] / m;
+ }
+ } else {
+ for (i=0;i<m;i++) {
+ x1[i] = x2[i];
+ y1[i] = y2[i];
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Combines different color components into a single image
+ * \param r,g,b: color channels
+ * \param a: alpha layer, can be NULL
+ * \param colorspace: 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ
+ * \return true if everything is ok
+ */
+bool CxImage::Combine(CxImage* r,CxImage* g,CxImage* b,CxImage* a, int32_t colorspace)
+{
+ if (r==0 || g==0 || b==0) return false;
+
+ int32_t w = r->GetWidth();
+ int32_t h = r->GetHeight();
+
+ Create(w,h,24);
+
+ g->Resample(w,h);
+ b->Resample(w,h);
+
+ if (a) {
+ a->Resample(w,h);
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+
+ RGBQUAD c;
+ for (int32_t y=0;y<h;y++){
+ info.nProgress = (int32_t)(100*y/h); //<Anatoly Ivasyuk>
+ for (int32_t x=0;x<w;x++){
+ c.rgbRed=r->GetPixelIndex(x,y);
+ c.rgbGreen=g->GetPixelIndex(x,y);
+ c.rgbBlue=b->GetPixelIndex(x,y);
+ switch (colorspace){
+ case 1:
+ BlindSetPixelColor(x,y,HSLtoRGB(c));
+ break;
+ case 2:
+ BlindSetPixelColor(x,y,YUVtoRGB(c));
+ break;
+ case 3:
+ BlindSetPixelColor(x,y,YIQtoRGB(c));
+ break;
+ case 4:
+ BlindSetPixelColor(x,y,XYZtoRGB(c));
+ break;
+ default:
+ BlindSetPixelColor(x,y,c);
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ if (a) AlphaSet(x,y,a->GetPixelIndex(x,y));
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Smart blurring to remove small defects, dithering or artifacts.
+ * \param radius: normally between 0.01 and 0.5
+ * \param niterations: should be trimmed with radius, to avoid blurring should be (radius*niterations)<1
+ * \param colorspace: 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ
+ * \return true if everything is ok
+ */
+bool CxImage::Repair(float radius, int32_t niterations, int32_t colorspace)
+{
+ if (!IsValid()) return false;
+
+ int32_t w = GetWidth();
+ int32_t h = GetHeight();
+
+ CxImage r,g,b;
+
+ r.Create(w,h,8);
+ g.Create(w,h,8);
+ b.Create(w,h,8);
+
+ switch (colorspace){
+ case 1:
+ SplitHSL(&r,&g,&b);
+ break;
+ case 2:
+ SplitYUV(&r,&g,&b);
+ break;
+ case 3:
+ SplitYIQ(&r,&g,&b);
+ break;
+ case 4:
+ SplitXYZ(&r,&g,&b);
+ break;
+ default:
+ SplitRGB(&r,&g,&b);
+ }
+
+ for (int32_t i=0; i<niterations; i++){
+ RepairChannel(&r,radius);
+ RepairChannel(&g,radius);
+ RepairChannel(&b,radius);
+ }
+
+ CxImage* a=NULL;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()){
+ a = new CxImage();
+ AlphaSplit(a);
+ }
+#endif
+
+ Combine(&r,&g,&b,a,colorspace);
+
+ delete a;
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::RepairChannel(CxImage *ch, float radius)
+{
+ if (ch==NULL) return false;
+
+ CxImage tmp(*ch);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t w = ch->GetWidth()-1;
+ int32_t h = ch->GetHeight()-1;
+
+ double correction,ix,iy,ixx,ixy,iyy;
+ int32_t x,y,xy0,xp1,xm1,yp1,ym1;
+
+ for(x=1; x<w; x++){
+ for(y=1; y<h; y++){
+
+ xy0 = ch->BlindGetPixelIndex(x,y);
+ xm1 = ch->BlindGetPixelIndex(x-1,y);
+ xp1 = ch->BlindGetPixelIndex(x+1,y);
+ ym1 = ch->BlindGetPixelIndex(x,y-1);
+ yp1 = ch->BlindGetPixelIndex(x,y+1);
+
+ ix= (xp1-xm1)/2.0;
+ iy= (yp1-ym1)/2.0;
+ ixx= xp1 - 2.0 * xy0 + xm1;
+ iyy= yp1 - 2.0 * xy0 + ym1;
+ ixy=(ch->BlindGetPixelIndex(x+1,y+1) + ch->BlindGetPixelIndex(x-1,y-1) -
+ ch->BlindGetPixelIndex(x-1,y+1) - ch->BlindGetPixelIndex(x+1,y-1))/4.0;
+
+ correction = ((1.0+iy*iy)*ixx - ix*iy*ixy + (1.0+ix*ix)*iyy)/(1.0+ix*ix+iy*iy);
+
+ tmp.BlindSetPixelIndex(x,y,(uint8_t)min(255,max(0,(xy0 + radius * correction + 0.5))));
+ }
+ }
+
+ for (x=0;x<=w;x++){
+ for(y=0; y<=h; y+=h){
+ xy0 = ch->BlindGetPixelIndex(x,y);
+ xm1 = ch->GetPixelIndex(x-1,y);
+ xp1 = ch->GetPixelIndex(x+1,y);
+ ym1 = ch->GetPixelIndex(x,y-1);
+ yp1 = ch->GetPixelIndex(x,y+1);
+
+ ix= (xp1-xm1)/2.0;
+ iy= (yp1-ym1)/2.0;
+ ixx= xp1 - 2.0 * xy0 + xm1;
+ iyy= yp1 - 2.0 * xy0 + ym1;
+ ixy=(ch->GetPixelIndex(x+1,y+1) + ch->GetPixelIndex(x-1,y-1) -
+ ch->GetPixelIndex(x-1,y+1) - ch->GetPixelIndex(x+1,y-1))/4.0;
+
+ correction = ((1.0+iy*iy)*ixx - ix*iy*ixy + (1.0+ix*ix)*iyy)/(1.0+ix*ix+iy*iy);
+
+ tmp.BlindSetPixelIndex(x,y,(uint8_t)min(255,max(0,(xy0 + radius * correction + 0.5))));
+ }
+ }
+ for (x=0;x<=w;x+=w){
+ for (y=0;y<=h;y++){
+ xy0 = ch->BlindGetPixelIndex(x,y);
+ xm1 = ch->GetPixelIndex(x-1,y);
+ xp1 = ch->GetPixelIndex(x+1,y);
+ ym1 = ch->GetPixelIndex(x,y-1);
+ yp1 = ch->GetPixelIndex(x,y+1);
+
+ ix= (xp1-xm1)/2.0;
+ iy= (yp1-ym1)/2.0;
+ ixx= xp1 - 2.0 * xy0 + xm1;
+ iyy= yp1 - 2.0 * xy0 + ym1;
+ ixy=(ch->GetPixelIndex(x+1,y+1) + ch->GetPixelIndex(x-1,y-1) -
+ ch->GetPixelIndex(x-1,y+1) - ch->GetPixelIndex(x+1,y-1))/4.0;
+
+ correction = ((1.0+iy*iy)*ixx - ix*iy*ixy + (1.0+ix*ix)*iyy)/(1.0+ix*ix+iy*iy);
+
+ tmp.BlindSetPixelIndex(x,y,(uint8_t)min(255,max(0,(xy0 + radius * correction + 0.5))));
+ }
+ }
+
+ ch->Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enhance the variations between adjacent pixels.
+ * Similar results can be achieved using Filter(),
+ * but the algorithms are different both in Edge() and in Contour().
+ * \return true if everything is ok
+ */
+bool CxImage::Contour()
+{
+ if (!pDib) return false;
+
+ int32_t Ksize = 3;
+ int32_t k2 = Ksize/2;
+ int32_t kmax= Ksize-k2;
+ int32_t i,j,k;
+ uint8_t maxr,maxg,maxb;
+ RGBQUAD pix1,pix2;
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ pix1 = BlindGetPixelColor(x,y);
+ maxr=maxg=maxb=0;
+ for(j=-k2, i=0;j<kmax;j++){
+ for(k=-k2;k<kmax;k++, i++){
+ if (!IsInside(x+j,y+k)) continue;
+ pix2 = BlindGetPixelColor(x+j,y+k);
+ if ((pix2.rgbBlue-pix1.rgbBlue)>maxb) maxb = pix2.rgbBlue;
+ if ((pix2.rgbGreen-pix1.rgbGreen)>maxg) maxg = pix2.rgbGreen;
+ if ((pix2.rgbRed-pix1.rgbRed)>maxr) maxr = pix2.rgbRed;
+ }
+ }
+ pix1.rgbBlue=(uint8_t)(255-maxb);
+ pix1.rgbGreen=(uint8_t)(255-maxg);
+ pix1.rgbRed=(uint8_t)(255-maxr);
+ tmp.BlindSetPixelColor(x,y,pix1);
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds a random offset to each pixel in the image
+ * \param radius: maximum pixel displacement
+ * \return true if everything is ok
+ */
+bool CxImage::Jitter(int32_t radius)
+{
+ if (!pDib) return false;
+
+ int32_t nx,ny;
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ nx=x+(int32_t)((rand()/(float)RAND_MAX - 0.5)*(radius*2));
+ ny=y+(int32_t)((rand()/(float)RAND_MAX - 0.5)*(radius*2));
+ if (!IsInside(nx,ny)) {
+ nx=x;
+ ny=y;
+ }
+ if (head.biClrUsed==0){
+ tmp.BlindSetPixelColor(x,y,BlindGetPixelColor(nx,ny));
+ } else {
+ tmp.BlindSetPixelIndex(x,y,BlindGetPixelIndex(nx,ny));
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ tmp.AlphaSet(x,y,AlphaGet(nx,ny));
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * generates a 1-D convolution matrix to be used for each pass of
+ * a two-pass gaussian blur. Returns the length of the matrix.
+ * \author [nipper]
+ */
+int32_t CxImage::gen_convolve_matrix (float radius, float **cmatrix_p)
+{
+ int32_t matrix_length;
+ int32_t matrix_midpoint;
+ float* cmatrix;
+ int32_t i,j;
+ float std_dev;
+ float sum;
+
+ /* we want to generate a matrix that goes out a certain radius
+ * from the center, so we have to go out ceil(rad-0.5) pixels,
+ * inlcuding the center pixel. Of course, that's only in one direction,
+ * so we have to go the same amount in the other direction, but not count
+ * the center pixel again. So we double the previous result and subtract
+ * one.
+ * The radius parameter that is passed to this function is used as
+ * the standard deviation, and the radius of effect is the
+ * standard deviation * 2. It's a little confusing.
+ * <DP> modified scaling, so that matrix_lenght = 1+2*radius parameter
+ */
+ radius = (float)fabs(0.5*radius) + 0.25f;
+
+ std_dev = radius;
+ radius = std_dev * 2;
+
+ /* go out 'radius' in each direction */
+ matrix_length = int32_t (2 * ceil(radius-0.5) + 1);
+ if (matrix_length <= 0) matrix_length = 1;
+ matrix_midpoint = matrix_length/2 + 1;
+ *cmatrix_p = new float[matrix_length];
+ cmatrix = *cmatrix_p;
+
+ /* Now we fill the matrix by doing a numeric integration approximation
+ * from -2*std_dev to 2*std_dev, sampling 50 points per pixel.
+ * We do the bottom half, mirror it to the top half, then compute the
+ * center point. Otherwise asymmetric quantization errors will occur.
+ * The formula to integrate is e^-(x^2/2s^2).
+ */
+
+ /* first we do the top (right) half of matrix */
+ for (i = matrix_length/2 + 1; i < matrix_length; i++)
+ {
+ float base_x = i - (float)floor((float)(matrix_length/2)) - 0.5f;
+ sum = 0;
+ for (j = 1; j <= 50; j++)
+ {
+ if ( base_x+0.02*j <= radius )
+ sum += (float)exp (-(base_x+0.02*j)*(base_x+0.02*j) /
+ (2*std_dev*std_dev));
+ }
+ cmatrix[i] = sum/50;
+ }
+
+ /* mirror the thing to the bottom half */
+ for (i=0; i<=matrix_length/2; i++) {
+ cmatrix[i] = cmatrix[matrix_length-1-i];
+ }
+
+ /* find center val -- calculate an odd number of quanta to make it symmetric,
+ * even if the center point is weighted slightly higher than others. */
+ sum = 0;
+ for (j=0; j<=50; j++)
+ {
+ sum += (float)exp (-(0.5+0.02*j)*(0.5+0.02*j) /
+ (2*std_dev*std_dev));
+ }
+ cmatrix[matrix_length/2] = sum/51;
+
+ /* normalize the distribution by scaling the total sum to one */
+ sum=0;
+ for (i=0; i<matrix_length; i++) sum += cmatrix[i];
+ for (i=0; i<matrix_length; i++) cmatrix[i] = cmatrix[i] / sum;
+
+ return matrix_length;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * generates a lookup table for every possible product of 0-255 and
+ * each value in the convolution matrix. The returned array is
+ * indexed first by matrix position, then by input multiplicand (?)
+ * value.
+ * \author [nipper]
+ */
+float* CxImage::gen_lookup_table (float *cmatrix, int32_t cmatrix_length)
+{
+ float* lookup_table = new float[cmatrix_length * 256];
+ float* lookup_table_p = lookup_table;
+ float* cmatrix_p = cmatrix;
+
+ for (int32_t i=0; i<cmatrix_length; i++)
+ {
+ for (int32_t j=0; j<256; j++)
+ {
+ *(lookup_table_p++) = *cmatrix_p * (float)j;
+ }
+ cmatrix_p++;
+ }
+
+ return lookup_table;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * this function is written as if it is blurring a column at a time,
+ * even though it can operate on rows, too. There is no difference
+ * in the processing of the lines, at least to the blur_line function.
+ * \author [nipper]
+ */
+void CxImage::blur_line (float *ctable, float *cmatrix, int32_t cmatrix_length, uint8_t* cur_col, uint8_t* dest_col, int32_t y, int32_t bytes)
+{
+ float scale;
+ float sum;
+ int32_t i=0, j=0;
+ int32_t row;
+ int32_t cmatrix_middle = cmatrix_length/2;
+
+ float *cmatrix_p;
+ uint8_t *cur_col_p;
+ uint8_t *cur_col_p1;
+ uint8_t *dest_col_p;
+ float *ctable_p;
+
+ /* this first block is the same as the non-optimized version --
+ * it is only used for very small pictures, so speed isn't a
+ * big concern.
+ */
+ if (cmatrix_length > y)
+ {
+ for (row = 0; row < y ; row++)
+ {
+ scale=0;
+ /* find the scale factor */
+ for (j = 0; j < y ; j++)
+ {
+ /* if the index is in bounds, add it to the scale counter */
+ if ((j + cmatrix_middle - row >= 0) &&
+ (j + cmatrix_middle - row < cmatrix_length))
+ scale += cmatrix[j + cmatrix_middle - row];
+ }
+ for (i = 0; i<bytes; i++)
+ {
+ sum = 0;
+ for (j = 0; j < y; j++)
+ {
+ if ((j >= row - cmatrix_middle) &&
+ (j <= row + cmatrix_middle))
+ sum += cur_col[j*bytes + i] * cmatrix[j];
+ }
+ dest_col[row*bytes + i] = (uint8_t)(0.5f + sum / scale);
+ }
+ }
+ }
+ else
+ {
+ /* for the edge condition, we only use available info and scale to one */
+ for (row = 0; row < cmatrix_middle; row++)
+ {
+ /* find scale factor */
+ scale=0;
+ for (j = cmatrix_middle - row; j<cmatrix_length; j++)
+ scale += cmatrix[j];
+ for (i = 0; i<bytes; i++)
+ {
+ sum = 0;
+ for (j = cmatrix_middle - row; j<cmatrix_length; j++)
+ {
+ sum += cur_col[(row + j-cmatrix_middle)*bytes + i] * cmatrix[j];
+ }
+ dest_col[row*bytes + i] = (uint8_t)(0.5f + sum / scale);
+ }
+ }
+ /* go through each pixel in each col */
+ dest_col_p = dest_col + row*bytes;
+ for (; row < y-cmatrix_middle; row++)
+ {
+ cur_col_p = (row - cmatrix_middle) * bytes + cur_col;
+ for (i = 0; i<bytes; i++)
+ {
+ sum = 0;
+ cmatrix_p = cmatrix;
+ cur_col_p1 = cur_col_p;
+ ctable_p = ctable;
+ for (j = cmatrix_length; j>0; j--)
+ {
+ sum += *(ctable_p + *cur_col_p1);
+ cur_col_p1 += bytes;
+ ctable_p += 256;
+ }
+ cur_col_p++;
+ *(dest_col_p++) = (uint8_t)(0.5f + sum);
+ }
+ }
+
+ /* for the edge condition , we only use available info, and scale to one */
+ for (; row < y; row++)
+ {
+ /* find scale factor */
+ scale=0;
+ for (j = 0; j< y-row + cmatrix_middle; j++)
+ scale += cmatrix[j];
+ for (i = 0; i<bytes; i++)
+ {
+ sum = 0;
+ for (j = 0; j<y-row + cmatrix_middle; j++)
+ {
+ sum += cur_col[(row + j-cmatrix_middle)*bytes + i] * cmatrix[j];
+ }
+ dest_col[row*bytes + i] = (uint8_t) (0.5f + sum / scale);
+ }
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \author [DP]
+ */
+void CxImage::blur_text (uint8_t threshold, uint8_t decay, uint8_t max_depth, CxImage* iSrc, CxImage* iDst, uint8_t bytes)
+{
+ int32_t x,y,z,m;
+ uint8_t *pSrc, *pSrc2, *pSrc3, *pDst;
+ uint8_t step,n;
+ int32_t pivot;
+
+ if (max_depth<1) max_depth = 1;
+
+ int32_t nmin,nmax,xmin,xmax,ymin,ymax;
+ xmin = ymin = 0;
+ xmax = iSrc->head.biWidth;
+ ymax = iSrc->head.biHeight;
+
+ if (xmin==xmax || ymin==ymax) return;
+
+ nmin = xmin * bytes;
+ nmax = xmax * bytes;
+
+ CImageIterator itSrc(iSrc);
+ CImageIterator itTmp(iDst);
+
+ double dbScaler = 100.0f/(ymax-ymin)/bytes;
+
+ for (n=0; n<bytes; n++){
+ for (y=ymin+1;y<(ymax-1);y++)
+ {
+ if (info.nEscape) break;
+ info.nProgress = (int32_t)((y-ymin)*dbScaler*(1+n));
+
+ pSrc = itSrc.GetRow(y);
+ pSrc2 = itSrc.GetRow(y+1);
+ pSrc3 = itSrc.GetRow(y-1);
+ pDst = itTmp.GetRow(y);
+
+ //scan left to right
+ for (x=n+nmin /*,i=xmin*/; x<(nmax-1); x+=bytes /*,i++*/)
+ {
+ z=x+bytes;
+ pivot = pSrc[z]-threshold;
+ //find upper corner
+ if (pSrc[x]<pivot && pSrc2[z]<pivot && pSrc3[x]>=pivot){
+ while (z<nmax && pSrc2[z]<pSrc[x+bytes] && pSrc[x+bytes]<=pSrc[z]){
+ z+=bytes;
+ }
+ m = z-x;
+ m = (decay>1) ? ((m/bytes)/decay+1) : m/bytes;
+ if (m>max_depth) m = max_depth;
+ step = (uint8_t)((pSrc[x+bytes]-pSrc[x])/(m+1));
+ while (m-->1){
+ pDst[x+m*bytes] = (uint8_t)(pDst[x]+(step*(m+1)));
+ }
+ }
+ //find lower corner
+ z=x+bytes;
+ if (pSrc[x]<pivot && pSrc3[z]<pivot && pSrc2[x]>=pivot){
+ while (z<nmax && pSrc3[z]<pSrc[x+bytes] && pSrc[x+bytes]<=pSrc[z]){
+ z+=bytes;
+ }
+ m = z-x;
+ m = (decay>1) ? ((m/bytes)/decay+1) : m/bytes;
+ if (m>max_depth) m = max_depth;
+ step = (uint8_t)((pSrc[x+bytes]-pSrc[x])/(m+1));
+ while (m-->1){
+ pDst[x+m*bytes] = (uint8_t)(pDst[x]+(step*(m+1)));
+ }
+ }
+ }
+ //scan right to left
+ for (x=nmax-1-n /*,i=(xmax-1)*/; x>0; x-=bytes /*,i--*/)
+ {
+ z=x-bytes;
+ pivot = pSrc[z]-threshold;
+ //find upper corner
+ if (pSrc[x]<pivot && pSrc2[z]<pivot && pSrc3[x]>=pivot){
+ while (z>n && pSrc2[z]<pSrc[x-bytes] && pSrc[x-bytes]<=pSrc[z]){
+ z-=bytes;
+ }
+ m = x-z;
+ m = (decay>1) ? ((m/bytes)/decay+1) : m/bytes;
+ if (m>max_depth) m = max_depth;
+ step = (uint8_t)((pSrc[x-bytes]-pSrc[x])/(m+1));
+ while (m-->1){
+ pDst[x-m*bytes] = (uint8_t)(pDst[x]+(step*(m+1)));
+ }
+ }
+ //find lower corner
+ z=x-bytes;
+ if (pSrc[x]<pivot && pSrc3[z]<pivot && pSrc2[x]>=pivot){
+ while (z>n && pSrc3[z]<pSrc[x-bytes] && pSrc[x-bytes]<=pSrc[z]){
+ z-=bytes;
+ }
+ m = x-z;
+ m = (decay>1) ? ((m/bytes)/decay+1) : m/bytes;
+ if (m>max_depth) m = max_depth;
+ step = (uint8_t)((pSrc[x-bytes]-pSrc[x])/(m+1));
+ while (m-->1){
+ pDst[x-m*bytes] = (uint8_t)(pDst[x]+(step*(m+1)));
+ }
+ }
+ }
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \author [DP]
+ */
+bool CxImage::TextBlur(uint8_t threshold, uint8_t decay, uint8_t max_depth, bool bBlurHorizontal, bool bBlurVertical, CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ RGBQUAD* pPalette=NULL;
+ uint16_t bpp = GetBpp();
+
+ //the routine is optimized for RGB or GrayScale images
+ if (!(head.biBitCount == 24 || IsGrayScale())){
+ pPalette = new RGBQUAD[head.biClrUsed];
+ memcpy(pPalette, GetPalette(),GetPaletteSize());
+ if (!IncreaseBpp(24))
+ return false;
+ }
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ if (bBlurHorizontal)
+ blur_text(threshold, decay, max_depth, this, &tmp, head.biBitCount>>3);
+
+ if (bBlurVertical){
+ CxImage src2(*this);
+ src2.RotateLeft();
+ tmp.RotateLeft();
+ blur_text(threshold, decay, max_depth, &src2, &tmp, head.biBitCount>>3);
+ tmp.RotateRight();
+ }
+
+#if CXIMAGE_SUPPORT_SELECTION
+ //restore the non selected region
+ if (pSelection){
+ for(int32_t y=0; y<head.biHeight; y++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ if (!BlindSelectionIsInside(x,y)){
+ tmp.BlindSetPixelColor(x,y,BlindGetPixelColor(x,y));
+ }
+ }
+ }
+ }
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+ //if necessary, restore the original BPP and palette
+ if (pPalette){
+ tmp.DecreaseBpp(bpp, true, pPalette);
+ delete [] pPalette;
+ }
+
+ if (iDst) iDst->Transfer(tmp);
+ else Transfer(tmp);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \author [nipper]; changes [DP]
+ */
+bool CxImage::GaussianBlur(float radius /*= 1.0f*/, CxImage* iDst /*= 0*/)
+{
+ if (!pDib) return false;
+
+ RGBQUAD* pPalette=NULL;
+ uint16_t bpp = GetBpp();
+
+ //the routine is optimized for RGB or GrayScale images
+ if (!(head.biBitCount == 24 || IsGrayScale())){
+ pPalette = new RGBQUAD[head.biClrUsed];
+ memcpy(pPalette, GetPalette(),GetPaletteSize());
+ if (!IncreaseBpp(24))
+ return false;
+ }
+
+ CxImage tmp_x(*this, false, true, true);
+ if (!tmp_x.IsValid()){
+ strcpy(info.szLastError,tmp_x.GetLastError());
+ return false;
+ }
+
+ // generate convolution matrix and make sure it's smaller than each dimension
+ float *cmatrix = NULL;
+ int32_t cmatrix_length = gen_convolve_matrix(radius, &cmatrix);
+ // generate lookup table
+ float *ctable = gen_lookup_table(cmatrix, cmatrix_length);
+
+ int32_t x,y;
+ int32_t bypp = head.biBitCount>>3;
+
+ CImageIterator itSrc(this);
+ CImageIterator itTmp(&tmp_x);
+
+ double dbScaler = 50.0f/head.biHeight;
+
+ // blur the rows
+ for (y=0;y<head.biHeight;y++)
+ {
+ if (info.nEscape) break;
+ info.nProgress = (int32_t)(y*dbScaler);
+
+ blur_line(ctable, cmatrix, cmatrix_length, itSrc.GetRow(y), itTmp.GetRow(y), head.biWidth, bypp);
+ }
+
+ CxImage tmp_y(tmp_x, false, true, true);
+ if (!tmp_y.IsValid()){
+ strcpy(info.szLastError,tmp_y.GetLastError());
+ return false;
+ }
+
+ CImageIterator itDst(&tmp_y);
+
+ // blur the cols
+ uint8_t* cur_col = (uint8_t*)malloc(bypp*head.biHeight);
+ uint8_t* dest_col = (uint8_t*)malloc(bypp*head.biHeight);
+
+ dbScaler = 50.0f/head.biWidth;
+
+ for (x=0;x<head.biWidth;x++)
+ {
+ if (info.nEscape) break;
+ info.nProgress = (int32_t)(50.0f+x*dbScaler);
+
+ itTmp.GetCol(cur_col, x);
+ itDst.GetCol(dest_col, x);
+ blur_line(ctable, cmatrix, cmatrix_length, cur_col, dest_col, head.biHeight, bypp);
+ itDst.SetCol(dest_col, x);
+ }
+
+ free(cur_col);
+ free(dest_col);
+
+ delete [] cmatrix;
+ delete [] ctable;
+
+#if CXIMAGE_SUPPORT_SELECTION
+ //restore the non selected region
+ if (pSelection){
+ for(y=0; y<head.biHeight; y++){
+ for(x=0; x<head.biWidth; x++){
+ if (!BlindSelectionIsInside(x,y)){
+ tmp_y.BlindSetPixelColor(x,y,BlindGetPixelColor(x,y));
+ }
+ }
+ }
+ }
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+ //if necessary, restore the original BPP and palette
+ if (pPalette){
+ tmp_y.DecreaseBpp(bpp, false, pPalette);
+ if (iDst) DecreaseBpp(bpp, false, pPalette);
+ delete [] pPalette;
+ }
+
+ if (iDst) iDst->Transfer(tmp_y);
+ else Transfer(tmp_y);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \author [DP],[nipper]
+ */
+bool CxImage::SelectiveBlur(float radius, uint8_t threshold, CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ RGBQUAD* pPalette=NULL;
+ uint16_t bpp = GetBpp();
+
+ CxImage Tmp(*this, true, true, true);
+ if (!Tmp.IsValid()){
+ strcpy(info.szLastError,Tmp.GetLastError());
+ return false;
+ }
+
+ //the routine is optimized for RGB or GrayScale images
+ if (!(head.biBitCount == 24 || IsGrayScale())){
+ pPalette = new RGBQUAD[head.biClrUsed];
+ memcpy(pPalette, GetPalette(),GetPaletteSize());
+ if (!Tmp.IncreaseBpp(24)){
+ delete [] pPalette;
+ return false;
+ }
+ }
+
+ CxImage Dst(Tmp, true, true, true);
+ if (!Dst.IsValid()){
+ strcpy(info.szLastError,Dst.GetLastError());
+ delete [] pPalette;
+ return false;
+ }
+
+ //build the difference mask
+ uint8_t thresh_dw = (uint8_t)max( 0 ,(int32_t)(128 - threshold));
+ uint8_t thresh_up = (uint8_t)min(255,(int32_t)(128 + threshold));
+ int32_t kernel[]={-100,-100,-100,-100,801,-100,-100,-100,-100};
+ if (!Tmp.Filter(kernel,3,800,128)){
+ strcpy(info.szLastError,Tmp.GetLastError());
+ delete [] pPalette;
+ return false;
+ }
+
+ //if the image has no selection, build a selection for the whole image
+#if CXIMAGE_SUPPORT_SELECTION
+ if (!Tmp.SelectionIsValid()){
+ Tmp.SelectionCreate();
+ Tmp.SelectionClear(255);
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ xmin = Tmp.info.rSelectionBox.left;
+ xmax = Tmp.info.rSelectionBox.right;
+ ymin = Tmp.info.rSelectionBox.bottom;
+ ymax = Tmp.info.rSelectionBox.top;
+
+ //modify the selection where the difference mask is over the threshold
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+ if(Tmp.BlindSelectionIsInside(x,y)){
+ RGBQUAD c = Tmp.BlindGetPixelColor(x,y);
+ if ((c.rgbRed < thresh_dw || c.rgbRed > thresh_up) ||
+ (c.rgbGreen < thresh_dw || c.rgbGreen > thresh_up) ||
+ (c.rgbBlue < thresh_dw || c.rgbBlue > thresh_up))
+ {
+ Tmp.SelectionSet(x,y,0);
+ }
+ }
+ }
+ }
+
+ //blur the image (only in the selected pixels)
+ Dst.SelectionCopy(Tmp);
+ if (!Dst.GaussianBlur(radius)){
+ strcpy(info.szLastError,Dst.GetLastError());
+ delete [] pPalette;
+ return false;
+ }
+
+ //restore the original selection
+ Dst.SelectionCopy(*this);
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+ //if necessary, restore the original BPP and palette
+ if (pPalette){
+ Dst.DecreaseBpp(bpp, false, pPalette);
+ delete [] pPalette;
+ }
+
+ if (iDst) iDst->Transfer(Dst);
+ else Transfer(Dst);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * sharpen the image by subtracting a blurred copy from the original image.
+ * \param radius: width in pixels of the blurring effect. Range: >0; default = 5.
+ * \param amount: strength of the filter. Range: 0.0 (none) to 1.0 (max); default = 0.5
+ * \param threshold: difference, between blurred and original pixel, to trigger the filter
+ * Range: 0 (always triggered) to 255 (never triggered); default = 0.
+ * \return true if everything is ok
+ * \author [nipper]; changes [DP]
+ */
+bool CxImage::UnsharpMask(float radius /*= 5.0*/, float amount /*= 0.5*/, int32_t threshold /*= 0*/)
+{
+ if (!pDib) return false;
+
+ RGBQUAD* pPalette=NULL;
+ uint16_t bpp = GetBpp();
+
+ //the routine is optimized for RGB or GrayScale images
+ if (!(head.biBitCount == 24 || IsGrayScale())){
+ pPalette = new RGBQUAD[head.biClrUsed];
+ memcpy(pPalette, GetPalette(),GetPaletteSize());
+ if (!IncreaseBpp(24))
+ return false;
+ }
+
+ CxImage iDst;
+ if (!GaussianBlur(radius,&iDst))
+ return false;
+
+ CImageIterator itSrc(this);
+ CImageIterator itDst(&iDst);
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ if (xmin==xmax || ymin==ymax)
+ return false;
+
+ double dbScaler = 100.0/(ymax-ymin);
+ int32_t bypp = head.biBitCount>>3;
+
+ // merge the source and destination (which currently contains
+ // the blurred version) images
+ for (int32_t y=ymin; y<ymax; y++)
+ {
+ if (info.nEscape) break;
+ info.nProgress = (int32_t)((y-ymin)*dbScaler);
+
+ // get source row
+ uint8_t* cur_row = itSrc.GetRow(y);
+ // get dest row
+ uint8_t* dest_row = itDst.GetRow(y);
+ // combine the two
+ for (int32_t x=xmin; x<xmax; x++) {
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ for (int32_t b=0, z=x*bypp; b<bypp; b++, z++){
+ int32_t diff = cur_row[z] - dest_row[z];
+
+ // do tresholding
+ if (abs(diff) < threshold){
+ dest_row[z] = cur_row[z];
+ } else {
+ dest_row[z] = (uint8_t)min(255, max(0,(int32_t)(cur_row[z] + amount * diff)));
+ }
+ }
+ }
+ }
+ }
+
+ //if necessary, restore the original BPP and palette
+ if (pPalette){
+ iDst.DecreaseBpp(bpp, false, pPalette);
+ delete [] pPalette;
+ }
+
+ Transfer(iDst);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Apply a look up table to the image.
+ * \param pLut: uint8_t[256] look up table
+ * \return true if everything is ok
+ */
+bool CxImage::Lut(uint8_t* pLut)
+{
+ if (!pDib || !pLut) return false;
+ RGBQUAD color;
+
+ double dbScaler;
+ if (head.biClrUsed==0){
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ // faster loop for full image
+ uint8_t *iSrc=info.pImage;
+ for(uint32_t i=0; i < head.biSizeImage ; i++){
+ *iSrc++ = pLut[*iSrc];
+ }
+ return true;
+ }
+
+ if (xmin==xmax || ymin==ymax)
+ return false;
+
+ dbScaler = 100.0/(ymax-ymin);
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)((y-ymin)*dbScaler); //<Anatoly Ivasyuk>
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ color = BlindGetPixelColor(x,y);
+ color.rgbRed = pLut[color.rgbRed];
+ color.rgbGreen = pLut[color.rgbGreen];
+ color.rgbBlue = pLut[color.rgbBlue];
+ BlindSetPixelColor(x,y,color);
+ }
+ }
+ }
+#if CXIMAGE_SUPPORT_SELECTION
+ } else if (pSelection && (head.biBitCount==8) && IsGrayScale()){
+ int32_t xmin,xmax,ymin,ymax;
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+
+ if (xmin==xmax || ymin==ymax)
+ return false;
+
+ dbScaler = 100.0/(ymax-ymin);
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)((y-ymin)*dbScaler);
+ for(int32_t x=xmin; x<xmax; x++){
+ if (BlindSelectionIsInside(x,y))
+ {
+ BlindSetPixelIndex(x,y,pLut[BlindGetPixelIndex(x,y)]);
+ }
+ }
+ }
+#endif //CXIMAGE_SUPPORT_SELECTION
+ } else {
+ bool bIsGrayScale = IsGrayScale();
+ for(uint32_t j=0; j<head.biClrUsed; j++){
+ color = GetPaletteColor((uint8_t)j);
+ color.rgbRed = pLut[color.rgbRed];
+ color.rgbGreen = pLut[color.rgbGreen];
+ color.rgbBlue = pLut[color.rgbBlue];
+ SetPaletteColor((uint8_t)j,color);
+ }
+ if (bIsGrayScale) GrayScale();
+ }
+ return true;
+
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Apply an indipendent look up table for each channel
+ * \param pLutR, pLutG, pLutB, pLutA: uint8_t[256] look up tables
+ * \return true if everything is ok
+ */
+bool CxImage::Lut(uint8_t* pLutR, uint8_t* pLutG, uint8_t* pLutB, uint8_t* pLutA)
+{
+ if (!pDib || !pLutR || !pLutG || !pLutB) return false;
+ RGBQUAD color;
+
+ double dbScaler;
+ if (head.biClrUsed==0){
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ if (xmin==xmax || ymin==ymax)
+ return false;
+
+ dbScaler = 100.0/(ymax-ymin);
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)((y-ymin)*dbScaler);
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ color = BlindGetPixelColor(x,y);
+ color.rgbRed = pLutR[color.rgbRed];
+ color.rgbGreen = pLutG[color.rgbGreen];
+ color.rgbBlue = pLutB[color.rgbBlue];
+ if (pLutA) color.rgbReserved=pLutA[color.rgbReserved];
+ BlindSetPixelColor(x,y,color,true);
+ }
+ }
+ }
+ } else {
+ bool bIsGrayScale = IsGrayScale();
+ for(uint32_t j=0; j<head.biClrUsed; j++){
+ color = GetPaletteColor((uint8_t)j);
+ color.rgbRed = pLutR[color.rgbRed];
+ color.rgbGreen = pLutG[color.rgbGreen];
+ color.rgbBlue = pLutB[color.rgbBlue];
+ SetPaletteColor((uint8_t)j,color);
+ }
+ if (bIsGrayScale) GrayScale();
+ }
+
+ return true;
+
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Use the RedEyeRemove function to remove the red-eye effect that frequently
+ * occurs in photographs of humans and animals. You must select the region
+ * where the function will filter the red channel.
+ * \param strength: range from 0.0f (no effect) to 1.0f (full effect). Default = 0.8
+ * \return true if everything is ok
+ */
+bool CxImage::RedEyeRemove(float strength)
+{
+ if (!pDib) return false;
+ RGBQUAD color;
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ if (xmin==xmax || ymin==ymax)
+ return false;
+
+ if (strength<0.0f) strength = 0.0f;
+ if (strength>1.0f) strength = 1.0f;
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ float a = 1.0f-5.0f*((float)((x-0.5f*(xmax+xmin))*(x-0.5f*(xmax+xmin))+(y-0.5f*(ymax+ymin))*(y-0.5f*(ymax+ymin))))/((float)((xmax-xmin)*(ymax-ymin)));
+ if (a<0) a=0;
+ color = BlindGetPixelColor(x,y);
+ color.rgbRed = (uint8_t)(a*min(color.rgbGreen,color.rgbBlue)+(1.0f-a)*color.rgbRed);
+ BlindSetPixelColor(x,y,color);
+ }
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Changes the saturation of the image.
+ * \param saturation: can be from -100 to 100, positive values increase the saturation.
+ * \param colorspace: can be 1 (HSL) or 2 (YUV).
+ * \return true if everything is ok
+ */
+bool CxImage::Saturate(const int32_t saturation, const int32_t colorspace)
+{
+ if (!pDib)
+ return false;
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ if (xmin==xmax || ymin==ymax)
+ return false;
+
+ uint8_t cTable[256];
+
+ switch(colorspace)
+ {
+ case 1:
+ {
+ for (int32_t i=0;i<256;i++) {
+ cTable[i] = (uint8_t)max(0,min(255,(int32_t)(i + saturation)));
+ }
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ RGBQUAD c = RGBtoHSL(BlindGetPixelColor(x,y));
+ c.rgbGreen = cTable[c.rgbGreen];
+ c = HSLtoRGB(c);
+ BlindSetPixelColor(x,y,c);
+ }
+ }
+ }
+ }
+ break;
+ case 2:
+ {
+ for (int32_t i=0;i<256;i++) {
+ cTable[i] = (uint8_t)max(0,min(255,(int32_t)((i-128)*(100 + saturation)/100.0f + 128.5f)));
+ }
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ RGBQUAD c = RGBtoYUV(BlindGetPixelColor(x,y));
+ c.rgbGreen = cTable[c.rgbGreen];
+ c.rgbBlue = cTable[c.rgbBlue];
+ c = YUVtoRGB(c);
+ BlindSetPixelColor(x,y,c);
+ }
+ }
+ }
+ }
+ break;
+ default:
+ strcpy(info.szLastError,"Saturate: wrong colorspace");
+ return false;
+ }
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Solarize: convert all colors above a given lightness level into their negative
+ * \param level : lightness threshold. Range = 0 to 255; default = 128.
+ * \param bLinkedChannels: true = compare with luminance, preserve colors (default)
+ * false = compare with independent R,G,B levels
+ * \return true if everything is ok
+ * \author [Priyank Bolia] (priyank_bolia(at)yahoo(dot)com); changes [DP]
+ */
+bool CxImage::Solarize(uint8_t level, bool bLinkedChannels)
+{
+ if (!pDib) return false;
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ if (head.biBitCount<=8){
+ if (IsGrayScale()){ //GRAYSCALE, selection
+ for(int32_t y=ymin; y<ymax; y++){
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ uint8_t index = BlindGetPixelIndex(x,y);
+ RGBQUAD color = GetPaletteColor(index);
+ if ((uint8_t)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)>level){
+ BlindSetPixelIndex(x,y,255-index);
+ }
+ }
+ }
+ }
+ } else { //PALETTE, full image
+ RGBQUAD* ppal=GetPalette();
+ for(uint32_t i=0;i<head.biClrUsed;i++){
+ RGBQUAD color = GetPaletteColor((uint8_t)i);
+ if (bLinkedChannels){
+ if ((uint8_t)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)>level){
+ ppal[i].rgbBlue =(uint8_t)(255-ppal[i].rgbBlue);
+ ppal[i].rgbGreen =(uint8_t)(255-ppal[i].rgbGreen);
+ ppal[i].rgbRed =(uint8_t)(255-ppal[i].rgbRed);
+ }
+ } else {
+ if (color.rgbBlue>level) ppal[i].rgbBlue =(uint8_t)(255-ppal[i].rgbBlue);
+ if (color.rgbGreen>level) ppal[i].rgbGreen =(uint8_t)(255-ppal[i].rgbGreen);
+ if (color.rgbRed>level) ppal[i].rgbRed =(uint8_t)(255-ppal[i].rgbRed);
+ }
+ }
+ }
+ } else { //RGB, selection
+ for(int32_t y=ymin; y<ymax; y++){
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ RGBQUAD color = BlindGetPixelColor(x,y);
+ if (bLinkedChannels){
+ if ((uint8_t)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)>level){
+ color.rgbRed = (uint8_t)(255-color.rgbRed);
+ color.rgbGreen = (uint8_t)(255-color.rgbGreen);
+ color.rgbBlue = (uint8_t)(255-color.rgbBlue);
+ }
+ } else {
+ if (color.rgbBlue>level) color.rgbBlue =(uint8_t)(255-color.rgbBlue);
+ if (color.rgbGreen>level) color.rgbGreen =(uint8_t)(255-color.rgbGreen);
+ if (color.rgbRed>level) color.rgbRed =(uint8_t)(255-color.rgbRed);
+ }
+ BlindSetPixelColor(x,y,color);
+ }
+ }
+ }
+ }
+
+ //invert transparent color only in case of full image processing
+ if (pSelection==0 || (!IsGrayScale() && IsIndexed())){
+ if (bLinkedChannels){
+ if ((uint8_t)RGB2GRAY(info.nBkgndColor.rgbRed,info.nBkgndColor.rgbGreen,info.nBkgndColor.rgbBlue)>level){
+ info.nBkgndColor.rgbBlue = (uint8_t)(255-info.nBkgndColor.rgbBlue);
+ info.nBkgndColor.rgbGreen = (uint8_t)(255-info.nBkgndColor.rgbGreen);
+ info.nBkgndColor.rgbRed = (uint8_t)(255-info.nBkgndColor.rgbRed);
+ }
+ } else {
+ if (info.nBkgndColor.rgbBlue>level) info.nBkgndColor.rgbBlue = (uint8_t)(255-info.nBkgndColor.rgbBlue);
+ if (info.nBkgndColor.rgbGreen>level) info.nBkgndColor.rgbGreen = (uint8_t)(255-info.nBkgndColor.rgbGreen);
+ if (info.nBkgndColor.rgbRed>level) info.nBkgndColor.rgbRed = (uint8_t)(255-info.nBkgndColor.rgbRed);
+ }
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Converts the RGB triplets to and from different colorspace
+ * \param dstColorSpace: destination colorspace; 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ
+ * \param srcColorSpace: source colorspace; 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ
+ * \return true if everything is ok
+ */
+bool CxImage::ConvertColorSpace(const int32_t dstColorSpace, const int32_t srcColorSpace)
+{
+ if (!pDib)
+ return false;
+
+ if (dstColorSpace == srcColorSpace)
+ return true;
+
+ int32_t w = GetWidth();
+ int32_t h = GetHeight();
+
+ for (int32_t y=0;y<h;y++){
+ info.nProgress = (int32_t)(100*y/h);
+ if (info.nEscape) break;
+ for (int32_t x=0;x<w;x++){
+ RGBQUAD c = BlindGetPixelColor(x,y);
+ switch (srcColorSpace){
+ case 0:
+ break;
+ case 1:
+ c = HSLtoRGB(c);
+ break;
+ case 2:
+ c = YUVtoRGB(c);
+ break;
+ case 3:
+ c = YIQtoRGB(c);
+ break;
+ case 4:
+ c = XYZtoRGB(c);
+ break;
+ default:
+ strcpy(info.szLastError,"ConvertColorSpace: unknown source colorspace");
+ return false;
+ }
+ switch (dstColorSpace){
+ case 0:
+ break;
+ case 1:
+ c = RGBtoHSL(c);
+ break;
+ case 2:
+ c = RGBtoYUV(c);
+ break;
+ case 3:
+ c = RGBtoYIQ(c);
+ break;
+ case 4:
+ c = RGBtoXYZ(c);
+ break;
+ default:
+ strcpy(info.szLastError,"ConvertColorSpace: unknown destination colorspace");
+ return false;
+ }
+ BlindSetPixelColor(x,y,c);
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Finds the optimal (global or local) treshold for image binarization
+ * \param method: 0 = average all methods (default); 1 = Otsu; 2 = Kittler & Illingworth; 3 = max entropy; 4 = potential difference;
+ * \param pBox: region from where the threshold is computed; 0 = full image (default).
+ * \param pContrastMask: limit the computation only in regions with contrasted (!=0) pixels; default = 0.
+ * the pContrastMask image must be grayscale with same with and height of the current image,
+ * can be obtained from the current image with a filter:
+ * CxImage iContrastMask(*image,true,false,false);
+ * iContrastMask.GrayScale();
+ * int32_t edge[]={-1,-1,-1,-1,8,-1,-1,-1,-1};
+ * iContrastMask.Filter(edge,3,1,0);
+ * int32_t blur[]={1,1,1,1,1,1,1,1,1};
+ * iContrastMask.Filter(blur,3,9,0);
+ * \return optimal threshold; -1 = error.
+ * \sa AdaptiveThreshold
+ */
+int32_t CxImage::OptimalThreshold(int32_t method, RECT * pBox, CxImage* pContrastMask)
+{
+ if (!pDib)
+ return false;
+
+ if (head.biBitCount!=8){
+ strcpy(info.szLastError,"OptimalThreshold works only on 8 bit images");
+ return -1;
+ }
+
+ if (pContrastMask){
+ if (!pContrastMask->IsValid() ||
+ !pContrastMask->IsGrayScale() ||
+ pContrastMask->GetWidth() != GetWidth() ||
+ pContrastMask->GetHeight() != GetHeight()){
+ strcpy(info.szLastError,"OptimalThreshold invalid ContrastMask");
+ return -1;
+ }
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pBox){
+ xmin = max(pBox->left,0);
+ xmax = min(pBox->right,head.biWidth);
+ ymin = max(pBox->bottom,0);
+ ymax = min(pBox->top,head.biHeight);
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ if (xmin>=xmax || ymin>=ymax)
+ return -1;
+
+ double p[256];
+ memset(p, 0, 256*sizeof(double));
+ //build histogram
+ for (int32_t y = ymin; y<ymax; y++){
+ uint8_t* pGray = GetBits(y) + xmin;
+ uint8_t* pContr = 0;
+ if (pContrastMask) pContr = pContrastMask->GetBits(y) + xmin;
+ for (int32_t x = xmin; x<xmax; x++){
+ uint8_t n = *pGray++;
+ if (pContr){
+ if (*pContr) p[n]++;
+ pContr++;
+ } else {
+ p[n]++;
+ }
+ }
+ }
+
+ //find histogram limits
+ int32_t gray_min = 0;
+ while (gray_min<255 && p[gray_min]==0) gray_min++;
+ int32_t gray_max = 255;
+ while (gray_max>0 && p[gray_max]==0) gray_max--;
+ if (gray_min > gray_max)
+ return -1;
+ if (gray_min == gray_max){
+ if (gray_min == 0)
+ return 0;
+ else
+ return gray_max-1;
+ }
+
+ //compute total moments 0th,1st,2nd order
+ int32_t i,k;
+ double w_tot = 0;
+ double m_tot = 0;
+ double q_tot = 0;
+ for (i = gray_min; i <= gray_max; i++){
+ w_tot += p[i];
+ m_tot += i*p[i];
+ q_tot += i*i*p[i];
+ }
+
+ double L, L1max, L2max, L3max, L4max; //objective functions
+ int32_t th1,th2,th3,th4; //optimal thresholds
+ L1max = L2max = L3max = L4max = 0;
+ th1 = th2 = th3 = th4 = -1;
+
+ double w1, w2, m1, m2, q1, q2, s1, s2;
+ w1 = m1 = q1 = 0;
+ for (i = gray_min; i < gray_max; i++){
+ w1 += p[i];
+ w2 = w_tot - w1;
+ m1 += i*p[i];
+ m2 = m_tot - m1;
+ q1 += i*i*p[i];
+ q2 = q_tot - q1;
+ s1 = q1/w1-m1*m1/w1/w1; //s1 = q1/w1-pow(m1/w1,2);
+ s2 = q2/w2-m2*m2/w2/w2; //s2 = q2/w2-pow(m2/w2,2);
+
+ //Otsu
+ L = -(s1*w1 + s2*w2); //implemented as definition
+ //L = w1 * w2 * (m2/w2 - m1/w1)*(m2/w2 - m1/w1); //implementation that doesn't need s1 & s2
+ if (L1max < L || th1<0){
+ L1max = L;
+ th1 = i;
+ }
+
+ //Kittler and Illingworth
+ if (s1>0 && s2>0){
+ L = w1*log(w1/sqrt(s1))+w2*log(w2/sqrt(s2));
+ //L = w1*log(w1*w1/s1)+w2*log(w2*w2/s2);
+ if (L2max < L || th2<0){
+ L2max = L;
+ th2 = i;
+ }
+ }
+
+ //max entropy
+ L = 0;
+ for (k=gray_min;k<=i;k++) if (p[k] > 0) L -= p[k]*log(p[k]/w1)/w1;
+ for (k;k<=gray_max;k++) if (p[k] > 0) L -= p[k]*log(p[k]/w2)/w2;
+ if (L3max < L || th3<0){
+ L3max = L;
+ th3 = i;
+ }
+
+ //potential difference (based on Electrostatic Binarization method by J. Acharya & G. Sreechakra)
+ // L=-fabs(vdiff/vsum); è molto selettivo, sembra che L=-fabs(vdiff) o L=-(vsum)
+ // abbiano lo stesso valore di soglia... il che semplificherebbe molto la routine
+ double vdiff = 0;
+ for (k=gray_min;k<=i;k++)
+ vdiff += p[k]*(i-k)*(i-k);
+ double vsum = vdiff;
+ for (k;k<=gray_max;k++){
+ double dv = p[k]*(k-i)*(k-i);
+ vdiff -= dv;
+ vsum += dv;
+ }
+ if (vsum>0) L = -fabs(vdiff/vsum); else L = 0;
+ if (L4max < L || th4<0){
+ L4max = L;
+ th4 = i;
+ }
+ }
+
+ int32_t threshold;
+ switch (method){
+ case 1: //Otsu
+ threshold = th1;
+ break;
+ case 2: //Kittler and Illingworth
+ threshold = th2;
+ break;
+ case 3: //max entropy
+ threshold = th3;
+ break;
+ case 4: //potential difference
+ threshold = th4;
+ break;
+ default: //auto
+ {
+ int32_t nt = 0;
+ threshold = 0;
+ if (th1>=0) { threshold += th1; nt++;}
+ if (th2>=0) { threshold += th2; nt++;}
+ if (th3>=0) { threshold += th3; nt++;}
+ if (th4>=0) { threshold += th4; nt++;}
+ if (nt)
+ threshold /= nt;
+ else
+ threshold = (gray_min+gray_max)/2;
+
+ /*better(?) but really expensive alternative:
+ n = 0:255;
+ pth1 = c1(th1)/sqrt(2*pi*s1(th1))*exp(-((n - m1(th1)).^2)/2/s1(th1)) + c2(th1)/sqrt(2*pi*s2(th1))*exp(-((n - m2(th1)).^2)/2/s2(th1));
+ pth2 = c1(th2)/sqrt(2*pi*s1(th2))*exp(-((n - m1(th2)).^2)/2/s1(th2)) + c2(th2)/sqrt(2*pi*s2(th2))*exp(-((n - m2(th2)).^2)/2/s2(th2));
+ ...
+ mse_th1 = sum((p-pth1).^2);
+ mse_th2 = sum((p-pth2).^2);
+ ...
+ select th# that gives minimum mse_th#
+ */
+
+ }
+ }
+
+ if (threshold <= gray_min || threshold >= gray_max)
+ threshold = (gray_min+gray_max)/2;
+
+ return threshold;
+}
+///////////////////////////////////////////////////////////////////////////////
+/**
+ * Converts the image to B&W, using an optimal threshold mask
+ * \param method: 0 = average all methods (default); 1 = Otsu; 2 = Kittler & Illingworth; 3 = max entropy; 4 = potential difference;
+ * \param nBoxSize: the image is divided into "nBoxSize x nBoxSize" blocks, from where the threshold is computed; min = 8; default = 64.
+ * \param pContrastMask: limit the computation only in regions with contrasted (!=0) pixels; default = 0.
+ * \param nBias: global offset added to the threshold mask; default = 0.
+ * \param fGlobalLocalBalance: balance between local and global threshold. default = 0.5
+ * fGlobalLocalBalance can be from 0.0 (use only local threshold) to 1.0 (use only global threshold)
+ * the pContrastMask image must be grayscale with same with and height of the current image,
+ * \return true if everything is ok.
+ * \sa OptimalThreshold
+ */
+bool CxImage::AdaptiveThreshold(int32_t method, int32_t nBoxSize, CxImage* pContrastMask, int32_t nBias, float fGlobalLocalBalance)
+{
+ if (!pDib)
+ return false;
+
+ if (pContrastMask){
+ if (!pContrastMask->IsValid() ||
+ !pContrastMask->IsGrayScale() ||
+ pContrastMask->GetWidth() != GetWidth() ||
+ pContrastMask->GetHeight() != GetHeight()){
+ strcpy(info.szLastError,"AdaptiveThreshold invalid ContrastMask");
+ return false;
+ }
+ }
+
+ if (nBoxSize<8) nBoxSize = 8;
+ if (fGlobalLocalBalance<0.0f) fGlobalLocalBalance = 0.0f;
+ if (fGlobalLocalBalance>1.0f) fGlobalLocalBalance = 1.0f;
+
+ int32_t mw = (head.biWidth + nBoxSize - 1)/nBoxSize;
+ int32_t mh = (head.biHeight + nBoxSize - 1)/nBoxSize;
+
+ CxImage mask(mw,mh,8);
+ if(!mask.GrayScale())
+ return false;
+
+ if(!GrayScale())
+ return false;
+
+ int32_t globalthreshold = OptimalThreshold(method, 0, pContrastMask);
+ if (globalthreshold <0)
+ return false;
+
+ for (int32_t y=0; y<mh; y++){
+ for (int32_t x=0; x<mw; x++){
+ info.nProgress = (int32_t)(100*(x+y*mw)/(mw*mh));
+ if (info.nEscape) break;
+ RECT r;
+ r.left = x*nBoxSize;
+ r.right = r.left + nBoxSize;
+ r.bottom = y*nBoxSize;
+ r.top = r.bottom + nBoxSize;
+ int32_t threshold = OptimalThreshold(method, &r, pContrastMask);
+ if (threshold <0) return false;
+ mask.SetPixelIndex(x,y,(uint8_t)max(0,min(255,nBias+((1.0f-fGlobalLocalBalance)*threshold + fGlobalLocalBalance*globalthreshold))));
+ }
+ }
+
+ mask.Resample(mw*nBoxSize,mh*nBoxSize,0);
+ mask.Crop(0,head.biHeight,head.biWidth,0);
+
+ if(!Threshold(&mask))
+ return false;
+
+ return true;
+}
+///////////////////////////////////////////////////////////////////////////////
+/**
+ * Finds the contour of an object with a given color
+ * \param color_target: object color
+ * \param color_trace: contour color
+ * \return true if everything is ok.
+ * \sa Edge, Contour
+ */
+bool CxImage::Trace(RGBQUAD color_target, RGBQUAD color_trace)
+{
+ if (!pDib) return false;
+
+ RGBQUAD color;
+ bool bFindStartPoint;
+ int32_t nFindPoint;
+ POINT StartPoint,CurrentPoint;
+ int32_t Direction[8][2]={{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}, {0,1},{1,1}};
+ int32_t BeginDirect = 0;
+ int32_t x,y;
+
+ CxImage tmp;
+ tmp.CopyInfo(*this);
+ tmp.Create(head.biWidth,head.biHeight,24,info.dwType);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+ tmp.Clear(255);
+
+ CurrentPoint.x = StartPoint.x = CurrentPoint.y = StartPoint.y = 0;
+ bFindStartPoint = false;
+ for (y=head.biHeight-1;y>=0 && !bFindStartPoint;y--){
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ if (info.nEscape) break;
+ for (x=0;x<head.biWidth && !bFindStartPoint;x++){
+ color = BlindGetPixelColor(x,y);
+ if (color.rgbRed == color_target.rgbRed &&
+ color.rgbGreen == color_target.rgbGreen &&
+ color.rgbBlue == color_target.rgbBlue )
+ {
+ bFindStartPoint = true;
+ CurrentPoint.x = StartPoint.x = x;
+ CurrentPoint.y = StartPoint.y = y;
+ }
+ }
+ }
+
+ while(bFindStartPoint)
+ {
+ nFindPoint = 8;
+ while(nFindPoint)
+ {
+ x = CurrentPoint.x + Direction[BeginDirect][0];
+ y = CurrentPoint.y + Direction[BeginDirect][1];
+ color = GetPixelColor(x,y);
+
+ if (IsInside(x,y) &&
+ color.rgbRed == color_target.rgbRed &&
+ color.rgbGreen == color_target.rgbGreen &&
+ color.rgbBlue == color_target.rgbBlue )
+ {
+ nFindPoint = 0;
+ CurrentPoint.x = x;
+ CurrentPoint.y = y;
+
+ if(x == StartPoint.x && y == StartPoint.y)
+ bFindStartPoint = false;
+
+ tmp.BlindSetPixelColor(x,y,color_trace);
+
+ BeginDirect--;
+ if(BeginDirect == -1) BeginDirect = 7;
+ }
+ else
+ {
+ BeginDirect++;
+ if(BeginDirect == 8) BeginDirect = 0;
+ nFindPoint--;
+ if(nFindPoint == 0) {
+ bFindStartPoint = false;
+ tmp.SetPixelColor(CurrentPoint.x,CurrentPoint.y,color_trace);
+ }
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+
+#ifndef __MINGW32__
+////////////////////////////////////////////////////////////////////////////////
+#include <queue>
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Flood Fill
+ * \param xStart, yStart: starting point
+ * \param cFillColor: filling color
+ * \param nTolerance: deviation from the starting point color
+ * \param nOpacity: can be from 0 (transparent) to 255 (opaque, default)
+ * \param bSelectFilledArea: if true, the pixels in the region are also set in the selection layer; default = false
+ * \param nSelectionLevel: if bSelectFilledArea is true, the selected pixels are set to nSelectionLevel; default = 255
+ * Note: nOpacity=0 && bSelectFilledArea=true act as a "magic wand"
+ * \return true if everything is ok
+ */
+bool CxImage::FloodFill(const int32_t xStart, const int32_t yStart, const RGBQUAD cFillColor, const uint8_t nTolerance,
+ uint8_t nOpacity, const bool bSelectFilledArea, const uint8_t nSelectionLevel)
+{
+ if (!pDib)
+ return false;
+
+ if (!IsInside(xStart,yStart))
+ return true;
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (!SelectionIsInside(xStart,yStart))
+ return true;
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+ RGBQUAD* pPalette=NULL;
+ uint16_t bpp = GetBpp();
+ //nTolerance or nOpacity implemented only for grayscale or 24bpp images
+ if ((nTolerance || nOpacity != 255) && !(head.biBitCount == 24 || IsGrayScale())){
+ pPalette = new RGBQUAD[head.biClrUsed];
+ memcpy(pPalette, GetPalette(),GetPaletteSize());
+ if (!IncreaseBpp(24))
+ return false;
+ }
+
+ uint8_t* pFillMask = (uint8_t*)calloc(head.biWidth * head.biHeight,1);
+ if (!pFillMask)
+ return false;
+
+//------------------------------------- Begin of Flood Fill
+ POINT offset[4] = {{-1,0},{0,-1},{1,0},{0,1}};
+ std::queue<POINT> q;
+ POINT point = {xStart,yStart};
+ q.push(point);
+
+ if (IsIndexed()){ //--- Generic indexed image, no tolerance OR Grayscale image with tolerance
+ uint8_t idxRef = GetPixelIndex(xStart,yStart);
+ uint8_t idxFill = GetNearestIndex(cFillColor);
+ uint8_t idxMin = (uint8_t)min(255, max(0,(int32_t)(idxRef - nTolerance)));
+ uint8_t idxMax = (uint8_t)min(255, max(0,(int32_t)(idxRef + nTolerance)));
+
+ while(!q.empty())
+ {
+ point = q.front();
+ q.pop();
+
+ for (int32_t z=0; z<4; z++){
+ int32_t x = point.x + offset[z].x;
+ int32_t y = point.y + offset[z].y;
+ if(IsInside(x,y)){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ uint8_t idx = BlindGetPixelIndex(x, y);
+ uint8_t* pFill = pFillMask + x + y * head.biWidth;
+ if (*pFill==0 && idxMin <= idx && idx <= idxMax )
+ {
+ if (nOpacity>0){
+ if (nOpacity == 255)
+ BlindSetPixelIndex(x, y, idxFill);
+ else
+ BlindSetPixelIndex(x, y, (uint8_t)((idxFill * nOpacity + idx * (255-nOpacity))>>8));
+ }
+ POINT pt = {x,y};
+ q.push(pt);
+ *pFill = 1;
+ }
+ }
+ }
+ }
+ }
+ } else { //--- RGB image
+ RGBQUAD cRef = GetPixelColor(xStart,yStart);
+ RGBQUAD cRefMin, cRefMax;
+ cRefMin.rgbRed = (uint8_t)min(255, max(0,(int32_t)(cRef.rgbRed - nTolerance)));
+ cRefMin.rgbGreen = (uint8_t)min(255, max(0,(int32_t)(cRef.rgbGreen - nTolerance)));
+ cRefMin.rgbBlue = (uint8_t)min(255, max(0,(int32_t)(cRef.rgbBlue - nTolerance)));
+ cRefMax.rgbRed = (uint8_t)min(255, max(0,(int32_t)(cRef.rgbRed + nTolerance)));
+ cRefMax.rgbGreen = (uint8_t)min(255, max(0,(int32_t)(cRef.rgbGreen + nTolerance)));
+ cRefMax.rgbBlue = (uint8_t)min(255, max(0,(int32_t)(cRef.rgbBlue + nTolerance)));
+
+ while(!q.empty())
+ {
+ point = q.front();
+ q.pop();
+
+ for (int32_t z=0; z<4; z++){
+ int32_t x = point.x + offset[z].x;
+ int32_t y = point.y + offset[z].y;
+ if(IsInside(x,y)){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ RGBQUAD cc = BlindGetPixelColor(x, y);
+ uint8_t* pFill = pFillMask + x + y * head.biWidth;
+ if (*pFill==0 &&
+ cRefMin.rgbRed <= cc.rgbRed && cc.rgbRed <= cRefMax.rgbRed &&
+ cRefMin.rgbGreen <= cc.rgbGreen && cc.rgbGreen <= cRefMax.rgbGreen &&
+ cRefMin.rgbBlue <= cc.rgbBlue && cc.rgbBlue <= cRefMax.rgbBlue )
+ {
+ if (nOpacity>0){
+ if (nOpacity == 255)
+ BlindSetPixelColor(x, y, cFillColor);
+ else
+ {
+ cc.rgbRed = (uint8_t)((cFillColor.rgbRed * nOpacity + cc.rgbRed * (255-nOpacity))>>8);
+ cc.rgbGreen = (uint8_t)((cFillColor.rgbGreen * nOpacity + cc.rgbGreen * (255-nOpacity))>>8);
+ cc.rgbBlue = (uint8_t)((cFillColor.rgbBlue * nOpacity + cc.rgbBlue * (255-nOpacity))>>8);
+ BlindSetPixelColor(x, y, cc);
+ }
+ }
+ POINT pt = {x,y};
+ q.push(pt);
+ *pFill = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (pFillMask[xStart+yStart*head.biWidth] == 0 && nOpacity>0){
+ if (nOpacity == 255)
+ BlindSetPixelColor(xStart, yStart, cFillColor);
+ else
+ {
+ RGBQUAD cc = BlindGetPixelColor(xStart, yStart);
+ cc.rgbRed = (uint8_t)((cFillColor.rgbRed * nOpacity + cc.rgbRed * (255-nOpacity))>>8);
+ cc.rgbGreen = (uint8_t)((cFillColor.rgbGreen * nOpacity + cc.rgbGreen * (255-nOpacity))>>8);
+ cc.rgbBlue = (uint8_t)((cFillColor.rgbBlue * nOpacity + cc.rgbBlue * (255-nOpacity))>>8);
+ BlindSetPixelColor(xStart, yStart, cc);
+ }
+ }
+ pFillMask[xStart+yStart*head.biWidth] = 1;
+//------------------------------------- End of Flood Fill
+
+ //if necessary, restore the original BPP and palette
+ if (pPalette){
+ DecreaseBpp(bpp, false, pPalette);
+ delete [] pPalette;
+ }
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (bSelectFilledArea){
+ if (!SelectionIsValid()){
+ if (!SelectionCreate()){
+ return false;
+ }
+ SelectionClear();
+ info.rSelectionBox.right = head.biWidth;
+ info.rSelectionBox.top = head.biHeight;
+ info.rSelectionBox.left = info.rSelectionBox.bottom = 0;
+ }
+ RECT r;
+ SelectionGetBox(r);
+ for (int32_t y = r.bottom; y < r.top; y++){
+ uint8_t* pFill = pFillMask + r.left + y * head.biWidth;
+ for (int32_t x = r.left; x<r.right; x++){
+ if (*pFill) SelectionSet(x,y,nSelectionLevel);
+ pFill++;
+ }
+ }
+ SelectionRebuildBox();
+ }
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+ free(pFillMask);
+
+ return true;
+}
+#endif //__MINGW32__
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DSP
diff --git a/archive/hge/CxImage/ximaenc.cpp b/archive/hge/CxImage/ximaenc.cpp new file mode 100644 index 0000000..6064e49 --- /dev/null +++ b/archive/hge/CxImage/ximaenc.cpp @@ -0,0 +1,1159 @@ +// xImaCodec.cpp : Encode Decode functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_JPG
+#include "ximajpg.h"
+#endif
+
+#if CXIMAGE_SUPPORT_GIF
+#include "ximagif.h"
+#endif
+
+#if CXIMAGE_SUPPORT_PNG
+#include "ximapng.h"
+#endif
+
+#if CXIMAGE_SUPPORT_MNG
+#include "ximamng.h"
+#endif
+
+#if CXIMAGE_SUPPORT_BMP
+#include "ximabmp.h"
+#endif
+
+#if CXIMAGE_SUPPORT_ICO
+#include "ximaico.h"
+#endif
+
+#if CXIMAGE_SUPPORT_TIF
+#include "ximatif.h"
+#endif
+
+#if CXIMAGE_SUPPORT_TGA
+#include "ximatga.h"
+#endif
+
+#if CXIMAGE_SUPPORT_PCX
+#include "ximapcx.h"
+#endif
+
+#if CXIMAGE_SUPPORT_WBMP
+#include "ximawbmp.h"
+#endif
+
+#if CXIMAGE_SUPPORT_WMF
+#include "ximawmf.h" // <vho> - WMF/EMF support
+#endif
+
+#if CXIMAGE_SUPPORT_JBG
+#include "ximajbg.h"
+#endif
+
+#if CXIMAGE_SUPPORT_JASPER
+#include "ximajas.h"
+#endif
+
+#if CXIMAGE_SUPPORT_SKA
+#include "ximaska.h"
+#endif
+
+#if CXIMAGE_SUPPORT_RAW
+#include "ximaraw.h"
+#endif
+
+#if CXIMAGE_SUPPORT_PSD
+#include "ximapsd.h"
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::EncodeSafeCheck(CxFile *hFile)
+{
+ if (hFile==NULL) {
+ strcpy(info.szLastError,CXIMAGE_ERR_NOFILE);
+ return true;
+ }
+
+ if (pDib==NULL){
+ strcpy(info.szLastError,CXIMAGE_ERR_NOIMAGE);
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+//#ifdef WIN32
+//bool CxImage::Save(LPCWSTR filename, uint32_t imagetype)
+//{
+// FILE* hFile; //file handle to write the image
+// if ((hFile=_wfopen(filename,L"wb"))==NULL) return false;
+// bool bOK = Encode(hFile,imagetype);
+// fclose(hFile);
+// return bOK;
+//}
+//#endif //WIN32
+////////////////////////////////////////////////////////////////////////////////
+// For UNICODE support: char -> TCHAR
+/**
+ * Saves to disk the image in a specific format.
+ * \param filename: file name
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Save(const TCHAR * filename, uint32_t imagetype)
+{
+ FILE* hFile; //file handle to write the image
+
+#ifdef WIN32
+ if ((hFile=_tfopen(filename,_T("wb")))==NULL) return false; // For UNICODE support
+#else
+ if ((hFile=fopen(filename,"wb"))==NULL) return false;
+#endif
+
+ bool bOK = Encode(hFile,imagetype);
+ fclose(hFile);
+ return bOK;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to disk the image in a specific format.
+ * \param hFile: file handle, open and enabled for writing.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Encode(FILE *hFile, uint32_t imagetype)
+{
+ CxIOFile file(hFile);
+ return Encode(&file,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to memory buffer the image in a specific format.
+ * \param buffer: output memory buffer pointer. Must be NULL,
+ * the function allocates and fill the memory,
+ * the application must free the buffer, see also FreeMemory().
+ * \param size: output memory buffer size.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Encode(uint8_t * &buffer, int32_t &size, uint32_t imagetype)
+{
+ if (buffer!=NULL){
+ strcpy(info.szLastError,"the buffer must be empty");
+ return false;
+ }
+ CxMemFile file;
+ file.Open();
+ if(Encode(&file,imagetype)){
+ buffer=file.GetBuffer();
+ size=file.Size();
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to disk the image in a specific format.
+ * \param hFile: file handle (CxMemFile or CxIOFile), with write access.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ * \sa ENUM_CXIMAGE_FORMATS
+ */
+bool CxImage::Encode(CxFile *hFile, uint32_t imagetype)
+{
+
+#if CXIMAGE_SUPPORT_BMP
+ if (CXIMAGE_FORMAT_BMP==imagetype){
+ CxImageBMP *newima = new CxImageBMP;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ if (CXIMAGE_FORMAT_ICO==imagetype){
+ CxImageICO *newima = new CxImageICO;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_TIF
+ if (CXIMAGE_FORMAT_TIF==imagetype){
+ CxImageTIF *newima = new CxImageTIF;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JPG
+ if (CXIMAGE_FORMAT_JPG==imagetype){
+ CxImageJPG *newima = new CxImageJPG;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ if (CXIMAGE_FORMAT_GIF==imagetype){
+ CxImageGIF *newima = new CxImageGIF;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_PNG
+ if (CXIMAGE_FORMAT_PNG==imagetype){
+ CxImagePNG *newima = new CxImagePNG;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_MNG
+ if (CXIMAGE_FORMAT_MNG==imagetype){
+ CxImageMNG *newima = new CxImageMNG;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_TGA
+ if (CXIMAGE_FORMAT_TGA==imagetype){
+ CxImageTGA *newima = new CxImageTGA;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_PCX
+ if (CXIMAGE_FORMAT_PCX==imagetype){
+ CxImagePCX *newima = new CxImagePCX;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+ if (CXIMAGE_FORMAT_WBMP==imagetype){
+ CxImageWBMP *newima = new CxImageWBMP;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // <vho> - WMF/EMF support
+ if (CXIMAGE_FORMAT_WMF==imagetype){
+ CxImageWMF *newima = new CxImageWMF;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JBG
+ if (CXIMAGE_FORMAT_JBG==imagetype){
+ CxImageJBG *newima = new CxImageJBG;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JASPER
+ if (
+ #if CXIMAGE_SUPPORT_JP2
+ CXIMAGE_FORMAT_JP2==imagetype ||
+ #endif
+ #if CXIMAGE_SUPPORT_JPC
+ CXIMAGE_FORMAT_JPC==imagetype ||
+ #endif
+ #if CXIMAGE_SUPPORT_PGX
+ CXIMAGE_FORMAT_PGX==imagetype ||
+ #endif
+ #if CXIMAGE_SUPPORT_PNM
+ CXIMAGE_FORMAT_PNM==imagetype ||
+ #endif
+ #if CXIMAGE_SUPPORT_RAS
+ CXIMAGE_FORMAT_RAS==imagetype ||
+ #endif
+ false ){
+ CxImageJAS *newima = new CxImageJAS;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile,imagetype)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+
+#if CXIMAGE_SUPPORT_SKA
+ if (CXIMAGE_FORMAT_SKA==imagetype){
+ CxImageSKA *newima = new CxImageSKA;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+
+#if CXIMAGE_SUPPORT_RAW
+ if (CXIMAGE_FORMAT_RAW==imagetype){
+ CxImageRAW *newima = new CxImageRAW;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+
+#if CXIMAGE_SUPPORT_PSD
+ if (CXIMAGE_FORMAT_PSD==imagetype){
+ CxImagePSD *newima = new CxImagePSD;
+ if (!newima) return false;
+ newima->Ghost(this);
+ if (newima->Encode(hFile)){
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ delete newima;
+ return false;
+ }
+ }
+#endif
+
+ strcpy(info.szLastError,"Encode: Unknown format");
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to disk or memory pagecount images, referenced by an array of CxImage pointers.
+ * \param hFile: file handle.
+ * \param pImages: array of CxImage pointers.
+ * \param pagecount: number of images.
+ * \param imagetype: can be CXIMAGE_FORMAT_TIF or CXIMAGE_FORMAT_GIF.
+ * \return true if everything is ok
+ */
+bool CxImage::Encode(FILE * hFile, CxImage ** pImages, int32_t pagecount, uint32_t imagetype)
+{
+ CxIOFile file(hFile);
+ return Encode(&file, pImages, pagecount,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Saves to disk or memory pagecount images, referenced by an array of CxImage pointers.
+ * \param hFile: file handle (CxMemFile or CxIOFile), with write access.
+ * \param pImages: array of CxImage pointers.
+ * \param pagecount: number of images.
+ * \param imagetype: can be CXIMAGE_FORMAT_TIF, CXIMAGE_FORMAT_GIF or CXIMAGE_FORMAT_ICO.
+ * \return true if everything is ok
+ */
+bool CxImage::Encode(CxFile * hFile, CxImage ** pImages, int32_t pagecount, uint32_t imagetype)
+{
+#if CXIMAGE_SUPPORT_TIF
+ if (imagetype==CXIMAGE_FORMAT_TIF){
+ CxImageTIF newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile,pImages,pagecount)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ if (imagetype==CXIMAGE_FORMAT_GIF){
+ CxImageGIF newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile,pImages,pagecount)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ if (imagetype==CXIMAGE_FORMAT_ICO){
+ CxImageICO newima;
+ newima.Ghost(this);
+ if (newima.Encode(hFile,pImages,pagecount)){
+ return true;
+ } else {
+ strcpy(info.szLastError,newima.GetLastError());
+ return false;
+ }
+ }
+#endif
+ strcpy(info.szLastError,"Multipage Encode, Unsupported operation for this format");
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * exports the image into a RGBA buffer, Useful for OpenGL applications.
+ * \param buffer: output memory buffer pointer. Must be NULL,
+ * the function allocates and fill the memory,
+ * the application must free the buffer, see also FreeMemory().
+ * \param size: output memory buffer size.
+ * \param bFlipY: direction of Y axis. default = false.
+ * \return true if everything is ok
+ */
+bool CxImage::Encode2RGBA(uint8_t * &buffer, int32_t &size, bool bFlipY)
+{
+ if (buffer!=NULL){
+ strcpy(info.szLastError,"the buffer must be empty");
+ return false;
+ }
+ CxMemFile file;
+ file.Open();
+ if(Encode2RGBA(&file,bFlipY)){
+ buffer=file.GetBuffer();
+ size=file.Size();
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * exports the image into a RGBA buffer, Useful for OpenGL applications.
+ * \param hFile: file handle (CxMemFile or CxIOFile), with write access.
+ * \param bFlipY: direction of Y axis. default = false.
+ * \return true if everything is ok
+ */
+bool CxImage::Encode2RGBA(CxFile *hFile, bool bFlipY)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ for (int32_t y1 = 0; y1 < head.biHeight; y1++) {
+ int32_t y = bFlipY ? head.biHeight - 1 - y1 : y1;
+ for(int32_t x = 0; x < head.biWidth; x++) {
+ RGBQUAD color = BlindGetPixelColor(x,y);
+ hFile->PutC(color.rgbRed);
+ hFile->PutC(color.rgbGreen);
+ hFile->PutC(color.rgbBlue);
+ hFile->PutC(color.rgbReserved);
+ }
+ }
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+// For UNICODE support: char -> TCHAR
+/**
+ * Reads from disk the image in a specific format.
+ * - If decoding fails using the specified image format,
+ * the function will try the automatic file format recognition.
+ *
+ * \param filename: file name
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Load(const TCHAR * filename, uint32_t imagetype)
+//bool CxImage::Load(const char * filename, uint32_t imagetype)
+{
+ /*FILE* hFile; //file handle to read the image
+ if ((hFile=fopen(filename,"rb"))==NULL) return false;
+ bool bOK = Decode(hFile,imagetype);
+ fclose(hFile);*/
+
+ /* automatic file type recognition */
+ bool bOK = false;
+ if ( GetTypeIndexFromId(imagetype) ){
+ FILE* hFile; //file handle to read the image
+
+#ifdef WIN32
+ if ((hFile=_tfopen(filename,_T("rb")))==NULL) return false; // For UNICODE support
+#else
+ if ((hFile=fopen(filename,"rb"))==NULL) return false;
+#endif
+
+ bOK = Decode(hFile,imagetype);
+ fclose(hFile);
+ if (bOK) return bOK;
+ }
+
+ char szError[256];
+ strcpy(szError,info.szLastError); //save the first error
+
+ // if failed, try automatic recognition of the file...
+ FILE* hFile;
+
+#ifdef WIN32
+ if ((hFile=_tfopen(filename,_T("rb")))==NULL) return false; // For UNICODE support
+#else
+ if ((hFile=fopen(filename,"rb"))==NULL) return false;
+#endif
+
+ bOK = Decode(hFile,CXIMAGE_FORMAT_UNKNOWN);
+ fclose(hFile);
+
+ if (!bOK && imagetype > 0) strcpy(info.szLastError,szError); //restore the first error
+
+ return bOK;
+}
+////////////////////////////////////////////////////////////////////////////////
+#ifdef WIN32
+//bool CxImage::Load(LPCWSTR filename, uint32_t imagetype)
+//{
+// /*FILE* hFile; //file handle to read the image
+// if ((hFile=_wfopen(filename, L"rb"))==NULL) return false;
+// bool bOK = Decode(hFile,imagetype);
+// fclose(hFile);*/
+//
+// /* automatic file type recognition */
+// bool bOK = false;
+// if ( GetTypeIndexFromId(imagetype) ){
+// FILE* hFile; //file handle to read the image
+// if ((hFile=_wfopen(filename,L"rb"))==NULL) return false;
+// bOK = Decode(hFile,imagetype);
+// fclose(hFile);
+// if (bOK) return bOK;
+// }
+//
+// char szError[256];
+// strcpy(szError,info.szLastError); //save the first error
+//
+// // if failed, try automatic recognition of the file...
+// FILE* hFile; //file handle to read the image
+// if ((hFile=_wfopen(filename,L"rb"))==NULL) return false;
+// bOK = Decode(hFile,CXIMAGE_FORMAT_UNKNOWN);
+// fclose(hFile);
+//
+// if (!bOK && imagetype > 0) strcpy(info.szLastError,szError); //restore the first error
+//
+// return bOK;
+//}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Loads an image from the application resources.
+ * \param hRes: the resource handle returned by FindResource().
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS.
+ * \param hModule: NULL for internal resource, or external application/DLL hinstance returned by LoadLibray.
+ * \return true if everything is ok
+ */
+bool CxImage::LoadResource(HRSRC hRes, uint32_t imagetype, HMODULE hModule)
+{
+ uint32_t rsize=SizeofResource(hModule,hRes);
+ HGLOBAL hMem=::LoadResource(hModule,hRes);
+ if (hMem){
+ char* lpVoid=(char*)LockResource(hMem);
+ if (lpVoid){
+ // FILE* fTmp=tmpfile(); doesn't work with network
+ /*char tmpPath[MAX_PATH] = {0};
+ char tmpFile[MAX_PATH] = {0};
+ GetTempPath(MAX_PATH,tmpPath);
+ GetTempFileName(tmpPath,"IMG",0,tmpFile);
+ FILE* fTmp=fopen(tmpFile,"w+b");
+ if (fTmp){
+ fwrite(lpVoid,rsize,1,fTmp);
+ fseek(fTmp,0,SEEK_SET);
+ bool bOK = Decode(fTmp,imagetype);
+ fclose(fTmp);
+ DeleteFile(tmpFile);
+ return bOK;
+ }*/
+
+ CxMemFile fTmp((uint8_t*)lpVoid,rsize);
+ return Decode(&fTmp,imagetype);
+ }
+ } else strcpy(info.szLastError,"Unable to load resource!");
+ return false;
+}
+#endif //WIN32
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor from file name, see Load()
+ * \param filename: file name
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ */
+//
+// > filename: file name
+// > imagetype: specify the image format (CXIMAGE_FORMAT_BMP,...)
+// For UNICODE support: char -> TCHAR
+CxImage::CxImage(const TCHAR * filename, uint32_t imagetype)
+//CxImage::CxImage(const char * filename, uint32_t imagetype)
+{
+ Startup(imagetype);
+ Load(filename,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor from file handle, see Decode()
+ * \param stream: file handle, with read access.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ */
+CxImage::CxImage(FILE * stream, uint32_t imagetype)
+{
+ Startup(imagetype);
+ Decode(stream,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor from CxFile object, see Decode()
+ * \param stream: file handle (CxMemFile or CxIOFile), with read access.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ */
+CxImage::CxImage(CxFile * stream, uint32_t imagetype)
+{
+ Startup(imagetype);
+ Decode(stream,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor from memory buffer, see Decode()
+ * \param buffer: memory buffer
+ * \param size: size of buffer
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ */
+CxImage::CxImage(uint8_t * buffer, uint32_t size, uint32_t imagetype)
+{
+ Startup(imagetype);
+ CxMemFile stream(buffer,size);
+ Decode(&stream,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Loads an image from memory buffer
+ * \param buffer: memory buffer
+ * \param size: size of buffer
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Decode(uint8_t * buffer, uint32_t size, uint32_t imagetype)
+{
+ CxMemFile file(buffer,size);
+ return Decode(&file,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Loads an image from file handle.
+ * \param hFile: file handle, with read access.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ */
+bool CxImage::Decode(FILE *hFile, uint32_t imagetype)
+{
+ CxIOFile file(hFile);
+ return Decode(&file,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Loads an image from CxFile object
+ * \param hFile: file handle (CxMemFile or CxIOFile), with read access.
+ * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS
+ * \return true if everything is ok
+ * \sa ENUM_CXIMAGE_FORMATS
+ */
+bool CxImage::Decode(CxFile *hFile, uint32_t imagetype)
+{
+ if (hFile == NULL){
+ strcpy(info.szLastError,CXIMAGE_ERR_NOFILE);
+ return false;
+ }
+
+ uint32_t pos = hFile->Tell();
+
+#if CXIMAGE_SUPPORT_BMP
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_BMP==imagetype){
+ CxImageBMP *newima = new CxImageBMP;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JPG
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_JPG==imagetype){
+ CxImageJPG *newima = new CxImageJPG;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_ICO==imagetype){
+ CxImageICO *newima = new CxImageICO;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ info.nNumFrames = newima->info.nNumFrames;
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_GIF==imagetype){
+ CxImageGIF *newima = new CxImageGIF;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ info.nNumFrames = newima->info.nNumFrames;
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_PNG
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_PNG==imagetype){
+ CxImagePNG *newima = new CxImagePNG;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_TIF
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_TIF==imagetype){
+ CxImageTIF *newima = new CxImageTIF;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ info.nNumFrames = newima->info.nNumFrames;
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_MNG
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_MNG==imagetype){
+ CxImageMNG *newima = new CxImageMNG;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ info.nNumFrames = newima->info.nNumFrames;
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_TGA
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_TGA==imagetype){
+ CxImageTGA *newima = new CxImageTGA;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_PCX
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_PCX==imagetype){
+ CxImagePCX *newima = new CxImagePCX;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_WBMP==imagetype){
+ CxImageWBMP *newima = new CxImageWBMP;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_WMF==imagetype){
+ CxImageWMF *newima = new CxImageWMF;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JBG
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_JBG==imagetype){
+ CxImageJBG *newima = new CxImageJBG;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_JASPER
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype ||
+#if CXIMAGE_SUPPORT_JP2
+ CXIMAGE_FORMAT_JP2==imagetype ||
+#endif
+#if CXIMAGE_SUPPORT_JPC
+ CXIMAGE_FORMAT_JPC==imagetype ||
+#endif
+#if CXIMAGE_SUPPORT_PGX
+ CXIMAGE_FORMAT_PGX==imagetype ||
+#endif
+#if CXIMAGE_SUPPORT_PNM
+ CXIMAGE_FORMAT_PNM==imagetype ||
+#endif
+#if CXIMAGE_SUPPORT_RAS
+ CXIMAGE_FORMAT_RAS==imagetype ||
+#endif
+ false ){
+ CxImageJAS *newima = new CxImageJAS;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_SKA
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_SKA==imagetype){
+ CxImageSKA *newima = new CxImageSKA;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_RAW
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_RAW==imagetype){
+ CxImageRAW *newima = new CxImageRAW;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+#if CXIMAGE_SUPPORT_PSD
+ if (CXIMAGE_FORMAT_UNKNOWN==imagetype || CXIMAGE_FORMAT_PSD==imagetype){
+ CxImagePSD *newima = new CxImagePSD;
+ if (!newima)
+ return false;
+ newima->CopyInfo(*this);
+ if (newima->Decode(hFile)) {
+ Transfer(*newima);
+ delete newima;
+ return true;
+ } else {
+ strcpy(info.szLastError,newima->GetLastError());
+ hFile->Seek(pos,SEEK_SET);
+ delete newima;
+ if (CXIMAGE_FORMAT_UNKNOWN!=imagetype)
+ return false;
+ }
+ }
+#endif
+
+ strcpy(info.szLastError,"Decode: Unknown or wrong format");
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Loads an image from CxFile object
+ * \param hFile: file handle (CxMemFile or CxIOFile), with read access.
+ * \param imagetype: file format, default = 0 (CXIMAGE_FORMAT_UNKNOWN)
+ * \return : if imagetype is not 0, the function returns true when imagetype
+ * matches the file image format. If imagetype is 0, the function returns true
+ * when the file image format is recognized as a supported format.
+ * If the returned value is true, use GetHeight(), GetWidth() or GetType()
+ * to retrieve the basic image information.
+ * \sa ENUM_CXIMAGE_FORMATS
+ */
+bool CxImage::CheckFormat(CxFile * hFile, uint32_t imagetype)
+{
+ SetType(CXIMAGE_FORMAT_UNKNOWN);
+ SetEscape(-1);
+
+ if (!Decode(hFile,imagetype))
+ return false;
+
+ if (GetType() == CXIMAGE_FORMAT_UNKNOWN ||
+ ((imagetype!=CXIMAGE_FORMAT_UNKNOWN)&&(GetType() != imagetype)))
+ return false;
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::CheckFormat(uint8_t * buffer, uint32_t size, uint32_t imagetype)
+{
+ if (buffer==NULL || size==0){
+ strcpy(info.szLastError,"invalid or empty buffer");
+ return false;
+ }
+ CxMemFile file(buffer,size);
+ return CheckFormat(&file,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_EXIF
+bool CxImage::GetExifThumbnail(const TCHAR *filename, const TCHAR *outname, int32_t type)
+{
+ switch (type){
+#if CXIMAGE_SUPPORT_RAW
+ case CXIMAGE_FORMAT_RAW:
+ {
+ CxImageRAW image;
+ return image.GetExifThumbnail(filename, outname, type);
+ }
+#endif //CXIMAGE_SUPPORT_RAW
+#if CXIMAGE_SUPPORT_JPG
+ case CXIMAGE_FORMAT_JPG:
+ {
+ CxImageJPG image;
+ return image.GetExifThumbnail(filename, outname, type);
+ }
+#endif //CXIMAGE_SUPPORT_JPG
+ default:
+ return false;
+ }
+}
+#endif //CXIMAGE_SUPPORT_EXIF
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
diff --git a/archive/hge/CxImage/ximaexif.cpp b/archive/hge/CxImage/ximaexif.cpp new file mode 100644 index 0000000..f880d72 --- /dev/null +++ b/archive/hge/CxImage/ximaexif.cpp @@ -0,0 +1,877 @@ +/*
+ * File: ximaexif.cpp
+ * Purpose: EXIF reader
+ * 18/Aug/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ * based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>
+ */
+
+#include "ximajpg.h"
+
+#if CXIMAGEJPG_SUPPORT_EXIF
+
+////////////////////////////////////////////////////////////////////////////////
+CxImageJPG::CxExifInfo::CxExifInfo(EXIFINFO* info)
+{
+ if (info) {
+ m_exifinfo = info;
+ freeinfo = false;
+ } else {
+ m_exifinfo = new EXIFINFO;
+ memset(m_exifinfo,0,sizeof(EXIFINFO));
+ freeinfo = true;
+ }
+
+ m_szLastError[0]='\0';
+ ExifImageWidth = MotorolaOrder = 0;
+ SectionsRead=0;
+ memset(&Sections, 0, MAX_SECTIONS * sizeof(Section_t));
+}
+////////////////////////////////////////////////////////////////////////////////
+CxImageJPG::CxExifInfo::~CxExifInfo()
+{
+ for(int32_t i=0;i<MAX_SECTIONS;i++) if(Sections[i].Data) free(Sections[i].Data);
+ if (freeinfo) delete m_exifinfo;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageJPG::CxExifInfo::DecodeExif(CxFile * hFile, int32_t nReadMode)
+{
+ int32_t a;
+ int32_t HaveCom = FALSE;
+
+ a = hFile->GetC();
+
+ if (a != 0xff || hFile->GetC() != M_SOI){
+ return FALSE;
+ }
+
+ for(;;){
+ int32_t itemlen;
+ int32_t marker = 0;
+ int32_t ll,lh, got;
+ uint8_t * Data;
+
+ if (SectionsRead >= MAX_SECTIONS){
+ strcpy(m_szLastError,"Too many sections in jpg file");
+ return false;
+ }
+
+ for (a=0;a<7;a++){
+ marker = hFile->GetC();
+ if (marker != 0xff) break;
+
+ if (a >= 6){
+ printf("too many padding bytes\n");
+ return false;
+ }
+ }
+
+ if (marker == 0xff){
+ // 0xff is legal padding, but if we get that many, something's wrong.
+ strcpy(m_szLastError,"too many padding bytes!");
+ return false;
+ }
+
+ Sections[SectionsRead].Type = marker;
+
+ // Read the length of the section.
+ lh = hFile->GetC();
+ ll = hFile->GetC();
+
+ itemlen = (lh << 8) | ll;
+
+ if (itemlen < 2){
+ strcpy(m_szLastError,"invalid marker");
+ return false;
+ }
+
+ Sections[SectionsRead].Size = itemlen;
+
+ Data = (uint8_t *)malloc(itemlen);
+ if (Data == NULL){
+ strcpy(m_szLastError,"Could not allocate memory");
+ return false;
+ }
+ Sections[SectionsRead].Data = Data;
+
+ // Store first two pre-read bytes.
+ Data[0] = (uint8_t)lh;
+ Data[1] = (uint8_t)ll;
+
+ got = hFile->Read(Data+2, 1, itemlen-2); // Read the whole section.
+ if (got != itemlen-2){
+ strcpy(m_szLastError,"Premature end of file?");
+ return false;
+ }
+ SectionsRead += 1;
+
+ switch(marker){
+
+ case M_SOS: // stop before hitting compressed data
+ // If reading entire image is requested, read the rest of the data.
+ if (nReadMode & EXIF_READ_IMAGE){
+ int32_t cp, ep, size;
+ // Determine how much file is left.
+ cp = hFile->Tell();
+ hFile->Seek(0, SEEK_END);
+ ep = hFile->Tell();
+ hFile->Seek(cp, SEEK_SET);
+
+ size = ep-cp;
+ Data = (uint8_t *)malloc(size);
+ if (Data == NULL){
+ strcpy(m_szLastError,"could not allocate data for entire image");
+ return false;
+ }
+
+ got = hFile->Read(Data, 1, size);
+ if (got != size){
+ strcpy(m_szLastError,"could not read the rest of the image");
+ return false;
+ }
+
+ Sections[SectionsRead].Data = Data;
+ Sections[SectionsRead].Size = size;
+ Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER;
+ SectionsRead ++;
+ }
+ return true;
+
+ case M_EOI: // in case it's a tables-only JPEG stream
+ printf("No image in jpeg!\n");
+ return FALSE;
+
+ case M_COM: // Comment section
+ if (HaveCom || ((nReadMode & EXIF_READ_EXIF) == 0)){
+ // Discard this section.
+ free(Sections[--SectionsRead].Data);
+ Sections[SectionsRead].Data=0;
+ }else{
+ process_COM(Data, itemlen);
+ HaveCom = TRUE;
+ }
+ break;
+
+ case M_JFIF:
+ // Regular jpegs always have this tag, exif images have the exif
+ // marker instead, althogh ACDsee will write images with both markers.
+ // this program will re-create this marker on absence of exif marker.
+ // hence no need to keep the copy from the file.
+ free(Sections[--SectionsRead].Data);
+ Sections[SectionsRead].Data=0;
+ break;
+
+ case M_EXIF:
+ // Seen files from some 'U-lead' software with Vivitar scanner
+ // that uses marker 31 for non exif stuff. Thus make sure
+ // it says 'Exif' in the section before treating it as exif.
+ if ((nReadMode & EXIF_READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){
+ m_exifinfo->IsExif = process_EXIF((uint8_t *)Data+2, itemlen);
+ }else{
+ // Discard this section.
+ free(Sections[--SectionsRead].Data);
+ Sections[SectionsRead].Data=0;
+ }
+ break;
+
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ process_SOFn(Data, marker);
+ break;
+ default:
+ // Skip any other sections.
+ //if (ShowTags) printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen);
+ break;
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Process a EXIF marker
+ Describes all the drivel that most digital cameras include...
+--------------------------------------------------------------------------*/
+bool CxImageJPG::CxExifInfo::process_EXIF(uint8_t * CharBuf, uint32_t length)
+{
+ m_exifinfo->FlashUsed = 0;
+ /* If it's from a digicam, and it used flash, it says so. */
+ m_exifinfo->Comments[0] = '\0'; /* Initial value - null string */
+
+ ExifImageWidth = 0;
+
+ { /* Check the EXIF header component */
+ static const uint8_t ExifHeader[] = "Exif\0\0";
+ if (memcmp(CharBuf+0, ExifHeader,6)){
+ strcpy(m_szLastError,"Incorrect Exif header");
+ return false;
+ }
+ }
+
+ if (memcmp(CharBuf+6,"II",2) == 0){
+ MotorolaOrder = 0;
+ }else{
+ if (memcmp(CharBuf+6,"MM",2) == 0){
+ MotorolaOrder = 1;
+ }else{
+ strcpy(m_szLastError,"Invalid Exif alignment marker.");
+ return false;
+ }
+ }
+
+ /* Check the next two values for correctness. */
+ if (Get16u(CharBuf+8) != 0x2a){
+ strcpy(m_szLastError,"Invalid Exif start (1)");
+ return false;
+ }
+
+ int32_t FirstOffset = Get32u(CharBuf+10);
+ /* <Richard Collins>
+ if (FirstOffset < 8 || FirstOffset > 16){
+ // I used to ensure this was set to 8 (website I used indicated its 8)
+ // but PENTAX Optio 230 has it set differently, and uses it as offset. (Sept 11 2002)
+ strcpy(m_szLastError,"Suspicious offset of first IFD value");
+ return false;
+ }*/
+
+ uint8_t * LastExifRefd = CharBuf;
+
+ /* First directory starts 16 bytes in. Offsets start at 8 bytes in. */
+ if (!ProcessExifDir(CharBuf+14, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))
+ return false;
+
+ /* <Richard Collins> give a chance for a second directory */
+ if (FirstOffset > 8) {
+ if (!ProcessExifDir(CharBuf+14+FirstOffset-8, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))
+ return false;
+ }
+
+ /* This is how far the interesting (non thumbnail) part of the exif went. */
+ // int32_t ExifSettingsLength = LastExifRefd - CharBuf;
+
+ /* Compute the CCD width, in milimeters. */
+ if (m_exifinfo->FocalplaneXRes != 0){
+ m_exifinfo->CCDWidth = (float)(ExifImageWidth * m_exifinfo->FocalplaneUnits / m_exifinfo->FocalplaneXRes);
+ }
+
+ return true;
+}
+//--------------------------------------------------------------------------
+// Get 16 bits motorola order (always) for jpeg header stuff.
+//--------------------------------------------------------------------------
+int32_t CxImageJPG::CxExifInfo::Get16m(void * Short)
+{
+ return (((uint8_t *)Short)[0] << 8) | ((uint8_t *)Short)[1];
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Convert a 16 bit unsigned value from file's native byte order
+--------------------------------------------------------------------------*/
+int32_t CxImageJPG::CxExifInfo::Get16u(void * Short)
+{
+ if (MotorolaOrder){
+ return (((uint8_t *)Short)[0] << 8) | ((uint8_t *)Short)[1];
+ }else{
+ return (((uint8_t *)Short)[1] << 8) | ((uint8_t *)Short)[0];
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Convert a 32 bit signed value from file's native byte order
+--------------------------------------------------------------------------*/
+int32_t CxImageJPG::CxExifInfo::Get32s(void * Long)
+{
+ if (MotorolaOrder){
+ return ((( char *)Long)[0] << 24) | (((uint8_t *)Long)[1] << 16)
+ | (((uint8_t *)Long)[2] << 8 ) | (((uint8_t *)Long)[3] << 0 );
+ }else{
+ return ((( char *)Long)[3] << 24) | (((uint8_t *)Long)[2] << 16)
+ | (((uint8_t *)Long)[1] << 8 ) | (((uint8_t *)Long)[0] << 0 );
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Convert a 32 bit unsigned value from file's native byte order
+--------------------------------------------------------------------------*/
+uint32_t CxImageJPG::CxExifInfo::Get32u(void * Long)
+{
+ return (uint32_t)Get32s(Long) & 0xffffffff;
+}
+////////////////////////////////////////////////////////////////////////////////
+
+/* Describes format descriptor */
+static const int32_t BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};
+#define NUM_FORMATS 12
+
+#define FMT_BYTE 1
+#define FMT_STRING 2
+#define FMT_USHORT 3
+#define FMT_ULONG 4
+#define FMT_URATIONAL 5
+#define FMT_SBYTE 6
+#define FMT_UNDEFINED 7
+#define FMT_SSHORT 8
+#define FMT_SLONG 9
+#define FMT_SRATIONAL 10
+#define FMT_SINGLE 11
+#define FMT_DOUBLE 12
+
+/* Describes tag values */
+
+#define TAG_EXIF_VERSION 0x9000
+#define TAG_EXIF_OFFSET 0x8769
+#define TAG_INTEROP_OFFSET 0xa005
+
+#define TAG_MAKE 0x010F
+#define TAG_MODEL 0x0110
+
+#define TAG_ORIENTATION 0x0112
+#define TAG_XRESOLUTION 0x011A
+#define TAG_YRESOLUTION 0x011B
+#define TAG_RESOLUTIONUNIT 0x0128
+
+#define TAG_EXPOSURETIME 0x829A
+#define TAG_FNUMBER 0x829D
+
+#define TAG_SHUTTERSPEED 0x9201
+#define TAG_APERTURE 0x9202
+#define TAG_BRIGHTNESS 0x9203
+#define TAG_MAXAPERTURE 0x9205
+#define TAG_FOCALLENGTH 0x920A
+
+#define TAG_DATETIME_ORIGINAL 0x9003
+#define TAG_USERCOMMENT 0x9286
+
+#define TAG_SUBJECT_DISTANCE 0x9206
+#define TAG_FLASH 0x9209
+
+#define TAG_FOCALPLANEXRES 0xa20E
+#define TAG_FOCALPLANEYRES 0xa20F
+#define TAG_FOCALPLANEUNITS 0xa210
+#define TAG_EXIF_IMAGEWIDTH 0xA002
+#define TAG_EXIF_IMAGELENGTH 0xA003
+
+/* the following is added 05-jan-2001 vcs */
+#define TAG_EXPOSURE_BIAS 0x9204
+#define TAG_WHITEBALANCE 0x9208
+#define TAG_METERING_MODE 0x9207
+#define TAG_EXPOSURE_PROGRAM 0x8822
+#define TAG_ISO_EQUIVALENT 0x8827
+#define TAG_COMPRESSION_LEVEL 0x9102
+
+#define TAG_THUMBNAIL_OFFSET 0x0201
+#define TAG_THUMBNAIL_LENGTH 0x0202
+
+
+/*--------------------------------------------------------------------------
+ Process one of the nested EXIF directories.
+--------------------------------------------------------------------------*/
+bool CxImageJPG::CxExifInfo::ProcessExifDir(uint8_t * DirStart, uint8_t * OffsetBase, unsigned ExifLength,
+ EXIFINFO * const m_exifinfo, uint8_t ** const LastExifRefdP, int32_t NestingLevel)
+{
+ int32_t de;
+ int32_t a;
+ int32_t NumDirEntries;
+ unsigned ThumbnailOffset = 0;
+ unsigned ThumbnailSize = 0;
+
+ if (NestingLevel > 4){
+ strcpy(m_szLastError,"Maximum directory nesting exceeded (corrupt exif header)");
+ return false;
+ }
+
+ NumDirEntries = Get16u(DirStart);
+
+ if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)){
+ strcpy(m_szLastError,"Illegally sized directory");
+ return false;
+ }
+
+ for (de=0;de<NumDirEntries;de++){
+ int32_t Tag, Format, Components;
+ uint8_t * ValuePtr;
+ /* This actually can point to a variety of things; it must be
+ cast to other types when used. But we use it as a byte-by-byte
+ cursor, so we declare it as a pointer to a generic byte here.
+ */
+ int32_t ByteCount;
+ uint8_t * DirEntry;
+ DirEntry = DirStart+2+12*de;
+
+ Tag = Get16u(DirEntry);
+ Format = Get16u(DirEntry+2);
+ Components = Get32u(DirEntry+4);
+
+ if ((Format-1) >= NUM_FORMATS) {
+ /* (-1) catches illegal zero case as unsigned underflows to positive large */
+ strcpy(m_szLastError,"Illegal format code in EXIF dir");
+ return false;
+ }
+
+ ByteCount = Components * BytesPerFormat[Format];
+
+ if (ByteCount > 4){
+ unsigned OffsetVal;
+ OffsetVal = Get32u(DirEntry+8);
+ /* If its bigger than 4 bytes, the dir entry contains an offset.*/
+ if (OffsetVal+ByteCount > ExifLength){
+ /* Bogus pointer offset and / or bytecount value */
+ strcpy(m_szLastError,"Illegal pointer offset value in EXIF.");
+ return false;
+ }
+ ValuePtr = OffsetBase+OffsetVal;
+ }else{
+ /* 4 bytes or less and value is in the dir entry itself */
+ ValuePtr = DirEntry+8;
+ }
+
+ if (*LastExifRefdP < ValuePtr+ByteCount){
+ /* Keep track of last byte in the exif header that was
+ actually referenced. That way, we know where the
+ discardable thumbnail data begins.
+ */
+ *LastExifRefdP = ValuePtr+ByteCount;
+ }
+
+ /* Extract useful components of tag */
+ switch(Tag){
+
+ case TAG_MAKE:
+ strncpy(m_exifinfo->CameraMake, (char*)ValuePtr, 31);
+ break;
+
+ case TAG_MODEL:
+ strncpy(m_exifinfo->CameraModel, (char*)ValuePtr, 39);
+ break;
+
+ case TAG_EXIF_VERSION:
+ strncpy(m_exifinfo->Version,(char*)ValuePtr, 4);
+ break;
+
+ case TAG_DATETIME_ORIGINAL:
+ strncpy(m_exifinfo->DateTime, (char*)ValuePtr, 19);
+ break;
+
+ case TAG_USERCOMMENT:
+ // Olympus has this padded with trailing spaces. Remove these first.
+ for (a=ByteCount;;){
+ a--;
+ if (((char*)ValuePtr)[a] == ' '){
+ ((char*)ValuePtr)[a] = '\0';
+ }else{
+ break;
+ }
+ if (a == 0) break;
+ }
+
+ /* Copy the comment */
+ if (memcmp(ValuePtr, "ASCII",5) == 0){
+ for (a=5;a<10;a++){
+ char c;
+ c = ((char*)ValuePtr)[a];
+ if (c != '\0' && c != ' '){
+ strncpy(m_exifinfo->Comments, (char*)ValuePtr+a, 199);
+ break;
+ }
+ }
+
+ }else{
+ strncpy(m_exifinfo->Comments, (char*)ValuePtr, 199);
+ }
+ break;
+
+ case TAG_FNUMBER:
+ /* Simplest way of expressing aperture, so I trust it the most.
+ (overwrite previously computd value if there is one)
+ */
+ m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_APERTURE:
+ case TAG_MAXAPERTURE:
+ /* More relevant info always comes earlier, so only
+ use this field if we don't have appropriate aperture
+ information yet.
+ */
+ if (m_exifinfo->ApertureFNumber == 0){
+ m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f)*0.5);
+ }
+ break;
+
+ case TAG_BRIGHTNESS:
+ m_exifinfo->Brightness = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_FOCALLENGTH:
+ /* Nice digital cameras actually save the focal length
+ as a function of how farthey are zoomed in.
+ */
+
+ m_exifinfo->FocalLength = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_SUBJECT_DISTANCE:
+ /* Inidcates the distacne the autofocus camera is focused to.
+ Tends to be less accurate as distance increases.
+ */
+ m_exifinfo->Distance = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_EXPOSURETIME:
+ /* Simplest way of expressing exposure time, so I
+ trust it most. (overwrite previously computd value
+ if there is one)
+ */
+ m_exifinfo->ExposureTime =
+ (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_SHUTTERSPEED:
+ /* More complicated way of expressing exposure time,
+ so only use this value if we don't already have it
+ from somewhere else.
+ */
+ if (m_exifinfo->ExposureTime == 0){
+ m_exifinfo->ExposureTime = (float)
+ (1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f)));
+ }
+ break;
+
+ case TAG_FLASH:
+ if ((int32_t)ConvertAnyFormat(ValuePtr, Format) & 7){
+ m_exifinfo->FlashUsed = 1;
+ }else{
+ m_exifinfo->FlashUsed = 0;
+ }
+ break;
+
+ case TAG_ORIENTATION:
+ m_exifinfo->Orientation = (int32_t)ConvertAnyFormat(ValuePtr, Format);
+ if (m_exifinfo->Orientation < 1 || m_exifinfo->Orientation > 8){
+ strcpy(m_szLastError,"Undefined rotation value");
+ m_exifinfo->Orientation = 0;
+ }
+ break;
+
+ case TAG_EXIF_IMAGELENGTH:
+ case TAG_EXIF_IMAGEWIDTH:
+ /* Use largest of height and width to deal with images
+ that have been rotated to portrait format.
+ */
+ a = (int32_t)ConvertAnyFormat(ValuePtr, Format);
+ if (ExifImageWidth < a) ExifImageWidth = a;
+ break;
+
+ case TAG_FOCALPLANEXRES:
+ m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_FOCALPLANEYRES:
+ m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_RESOLUTIONUNIT:
+ switch((int32_t)ConvertAnyFormat(ValuePtr, Format)){
+ case 1: m_exifinfo->ResolutionUnit = 1.0f; break; /* 1 inch */
+ case 2: m_exifinfo->ResolutionUnit = 1.0f; break;
+ case 3: m_exifinfo->ResolutionUnit = 0.3937007874f; break; /* 1 centimeter*/
+ case 4: m_exifinfo->ResolutionUnit = 0.03937007874f; break; /* 1 millimeter*/
+ case 5: m_exifinfo->ResolutionUnit = 0.00003937007874f; /* 1 micrometer*/
+ }
+ break;
+
+ case TAG_FOCALPLANEUNITS:
+ switch((int32_t)ConvertAnyFormat(ValuePtr, Format)){
+ case 1: m_exifinfo->FocalplaneUnits = 1.0f; break; /* 1 inch */
+ case 2: m_exifinfo->FocalplaneUnits = 1.0f; break;
+ case 3: m_exifinfo->FocalplaneUnits = 0.3937007874f; break; /* 1 centimeter*/
+ case 4: m_exifinfo->FocalplaneUnits = 0.03937007874f; break; /* 1 millimeter*/
+ case 5: m_exifinfo->FocalplaneUnits = 0.00003937007874f; /* 1 micrometer*/
+ }
+ break;
+
+ // Remaining cases contributed by: Volker C. Schoech <schoech(at)gmx(dot)de>
+
+ case TAG_EXPOSURE_BIAS:
+ m_exifinfo->ExposureBias = (float) ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_WHITEBALANCE:
+ m_exifinfo->Whitebalance = (int32_t)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_METERING_MODE:
+ m_exifinfo->MeteringMode = (int32_t)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_EXPOSURE_PROGRAM:
+ m_exifinfo->ExposureProgram = (int32_t)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_ISO_EQUIVALENT:
+ m_exifinfo->ISOequivalent = (int32_t)ConvertAnyFormat(ValuePtr, Format);
+ if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200;
+ break;
+
+ case TAG_COMPRESSION_LEVEL:
+ m_exifinfo->CompressionLevel = (int32_t)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_XRESOLUTION:
+ m_exifinfo->Xresolution = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+ case TAG_YRESOLUTION:
+ m_exifinfo->Yresolution = (float)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_THUMBNAIL_OFFSET:
+ ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ case TAG_THUMBNAIL_LENGTH:
+ ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format);
+ break;
+
+ }
+
+ if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){
+ uint8_t * SubdirStart;
+ unsigned Offset = Get32u(ValuePtr);
+ if (Offset>8){
+ SubdirStart = OffsetBase + Offset;
+ if (SubdirStart < OffsetBase ||
+ SubdirStart > OffsetBase+ExifLength){
+ strcpy(m_szLastError,"Illegal subdirectory link");
+ return false;
+ }
+ ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP, NestingLevel+1);
+ }
+ continue;
+ }
+ }
+
+
+ {
+ /* In addition to linking to subdirectories via exif tags,
+ there's also a potential link to another directory at the end
+ of each directory. This has got to be the result of a
+ committee!
+ */
+ uint8_t * SubdirStart;
+ unsigned Offset;
+ Offset = Get16u(DirStart+2+12*NumDirEntries);
+ if (Offset){
+ SubdirStart = OffsetBase + Offset;
+ if (SubdirStart < OffsetBase
+ || SubdirStart > OffsetBase+ExifLength){
+ strcpy(m_szLastError,"Illegal subdirectory link");
+ return false;
+ }
+ ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP, NestingLevel+1);
+ }
+ }
+
+
+ if (ThumbnailSize && ThumbnailOffset){
+ if (ThumbnailSize + ThumbnailOffset <= ExifLength){
+ /* The thumbnail pointer appears to be valid. Store it. */
+ m_exifinfo->ThumbnailPointer = OffsetBase + ThumbnailOffset;
+ m_exifinfo->ThumbnailSize = ThumbnailSize;
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+ Evaluate number, be it int32_t, rational, or float from directory.
+--------------------------------------------------------------------------*/
+double CxImageJPG::CxExifInfo::ConvertAnyFormat(void * ValuePtr, int32_t Format)
+{
+ double Value;
+ Value = 0;
+
+ switch(Format){
+ case FMT_SBYTE: Value = *(signed char *)ValuePtr; break;
+ case FMT_BYTE: Value = *(uint8_t *)ValuePtr; break;
+
+ case FMT_USHORT: Value = Get16u(ValuePtr); break;
+ case FMT_ULONG: Value = Get32u(ValuePtr); break;
+
+ case FMT_URATIONAL:
+ case FMT_SRATIONAL:
+ {
+ int32_t Num,Den;
+ Num = Get32s(ValuePtr);
+ Den = Get32s(4+(char *)ValuePtr);
+ if (Den == 0){
+ Value = 0;
+ }else{
+ Value = (double)Num/Den;
+ }
+ break;
+ }
+
+ case FMT_SSHORT: Value = (int16_t)Get16u(ValuePtr); break;
+ case FMT_SLONG: Value = Get32s(ValuePtr); break;
+
+ /* Not sure if this is correct (never seen float used in Exif format)
+ */
+ case FMT_SINGLE: Value = (double)*(float *)ValuePtr; break;
+ case FMT_DOUBLE: Value = *(double *)ValuePtr; break;
+ }
+ return Value;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageJPG::CxExifInfo::process_COM (const uint8_t * Data, int32_t length)
+{
+ int32_t ch;
+ char Comment[MAX_COMMENT+1];
+ int32_t nch;
+ int32_t a;
+
+ nch = 0;
+
+ if (length > MAX_COMMENT) length = MAX_COMMENT; // Truncate if it won't fit in our structure.
+
+ for (a=2;a<length;a++){
+ ch = Data[a];
+
+ if (ch == '\r' && Data[a+1] == '\n') continue; // Remove cr followed by lf.
+
+ if (isprint(ch) || ch == '\n' || ch == '\t'){
+ Comment[nch++] = (char)ch;
+ }else{
+ Comment[nch++] = '?';
+ }
+ }
+
+ Comment[nch] = '\0'; // Null terminate
+
+ //if (ShowTags) printf("COM marker comment: %s\n",Comment);
+
+ strcpy(m_exifinfo->Comments,Comment);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageJPG::CxExifInfo::process_SOFn (const uint8_t * Data, int32_t marker)
+{
+ int32_t data_precision, num_components;
+
+ data_precision = Data[2];
+ m_exifinfo->Height = Get16m((void*)(Data+3));
+ m_exifinfo->Width = Get16m((void*)(Data+5));
+ num_components = Data[7];
+
+ if (num_components == 3){
+ m_exifinfo->IsColor = 1;
+ }else{
+ m_exifinfo->IsColor = 0;
+ }
+
+ m_exifinfo->Process = marker;
+
+ //if (ShowTags) printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
+ // ImageInfo.Width, ImageInfo.Height, num_components, data_precision);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * this will work only on a CxImageJPG object, if the image originally has valid EXIF data
+ \verbatim
+ CxImageJPG jpg;
+ CxIOFile in,out;
+ in.Open("D:\\exif_in.jpg","rb");
+ out.Open("D:\\exif_out.jpg","w+b");
+ jpg.Decode(&in);
+ if (jpg.IsValid()){
+ jpg.RotateLeft();
+ jpg.Encode(&out);
+ }
+ \endverbatim
+*/
+bool CxImageJPG::CxExifInfo::EncodeExif(CxFile * hFile)
+{
+ int32_t a;
+
+ if (FindSection(M_SOS)==NULL){
+ strcpy(m_szLastError,"Can't write exif : didn't read all");
+ return false;
+ }
+
+ // Initial static jpeg marker.
+ hFile->PutC(0xff);
+ hFile->PutC(0xd8);
+
+ if (Sections[0].Type != M_EXIF && Sections[0].Type != M_JFIF){
+ // The image must start with an exif or jfif marker. If we threw those away, create one.
+ static uint8_t JfifHead[18] = {
+ 0xff, M_JFIF,
+ 0x00, 0x10, 'J' , 'F' , 'I' , 'F' , 0x00, 0x01,
+ 0x01, 0x01, 0x01, 0x2C, 0x01, 0x2C, 0x00, 0x00
+ };
+ hFile->Write(JfifHead, 18, 1);
+ }
+
+ // Write all the misc sections
+ for (a=0;a<SectionsRead-1;a++){
+ hFile->PutC(0xff);
+ hFile->PutC((uint8_t)(Sections[a].Type));
+ hFile->Write(Sections[a].Data, Sections[a].Size, 1);
+ }
+
+ // Write the remaining image data.
+ hFile->Write(Sections[a].Data, Sections[a].Size, 1);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageJPG::CxExifInfo::DiscardAllButExif()
+{
+ Section_t ExifKeeper;
+ Section_t CommentKeeper;
+ int32_t a;
+
+ memset(&ExifKeeper, 0, sizeof(ExifKeeper));
+ memset(&CommentKeeper, 0, sizeof(ExifKeeper));
+
+ for (a=0;a<SectionsRead;a++){
+ if (Sections[a].Type == M_EXIF && ExifKeeper.Type == 0){
+ ExifKeeper = Sections[a];
+ }else if (Sections[a].Type == M_COM && CommentKeeper.Type == 0){
+ CommentKeeper = Sections[a];
+ }else{
+ free(Sections[a].Data);
+ Sections[a].Data = 0;
+ }
+ }
+ SectionsRead = 0;
+ if (ExifKeeper.Type){
+ Sections[SectionsRead++] = ExifKeeper;
+ }
+ if (CommentKeeper.Type){
+ Sections[SectionsRead++] = CommentKeeper;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void* CxImageJPG::CxExifInfo::FindSection(int32_t SectionType)
+{
+ int32_t a;
+ for (a=0;a<SectionsRead-1;a++){
+ if (Sections[a].Type == SectionType){
+ return &Sections[a];
+ }
+ }
+ // Could not be found.
+ return NULL;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGEJPG_SUPPORT_EXIF
diff --git a/archive/hge/CxImage/ximage.cpp b/archive/hge/CxImage/ximage.cpp new file mode 100644 index 0000000..904b807 --- /dev/null +++ b/archive/hge/CxImage/ximage.cpp @@ -0,0 +1,537 @@ +// ximage.cpp : main implementation file
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// CxImage
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Initialize the internal structures
+ */
+void CxImage::Startup(uint32_t imagetype)
+{
+ //init pointers
+ pDib = pSelection = pAlpha = NULL;
+ ppLayers = ppFrames = NULL;
+ //init structures
+ memset(&head,0,sizeof(BITMAPINFOHEADER));
+ memset(&info,0,sizeof(CXIMAGEINFO));
+ //init default attributes
+ info.dwType = imagetype;
+ info.fQuality = 90.0f;
+ info.nAlphaMax = 255;
+ info.nBkgndIndex = -1;
+ info.bEnabled = true;
+ info.nJpegScale = 1;
+ SetXDPI(CXIMAGE_DEFAULT_DPI);
+ SetYDPI(CXIMAGE_DEFAULT_DPI);
+
+ int16_t test = 1;
+ info.bLittleEndianHost = (*((char *) &test) == 1);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Empty image constructor
+ * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS
+ */
+CxImage::CxImage(uint32_t imagetype)
+{
+ Startup(imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Call this function to destroy image pixels, alpha channel, selection and sub layers.
+ * - Attributes are not erased, but IsValid returns false.
+ *
+ * \return true if everything is freed, false if the image is a Ghost
+ */
+bool CxImage::Destroy()
+{
+ //free this only if it's valid and it's not a ghost
+ if (info.pGhost==NULL){
+ if (ppLayers) {
+ for(int32_t n=0; n<info.nNumLayers;n++){ delete ppLayers[n]; }
+ delete [] ppLayers; ppLayers=0; info.nNumLayers = 0;
+ }
+ if (pSelection) {free(pSelection); pSelection=0;}
+ if (pAlpha) {free(pAlpha); pAlpha=0;}
+ if (pDib) {free(pDib); pDib=0;}
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::DestroyFrames()
+{
+ if (info.pGhost==NULL) {
+ if (ppFrames) {
+ for (int32_t n=0; n<info.nNumFrames; n++) { delete ppFrames[n]; }
+ delete [] ppFrames; ppFrames = NULL; info.nNumFrames = 0;
+ }
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sized image constructor
+ * \param dwWidth: width
+ * \param dwHeight: height
+ * \param wBpp: bit per pixel, can be 1, 4, 8, 24
+ * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS
+ */
+CxImage::CxImage(uint32_t dwWidth, uint32_t dwHeight, uint32_t wBpp, uint32_t imagetype)
+{
+ Startup(imagetype);
+ Create(dwWidth,dwHeight,wBpp,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * image constructor from existing source
+ * \param src: source image.
+ * \param copypixels: copy the pixels from the source image into the new image.
+ * \param copyselection: copy the selection from source
+ * \param copyalpha: copy the alpha channel from source
+ * \sa Copy
+ */
+CxImage::CxImage(const CxImage &src, bool copypixels, bool copyselection, bool copyalpha)
+{
+ Startup(src.GetType());
+ Copy(src,copypixels,copyselection,copyalpha);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Copies the image from an exsisting source
+ * \param src: source image.
+ * \param copypixels: copy the pixels from the source image into the new image.
+ * \param copyselection: copy the selection from source
+ * \param copyalpha: copy the alpha channel from source
+ */
+void CxImage::Copy(const CxImage &src, bool copypixels, bool copyselection, bool copyalpha)
+{
+ // if the source is a ghost, the copy is still a ghost
+ if (src.info.pGhost){
+ Ghost(&src);
+ return;
+ }
+ //copy the attributes
+ memcpy(&info,&src.info,sizeof(CXIMAGEINFO));
+ memcpy(&head,&src.head,sizeof(BITMAPINFOHEADER)); // [andy] - fix for bitmap header DPI
+ //rebuild the image
+ Create(src.GetWidth(),src.GetHeight(),src.GetBpp(),src.GetType());
+ //copy the pixels and the palette, or at least copy the palette only.
+ if (copypixels && pDib && src.pDib) memcpy(pDib,src.pDib,GetSize());
+ else SetPalette(src.GetPalette());
+ int32_t nSize = head.biWidth * head.biHeight;
+ //copy the selection
+ if (copyselection && src.pSelection){
+ if (pSelection) free(pSelection);
+ pSelection = (uint8_t*)malloc(nSize);
+ memcpy(pSelection,src.pSelection,nSize);
+ }
+ //copy the alpha channel
+ if (copyalpha && src.pAlpha){
+ if (pAlpha) free(pAlpha);
+ pAlpha = (uint8_t*)malloc(nSize);
+ memcpy(pAlpha,src.pAlpha,nSize);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Copies the image attributes from an existing image.
+ * - Works only on an empty image, and the image will be still empty.
+ * - <b> Use it before Create() </b>
+ */
+void CxImage::CopyInfo(const CxImage &src)
+{
+ if (pDib==NULL) memcpy(&info,&src.info,sizeof(CXIMAGEINFO));
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa Copy
+ */
+CxImage& CxImage::operator = (const CxImage& isrc)
+{
+ if (this != &isrc) Copy(isrc);
+ return *this;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Initializes or rebuilds the image.
+ * \param dwWidth: width
+ * \param dwHeight: height
+ * \param wBpp: bit per pixel, can be 1, 4, 8, 24
+ * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS
+ * \return pointer to the internal pDib object; NULL if an error occurs.
+ */
+void* CxImage::Create(uint32_t dwWidth, uint32_t dwHeight, uint32_t wBpp, uint32_t imagetype)
+{
+ // destroy the existing image (if any)
+ if (!Destroy())
+ return NULL;
+
+ // prevent further actions if width or height are not vaild <Balabasnia>
+ if ((dwWidth == 0) || (dwHeight == 0)){
+ strcpy(info.szLastError,"CxImage::Create : width and height must be greater than zero");
+ return NULL;
+ }
+
+ // Make sure bits per pixel is valid
+ if (wBpp <= 1) wBpp = 1;
+ else if (wBpp <= 4) wBpp = 4;
+ else if (wBpp <= 8) wBpp = 8;
+ else wBpp = 24;
+
+ // limit memory requirements
+ if ((((float)dwWidth*(float)dwHeight*(float)wBpp)/8.0f) > (float)CXIMAGE_MAX_MEMORY)
+ {
+ strcpy(info.szLastError,"CXIMAGE_MAX_MEMORY exceeded");
+ return NULL;
+ }
+
+ // set the correct bpp value
+ switch (wBpp){
+ case 1:
+ head.biClrUsed = 2; break;
+ case 4:
+ head.biClrUsed = 16; break;
+ case 8:
+ head.biClrUsed = 256; break;
+ default:
+ head.biClrUsed = 0;
+ }
+
+ //set the common image informations
+ info.dwEffWidth = ((((wBpp * dwWidth) + 31) / 32) * 4);
+ info.dwType = imagetype;
+
+ // initialize BITMAPINFOHEADER
+ head.biSize = sizeof(BITMAPINFOHEADER); //<ralphw>
+ head.biWidth = dwWidth; // fill in width from parameter
+ head.biHeight = dwHeight; // fill in height from parameter
+ head.biPlanes = 1; // must be 1
+ head.biBitCount = (uint16_t)wBpp; // from parameter
+ head.biCompression = BI_RGB;
+ head.biSizeImage = info.dwEffWidth * dwHeight;
+// head.biXPelsPerMeter = 0; See SetXDPI
+// head.biYPelsPerMeter = 0; See SetYDPI
+// head.biClrImportant = 0; See SetClrImportant
+
+ pDib = malloc(GetSize()); // alloc memory block to store our bitmap
+ if (!pDib){
+ strcpy(info.szLastError,"CxImage::Create can't allocate memory");
+ return NULL;
+ }
+
+ //clear the palette
+ RGBQUAD* pal=GetPalette();
+ if (pal) memset(pal,0,GetPaletteSize());
+ //Destroy the existing selection
+#if CXIMAGE_SUPPORT_SELECTION
+ if (pSelection) SelectionDelete();
+#endif //CXIMAGE_SUPPORT_SELECTION
+ //Destroy the existing alpha channel
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pAlpha) AlphaDelete();
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ // use our bitmap info structure to fill in first part of
+ // our DIB with the BITMAPINFOHEADER
+ BITMAPINFOHEADER* lpbi;
+ lpbi = (BITMAPINFOHEADER*)(pDib);
+ *lpbi = head;
+
+ info.pImage=GetBits();
+
+ return pDib; //return handle to the DIB
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return pointer to the image pixels. <b> USE CAREFULLY </b>
+ */
+uint8_t* CxImage::GetBits(uint32_t row)
+{
+ if (pDib){
+ if (row) {
+ if (row<(uint32_t)head.biHeight){
+ return ((uint8_t*)pDib + *(uint32_t*)pDib + GetPaletteSize() + (info.dwEffWidth * row));
+ } else {
+ return NULL;
+ }
+ } else {
+ return ((uint8_t*)pDib + *(uint32_t*)pDib + GetPaletteSize());
+ }
+ }
+ return NULL;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return the size in bytes of the internal pDib object
+ */
+int32_t CxImage::GetSize()
+{
+ return head.biSize + head.biSizeImage + GetPaletteSize();
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the coordinates are inside the image
+ * \return true if x and y are both inside the image
+ */
+bool CxImage::IsInside(int32_t x, int32_t y)
+{
+ return (0<=y && y<head.biHeight && 0<=x && x<head.biWidth);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the image bits to the specified value
+ * - for indexed images, the output color is set by the palette entries.
+ * - for RGB images, the output color is a shade of gray.
+ */
+void CxImage::Clear(uint8_t bval)
+{
+ if (pDib == 0) return;
+
+ if (GetBpp() == 1){
+ if (bval > 0) bval = 255;
+ }
+ if (GetBpp() == 4){
+ bval = (uint8_t)(17*(0x0F & bval));
+ }
+
+ memset(info.pImage,bval,head.biSizeImage);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Transfers the image from an existing source image. The source becomes empty.
+ * \return true if everything is ok
+ */
+bool CxImage::Transfer(CxImage &from, bool bTransferFrames /*=true*/)
+{
+ if (!Destroy())
+ return false;
+
+ memcpy(&head,&from.head,sizeof(BITMAPINFOHEADER));
+ memcpy(&info,&from.info,sizeof(CXIMAGEINFO));
+
+ pDib = from.pDib;
+ pSelection = from.pSelection;
+ pAlpha = from.pAlpha;
+ ppLayers = from.ppLayers;
+
+ memset(&from.head,0,sizeof(BITMAPINFOHEADER));
+ memset(&from.info,0,sizeof(CXIMAGEINFO));
+ from.pDib = from.pSelection = from.pAlpha = NULL;
+ from.ppLayers = NULL;
+
+ if (bTransferFrames){
+ DestroyFrames();
+ ppFrames = from.ppFrames;
+ from.ppFrames = NULL;
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * (this) points to the same pDib owned by (*from), the image remains in (*from)
+ * but (this) has the access to the pixels. <b>Use carefully !!!</b>
+ */
+void CxImage::Ghost(const CxImage *from)
+{
+ if (from){
+ memcpy(&head,&from->head,sizeof(BITMAPINFOHEADER));
+ memcpy(&info,&from->info,sizeof(CXIMAGEINFO));
+ pDib = from->pDib;
+ pSelection = from->pSelection;
+ pAlpha = from->pAlpha;
+ ppLayers = from->ppLayers;
+ ppFrames = from->ppFrames;
+ info.pGhost=(CxImage *)from;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * turns a 16 or 32 bit bitfield image into a RGB image
+ */
+void CxImage::Bitfield2RGB(uint8_t *src, uint32_t redmask, uint32_t greenmask, uint32_t bluemask, uint8_t bpp)
+{
+ switch (bpp){
+ case 16:
+ {
+ uint32_t ns[3]={0,0,0};
+ // compute the number of shift for each mask
+ for (int32_t i=0;i<16;i++){
+ if ((redmask>>i)&0x01) ns[0]++;
+ if ((greenmask>>i)&0x01) ns[1]++;
+ if ((bluemask>>i)&0x01) ns[2]++;
+ }
+ ns[1]+=ns[0]; ns[2]+=ns[1]; ns[0]=8-ns[0]; ns[1]-=8; ns[2]-=8;
+ // dword aligned width for 16 bit image
+ int32_t effwidth2=(((head.biWidth + 1) / 2) * 4);
+ uint16_t w;
+ int32_t y2,y3,x2,x3;
+ uint8_t *p=info.pImage;
+ // scan the buffer in reverse direction to avoid reallocations
+ for (int32_t y=head.biHeight-1; y>=0; y--){
+ y2=effwidth2*y;
+ y3=info.dwEffWidth*y;
+ for (int32_t x=head.biWidth-1; x>=0; x--){
+ x2 = 2*x+y2;
+ x3 = 3*x+y3;
+ w = (uint16_t)(src[x2]+256*src[1+x2]);
+ p[ x3]=(uint8_t)((w & bluemask)<<ns[0]);
+ p[1+x3]=(uint8_t)((w & greenmask)>>ns[1]);
+ p[2+x3]=(uint8_t)((w & redmask)>>ns[2]);
+ }
+ }
+ break;
+ }
+ case 32:
+ {
+ uint32_t ns[3]={0,0,0};
+ // compute the number of shift for each mask
+ for (int32_t i=8;i<32;i+=8){
+ if (redmask>>i) ns[0]++;
+ if (greenmask>>i) ns[1]++;
+ if (bluemask>>i) ns[2]++;
+ }
+ // dword aligned width for 32 bit image
+ int32_t effwidth4 = head.biWidth * 4;
+ int32_t y4,y3,x4,x3;
+ uint8_t *p=info.pImage;
+ // scan the buffer in reverse direction to avoid reallocations
+ for (int32_t y=head.biHeight-1; y>=0; y--){
+ y4=effwidth4*y;
+ y3=info.dwEffWidth*y;
+ for (int32_t x=head.biWidth-1; x>=0; x--){
+ x4 = 4*x+y4;
+ x3 = 3*x+y3;
+ p[ x3]=src[ns[2]+x4];
+ p[1+x3]=src[ns[1]+x4];
+ p[2+x3]=src[ns[0]+x4];
+ }
+ }
+ }
+
+ }
+ return;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Creates an image from a generic buffer
+ * \param pArray: source memory buffer
+ * \param dwWidth: image width
+ * \param dwHeight: image height
+ * \param dwBitsperpixel: can be 1,4,8,24,32
+ * \param dwBytesperline: line alignment, in bytes, for a single row stored in pArray
+ * \param bFlipImage: tune this parameter if the image is upsidedown
+ * \return true if everything is ok
+ */
+bool CxImage::CreateFromArray(uint8_t* pArray,uint32_t dwWidth,uint32_t dwHeight,uint32_t dwBitsperpixel, uint32_t dwBytesperline, bool bFlipImage)
+{
+ if (pArray==NULL) return false;
+ if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)||
+ (dwBitsperpixel==24)||(dwBitsperpixel==32))) return false;
+
+ if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false;
+
+ if (dwBitsperpixel<24) SetGrayPalette();
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (dwBitsperpixel==32) AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ uint8_t *dst,*src;
+
+ for (uint32_t y = 0; y<dwHeight; y++) {
+ dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;
+ src = pArray + y * dwBytesperline;
+ if (dwBitsperpixel==32){
+ for(uint32_t x=0;x<dwWidth;x++){
+ *dst++=src[0];
+ *dst++=src[1];
+ *dst++=src[2];
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaSet(x,(bFlipImage?(dwHeight-1-y):y),src[3]);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ src+=4;
+ }
+ } else {
+ memcpy(dst,src,min(info.dwEffWidth,dwBytesperline));
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa CreateFromArray
+ */
+bool CxImage::CreateFromMatrix(uint8_t** ppMatrix,uint32_t dwWidth,uint32_t dwHeight,uint32_t dwBitsperpixel, uint32_t dwBytesperline, bool bFlipImage)
+{
+ if (ppMatrix==NULL) return false;
+ if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)||
+ (dwBitsperpixel==24)||(dwBitsperpixel==32))) return false;
+
+ if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false;
+
+ if (dwBitsperpixel<24) SetGrayPalette();
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (dwBitsperpixel==32) AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ uint8_t *dst,*src;
+
+ for (uint32_t y = 0; y<dwHeight; y++) {
+ dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;
+ src = ppMatrix[y];
+ if (src){
+ if (dwBitsperpixel==32){
+ for(uint32_t x=0;x<dwWidth;x++){
+ *dst++=src[0];
+ *dst++=src[1];
+ *dst++=src[2];
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaSet(x,(bFlipImage?(dwHeight-1-y):y),src[3]);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ src+=4;
+ }
+ } else {
+ memcpy(dst,src,min(info.dwEffWidth,dwBytesperline));
+ }
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return lightness difference between elem1 and elem2
+ */
+int32_t CxImage::CompareColors(const void *elem1, const void *elem2)
+{
+ RGBQUAD* c1 = (RGBQUAD*)elem1;
+ RGBQUAD* c2 = (RGBQUAD*)elem2;
+
+ int32_t g1 = (int32_t)RGB2GRAY(c1->rgbRed,c1->rgbGreen,c1->rgbBlue);
+ int32_t g2 = (int32_t)RGB2GRAY(c2->rgbRed,c2->rgbGreen,c2->rgbBlue);
+
+ return (g1-g2);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * simply calls "if (memblock) free(memblock);".
+ * Useful when calling Encode for a memory buffer,
+ * from a DLL compiled with different memory management options.
+ * CxImage::FreeMemory will use the same memory environment used by Encode.
+ * \author [livecn]
+ */
+void CxImage::FreeMemory(void* memblock)
+{
+ if (memblock)
+ free(memblock);
+}
+////////////////////////////////////////////////////////////////////////////////
+//EOF
diff --git a/archive/hge/CxImage/ximage.h b/archive/hge/CxImage/ximage.h new file mode 100644 index 0000000..4eed84e --- /dev/null +++ b/archive/hge/CxImage/ximage.h @@ -0,0 +1,808 @@ +/*
+ * File: ximage.h
+ * Purpose: General Purpose Image Class
+ */
+/*
+ --------------------------------------------------------------------------------
+
+ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+ CxImage version 7.0.0 31/Dec/2010
+
+ CxImage : Copyright (C) 2001 - 2010, Davide Pizzolato
+
+ Original CImage and CImageIterator implementation are:
+ Copyright (C) 1995, Alejandro Aguilar Sierra (asierra(at)servidor(dot)unam(dot)mx)
+
+ Covered code is provided under this license on an "as is" basis, without warranty
+ of any kind, either expressed or implied, including, without limitation, warranties
+ that the covered code is free of defects, merchantable, fit for a particular purpose
+ or non-infringing. The entire risk as to the quality and performance of the covered
+ code is with you. Should any covered code prove defective in any respect, you (not
+ the initial developer or any other contributor) assume the cost of any necessary
+ servicing, repair or correction. This disclaimer of warranty constitutes an essential
+ part of this license. No use of any covered code is authorized hereunder except under
+ this disclaimer.
+
+ Permission is hereby granted to use, copy, modify, and distribute this
+ source code, or portions hereof, for any purpose, including commercial applications,
+ freely and without fee, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
+
+ --------------------------------------------------------------------------------
+
+ Other information about CxImage, and the latest version, can be found at the
+ CxImage home page: http://www.xdp.it/cximage/
+
+ --------------------------------------------------------------------------------
+ */
+#if !defined(__CXIMAGE_H)
+#define __CXIMAGE_H
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+#ifdef _LINUX
+#ifndef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE
+#endif
+ #include <unistd.h>
+ #include <arpa/inet.h>
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#include "xfile.h"
+#include "xiofile.h"
+#include "xmemfile.h"
+#include "ximadef.h" //<vho> adjust some #define
+
+/* see "ximacfg.h" for CxImage configuration options */
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage formats enumerator
+enum ENUM_CXIMAGE_FORMATS{
+CXIMAGE_FORMAT_UNKNOWN = 0,
+#if CXIMAGE_SUPPORT_BMP
+CXIMAGE_FORMAT_BMP = 1,
+#endif
+#if CXIMAGE_SUPPORT_GIF
+CXIMAGE_FORMAT_GIF = 2,
+#endif
+#if CXIMAGE_SUPPORT_JPG
+CXIMAGE_FORMAT_JPG = 3,
+#endif
+#if CXIMAGE_SUPPORT_PNG
+CXIMAGE_FORMAT_PNG = 4,
+#endif
+#if CXIMAGE_SUPPORT_ICO
+CXIMAGE_FORMAT_ICO = 5,
+#endif
+#if CXIMAGE_SUPPORT_TIF
+CXIMAGE_FORMAT_TIF = 6,
+#endif
+#if CXIMAGE_SUPPORT_TGA
+CXIMAGE_FORMAT_TGA = 7,
+#endif
+#if CXIMAGE_SUPPORT_PCX
+CXIMAGE_FORMAT_PCX = 8,
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+CXIMAGE_FORMAT_WBMP = 9,
+#endif
+#if CXIMAGE_SUPPORT_WMF
+CXIMAGE_FORMAT_WMF = 10,
+#endif
+#if CXIMAGE_SUPPORT_JP2
+CXIMAGE_FORMAT_JP2 = 11,
+#endif
+#if CXIMAGE_SUPPORT_JPC
+CXIMAGE_FORMAT_JPC = 12,
+#endif
+#if CXIMAGE_SUPPORT_PGX
+CXIMAGE_FORMAT_PGX = 13,
+#endif
+#if CXIMAGE_SUPPORT_PNM
+CXIMAGE_FORMAT_PNM = 14,
+#endif
+#if CXIMAGE_SUPPORT_RAS
+CXIMAGE_FORMAT_RAS = 15,
+#endif
+#if CXIMAGE_SUPPORT_JBG
+CXIMAGE_FORMAT_JBG = 16,
+#endif
+#if CXIMAGE_SUPPORT_MNG
+CXIMAGE_FORMAT_MNG = 17,
+#endif
+#if CXIMAGE_SUPPORT_SKA
+CXIMAGE_FORMAT_SKA = 18,
+#endif
+#if CXIMAGE_SUPPORT_RAW
+CXIMAGE_FORMAT_RAW = 19,
+#endif
+#if CXIMAGE_SUPPORT_PSD
+CXIMAGE_FORMAT_PSD = 20,
+#endif
+CMAX_IMAGE_FORMATS = CXIMAGE_SUPPORT_BMP + CXIMAGE_SUPPORT_GIF + CXIMAGE_SUPPORT_JPG +
+ CXIMAGE_SUPPORT_PNG + CXIMAGE_SUPPORT_MNG + CXIMAGE_SUPPORT_ICO +
+ CXIMAGE_SUPPORT_TIF + CXIMAGE_SUPPORT_TGA + CXIMAGE_SUPPORT_PCX +
+ CXIMAGE_SUPPORT_WBMP+ CXIMAGE_SUPPORT_WMF +
+ CXIMAGE_SUPPORT_JBG + CXIMAGE_SUPPORT_JP2 + CXIMAGE_SUPPORT_JPC +
+ CXIMAGE_SUPPORT_PGX + CXIMAGE_SUPPORT_PNM + CXIMAGE_SUPPORT_RAS +
+ CXIMAGE_SUPPORT_SKA + CXIMAGE_SUPPORT_RAW + CXIMAGE_SUPPORT_PSD + 1
+};
+
+#if CXIMAGE_SUPPORT_EXIF
+
+#define MAX_COMMENT 255
+#define MAX_SECTIONS 20
+
+typedef struct tag_ExifInfo {
+ char Version [5];
+ char CameraMake [32];
+ char CameraModel [40];
+ char DateTime [20];
+ int32_t Height, Width;
+ int32_t Orientation;
+ int32_t IsColor;
+ int32_t Process;
+ int32_t FlashUsed;
+ float FocalLength;
+ float ExposureTime;
+ float ApertureFNumber;
+ float Distance;
+ float CCDWidth;
+ float ExposureBias;
+ int32_t Whitebalance;
+ int32_t MeteringMode;
+ int32_t ExposureProgram;
+ int32_t ISOequivalent;
+ int32_t CompressionLevel;
+ float FocalplaneXRes;
+ float FocalplaneYRes;
+ float FocalplaneUnits;
+ float Xresolution;
+ float Yresolution;
+ float ResolutionUnit;
+ float Brightness;
+ char Comments[MAX_COMMENT+1];
+
+ uint8_t * ThumbnailPointer; /* Pointer at the thumbnail */
+ unsigned ThumbnailSize; /* Size of thumbnail. */
+
+ bool IsExif;
+} EXIFINFO;
+
+#endif //CXIMAGE_SUPPORT_EXIF
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage class
+/////////////////////////////////////////////////////////////////////////////
+class DLL_EXP CxImage
+{
+//extensible information collector
+typedef struct tagCxImageInfo {
+ uint32_t dwEffWidth; ///< uint32_t aligned scan line width
+ uint8_t* pImage; ///< THE IMAGE BITS
+ CxImage* pGhost; ///< if this is a ghost, pGhost points to the body
+ CxImage* pParent; ///< if this is a layer, pParent points to the body
+ uint32_t dwType; ///< original image format
+ char szLastError[256]; ///< debugging
+ int32_t nProgress; ///< monitor
+ int32_t nEscape; ///< escape
+ int32_t nBkgndIndex; ///< used for GIF, PNG, MNG
+ RGBQUAD nBkgndColor; ///< used for RGB transparency
+ float fQuality; ///< used for JPEG, JPEG2000 (0.0f ... 100.0f)
+ uint8_t nJpegScale; ///< used for JPEG [ignacio]
+ int32_t nFrame; ///< used for TIF, GIF, MNG : actual frame
+ int32_t nNumFrames; ///< used for TIF, GIF, MNG : total number of frames
+ uint32_t dwFrameDelay; ///< used for GIF, MNG
+ int32_t xDPI; ///< horizontal resolution
+ int32_t yDPI; ///< vertical resolution
+ RECT rSelectionBox; ///< bounding rectangle
+ uint8_t nAlphaMax; ///< max opacity (fade)
+ bool bAlphaPaletteEnabled; ///< true if alpha values in the palette are enabled.
+ bool bEnabled; ///< enables the painting functions
+ int32_t xOffset;
+ int32_t yOffset;
+ uint32_t dwCodecOpt[CMAX_IMAGE_FORMATS]; ///< for GIF, TIF : 0=def.1=unc,2=fax3,3=fax4,4=pack,5=jpg
+ RGBQUAD last_c; ///< for GetNearestIndex optimization
+ uint8_t last_c_index;
+ bool last_c_isvalid;
+ int32_t nNumLayers;
+ uint32_t dwFlags; ///< 0x??00000 = reserved, 0x00??0000 = blend mode, 0x0000???? = layer id - user flags
+ uint8_t dispmeth;
+ bool bGetAllFrames;
+ bool bLittleEndianHost;
+
+#if CXIMAGE_SUPPORT_EXIF
+ EXIFINFO ExifInfo;
+#endif
+
+} CXIMAGEINFO;
+
+public:
+ //public structures
+struct rgb_color { uint8_t r,g,b; };
+
+#if CXIMAGE_SUPPORT_WINDOWS
+// <VATI> text placement data
+// members must be initialized with the InitTextInfo(&this) function.
+typedef struct tagCxTextInfo
+{
+#if defined (_WIN32_WCE)
+ TCHAR text[256]; ///< text for windows CE
+#else
+ TCHAR text[4096]; ///< text (char -> TCHAR for UNICODE [Cesar M])
+#endif
+ LOGFONT lfont; ///< font and codepage data
+ COLORREF fcolor; ///< foreground color
+ int32_t align; ///< DT_CENTER, DT_RIGHT, DT_LEFT aligment for multiline text
+ uint8_t smooth; ///< text smoothing option. Default is false.
+ uint8_t opaque; ///< text has background or hasn't. Default is true.
+ ///< data for background (ignored if .opaque==FALSE)
+ COLORREF bcolor; ///< background color
+ float b_opacity; ///< opacity value for background between 0.0-1.0 Default is 0. (opaque)
+ uint8_t b_outline; ///< outline width for background (zero: no outline)
+ uint8_t b_round; ///< rounding radius for background rectangle. % of the height, between 0-50. Default is 10.
+ ///< (backgr. always has a frame: width = 3 pixel + 10% of height by default.)
+} CXTEXTINFO;
+#endif
+
+public:
+/** \addtogroup Constructors */ //@{
+ CxImage(uint32_t imagetype = 0);
+ CxImage(uint32_t dwWidth, uint32_t dwHeight, uint32_t wBpp, uint32_t imagetype = 0);
+ CxImage(const CxImage &src, bool copypixels = true, bool copyselection = true, bool copyalpha = true);
+#if CXIMAGE_SUPPORT_DECODE
+ CxImage(const TCHAR * filename, uint32_t imagetype); // For UNICODE support: char -> TCHAR
+ CxImage(FILE * stream, uint32_t imagetype);
+ CxImage(CxFile * stream, uint32_t imagetype);
+ CxImage(uint8_t * buffer, uint32_t size, uint32_t imagetype);
+#endif
+ virtual ~CxImage() { DestroyFrames(); Destroy(); };
+ CxImage& operator = (const CxImage&);
+//@}
+
+/** \addtogroup Initialization */ //@{
+ void* Create(uint32_t dwWidth, uint32_t dwHeight, uint32_t wBpp, uint32_t imagetype = 0);
+ bool Destroy();
+ bool DestroyFrames();
+ void Clear(uint8_t bval=0);
+ void Copy(const CxImage &src, bool copypixels = true, bool copyselection = true, bool copyalpha = true);
+ bool Transfer(CxImage &from, bool bTransferFrames = true);
+ bool CreateFromArray(uint8_t* pArray,uint32_t dwWidth,uint32_t dwHeight,uint32_t dwBitsperpixel, uint32_t dwBytesperline, bool bFlipImage);
+ bool CreateFromMatrix(uint8_t** ppMatrix,uint32_t dwWidth,uint32_t dwHeight,uint32_t dwBitsperpixel, uint32_t dwBytesperline, bool bFlipImage);
+ void FreeMemory(void* memblock);
+
+ uint32_t Dump(uint8_t * dst);
+ uint32_t UnDump(const uint8_t * src);
+ uint32_t DumpSize();
+
+//@}
+
+/** \addtogroup Attributes */ //@{
+ int32_t GetSize();
+ uint8_t* GetBits(uint32_t row = 0);
+ uint8_t GetColorType();
+ void* GetDIB() const;
+ uint32_t GetHeight() const;
+ uint32_t GetWidth() const;
+ uint32_t GetEffWidth() const;
+ uint32_t GetNumColors() const;
+ uint16_t GetBpp() const;
+ uint32_t GetType() const;
+ const char* GetLastError();
+ static const TCHAR* GetVersion();
+ static const float GetVersionNumber();
+
+ uint32_t GetFrameDelay() const;
+ void SetFrameDelay(uint32_t d);
+
+ void GetOffset(int32_t *x,int32_t *y);
+ void SetOffset(int32_t x,int32_t y);
+
+ uint8_t GetJpegQuality() const;
+ void SetJpegQuality(uint8_t q);
+ float GetJpegQualityF() const;
+ void SetJpegQualityF(float q);
+
+ uint8_t GetJpegScale() const;
+ void SetJpegScale(uint8_t q);
+
+#if CXIMAGE_SUPPORT_EXIF
+ EXIFINFO *GetExifInfo() {return &info.ExifInfo;};
+ bool GetExifThumbnail(const TCHAR *filename, const TCHAR *outname, int32_t imageType);
+ #if CXIMAGE_SUPPORT_TRANSFORMATION
+ bool RotateExif(int32_t orientation = 0);
+ #endif
+#endif
+
+ int32_t GetXDPI() const;
+ int32_t GetYDPI() const;
+ void SetXDPI(int32_t dpi);
+ void SetYDPI(int32_t dpi);
+
+ uint32_t GetClrImportant() const;
+ void SetClrImportant(uint32_t ncolors = 0);
+
+ int32_t GetProgress() const;
+ int32_t GetEscape() const;
+ void SetProgress(int32_t p);
+ void SetEscape(int32_t i);
+
+ int32_t GetTransIndex() const;
+ RGBQUAD GetTransColor();
+ void SetTransIndex(int32_t idx);
+ void SetTransColor(RGBQUAD rgb);
+ bool IsTransparent() const;
+
+ uint32_t GetCodecOption(uint32_t imagetype = 0);
+ bool SetCodecOption(uint32_t opt, uint32_t imagetype = 0);
+
+ uint32_t GetFlags() const;
+ void SetFlags(uint32_t flags, bool bLockReservedFlags = true);
+
+ uint8_t GetDisposalMethod() const;
+ void SetDisposalMethod(uint8_t dm);
+
+ bool SetType(uint32_t type);
+
+ static uint32_t GetNumTypes();
+ static uint32_t GetTypeIdFromName(const TCHAR* ext);
+ static uint32_t GetTypeIdFromIndex(const uint32_t index);
+ static uint32_t GetTypeIndexFromId(const uint32_t id);
+
+ bool GetRetreiveAllFrames() const;
+ void SetRetreiveAllFrames(bool flag);
+ CxImage * GetFrame(int32_t nFrame) const;
+
+ //void* GetUserData() const {return info.pUserData;}
+ //void SetUserData(void* pUserData) {info.pUserData = pUserData;}
+//@}
+
+/** \addtogroup Palette
+ * These functions have no effects on RGB images and in this case the returned value is always 0.
+ * @{ */
+ bool IsGrayScale();
+ bool IsIndexed() const;
+ bool IsSamePalette(CxImage &img, bool bCheckAlpha = true);
+ uint32_t GetPaletteSize();
+ RGBQUAD* GetPalette() const;
+ RGBQUAD GetPaletteColor(uint8_t idx);
+ bool GetPaletteColor(uint8_t i, uint8_t* r, uint8_t* g, uint8_t* b);
+ uint8_t GetNearestIndex(RGBQUAD c);
+ void BlendPalette(COLORREF cr,int32_t perc);
+ void SetGrayPalette();
+ void SetPalette(uint32_t n, uint8_t *r, uint8_t *g, uint8_t *b);
+ void SetPalette(RGBQUAD* pPal,uint32_t nColors=256);
+ void SetPalette(rgb_color *rgb,uint32_t nColors=256);
+ void SetPaletteColor(uint8_t idx, uint8_t r, uint8_t g, uint8_t b, uint8_t alpha=0);
+ void SetPaletteColor(uint8_t idx, RGBQUAD c);
+ void SetPaletteColor(uint8_t idx, COLORREF cr);
+ void SwapIndex(uint8_t idx1, uint8_t idx2);
+ void SwapRGB2BGR();
+ void SetStdPalette();
+//@}
+
+/** \addtogroup Pixel */ //@{
+ bool IsInside(int32_t x, int32_t y);
+ bool IsTransparent(int32_t x,int32_t y);
+ bool GetTransparentMask(CxImage* iDst = 0);
+ RGBQUAD GetPixelColor(int32_t x,int32_t y, bool bGetAlpha = true);
+ uint8_t GetPixelIndex(int32_t x,int32_t y);
+ uint8_t GetPixelGray(int32_t x, int32_t y);
+ void SetPixelColor(int32_t x,int32_t y,RGBQUAD c, bool bSetAlpha = false);
+ void SetPixelColor(int32_t x,int32_t y,COLORREF cr);
+ void SetPixelIndex(int32_t x,int32_t y,uint8_t i);
+ void DrawLine(int32_t StartX, int32_t EndX, int32_t StartY, int32_t EndY, RGBQUAD color, bool bSetAlpha=false);
+ void DrawLine(int32_t StartX, int32_t EndX, int32_t StartY, int32_t EndY, COLORREF cr);
+ void BlendPixelColor(int32_t x,int32_t y,RGBQUAD c, float blend, bool bSetAlpha = false);
+//@}
+
+protected:
+/** \addtogroup Protected */ //@{
+ uint8_t BlindGetPixelIndex(const int32_t x,const int32_t y);
+ RGBQUAD BlindGetPixelColor(const int32_t x,const int32_t y, bool bGetAlpha = true);
+ void *BlindGetPixelPointer(const int32_t x,const int32_t y);
+ void BlindSetPixelColor(int32_t x,int32_t y,RGBQUAD c, bool bSetAlpha = false);
+ void BlindSetPixelIndex(int32_t x,int32_t y,uint8_t i);
+//@}
+
+public:
+
+#if CXIMAGE_SUPPORT_INTERPOLATION
+/** \addtogroup Interpolation */ //@{
+ //overflow methods:
+ enum OverflowMethod {
+ OM_COLOR=1,
+ OM_BACKGROUND=2,
+ OM_TRANSPARENT=3,
+ OM_WRAP=4,
+ OM_REPEAT=5,
+ OM_MIRROR=6
+ };
+ void OverflowCoordinates(float &x, float &y, OverflowMethod const ofMethod);
+ void OverflowCoordinates(int32_t &x, int32_t &y, OverflowMethod const ofMethod);
+ RGBQUAD GetPixelColorWithOverflow(int32_t x, int32_t y, OverflowMethod const ofMethod=OM_BACKGROUND, RGBQUAD* const rplColor=0);
+ //interpolation methods:
+ enum InterpolationMethod {
+ IM_NEAREST_NEIGHBOUR=1,
+ IM_BILINEAR =2,
+ IM_BSPLINE =3,
+ IM_BICUBIC =4,
+ IM_BICUBIC2 =5,
+ IM_LANCZOS =6,
+ IM_BOX =7,
+ IM_HERMITE =8,
+ IM_HAMMING =9,
+ IM_SINC =10,
+ IM_BLACKMAN =11,
+ IM_BESSEL =12,
+ IM_GAUSSIAN =13,
+ IM_QUADRATIC =14,
+ IM_MITCHELL =15,
+ IM_CATROM =16,
+ IM_HANNING =17,
+ IM_POWER =18
+ };
+ RGBQUAD GetPixelColorInterpolated(float x,float y, InterpolationMethod const inMethod=IM_BILINEAR, OverflowMethod const ofMethod=OM_BACKGROUND, RGBQUAD* const rplColor=0);
+ RGBQUAD GetAreaColorInterpolated(float const xc, float const yc, float const w, float const h, InterpolationMethod const inMethod, OverflowMethod const ofMethod=OM_BACKGROUND, RGBQUAD* const rplColor=0);
+//@}
+
+protected:
+/** \addtogroup Protected */ //@{
+ void AddAveragingCont(RGBQUAD const &color, float const surf, float &rr, float &gg, float &bb, float &aa);
+//@}
+
+/** \addtogroup Kernels */ //@{
+public:
+ static float KernelBSpline(const float x);
+ static float KernelLinear(const float t);
+ static float KernelCubic(const float t);
+ static float KernelGeneralizedCubic(const float t, const float a=-1);
+ static float KernelLanczosSinc(const float t, const float r = 3);
+ static float KernelBox(const float x);
+ static float KernelHermite(const float x);
+ static float KernelHamming(const float x);
+ static float KernelSinc(const float x);
+ static float KernelBlackman(const float x);
+ static float KernelBessel_J1(const float x);
+ static float KernelBessel_P1(const float x);
+ static float KernelBessel_Q1(const float x);
+ static float KernelBessel_Order1(float x);
+ static float KernelBessel(const float x);
+ static float KernelGaussian(const float x);
+ static float KernelQuadratic(const float x);
+ static float KernelMitchell(const float x);
+ static float KernelCatrom(const float x);
+ static float KernelHanning(const float x);
+ static float KernelPower(const float x, const float a = 2);
+//@}
+#endif //CXIMAGE_SUPPORT_INTERPOLATION
+
+/** \addtogroup Painting */ //@{
+#if CXIMAGE_SUPPORT_WINDOWS
+ int32_t Blt(HDC pDC, int32_t x=0, int32_t y=0);
+ HBITMAP Draw2HBITMAP(HDC hdc, int32_t x, int32_t y, int32_t cx, int32_t cy, RECT* pClipRect, bool bSmooth);
+ HBITMAP MakeBitmap(HDC hdc = NULL, bool bTransparency = false);
+ HICON MakeIcon(HDC hdc = NULL, bool bTransparency = false);
+ HANDLE CopyToHandle();
+ bool CreateFromHANDLE(HANDLE hMem); //Windows objects (clipboard)
+ bool CreateFromHBITMAP(HBITMAP hbmp, HPALETTE hpal=0, bool bTransparency = false); //Windows resource
+ bool CreateFromHICON(HICON hico, bool bTransparency = false);
+ int32_t Draw(HDC hdc, int32_t x=0, int32_t y=0, int32_t cx = -1, int32_t cy = -1, RECT* pClipRect = 0, bool bSmooth = false, bool bFlipY = false);
+ int32_t Draw(HDC hdc, const RECT& rect, RECT* pClipRect=NULL, bool bSmooth = false, bool bFlipY = false);
+ int32_t Stretch(HDC hdc, int32_t xoffset, int32_t yoffset, int32_t xsize, int32_t ysize, uint32_t dwRop = SRCCOPY);
+ int32_t Stretch(HDC hdc, const RECT& rect, uint32_t dwRop = SRCCOPY);
+ int32_t Tile(HDC hdc, RECT *rc);
+ int32_t Draw2(HDC hdc, int32_t x=0, int32_t y=0, int32_t cx = -1, int32_t cy = -1);
+ int32_t Draw2(HDC hdc, const RECT& rect);
+ //int32_t DrawString(HDC hdc, int32_t x, int32_t y, const char* text, RGBQUAD color, const char* font, int32_t lSize=0, int32_t lWeight=400, uint8_t bItalic=0, uint8_t bUnderline=0, bool bSetAlpha=false);
+ int32_t DrawString(HDC hdc, int32_t x, int32_t y, const TCHAR* text, RGBQUAD color, const TCHAR* font, int32_t lSize=0, int32_t lWeight=400, uint8_t bItalic=0, uint8_t bUnderline=0, bool bSetAlpha=false);
+ // <VATI> extensions
+ int32_t DrawStringEx(HDC hdc, int32_t x, int32_t y, CXTEXTINFO *pTextType, bool bSetAlpha=false );
+ void InitTextInfo( CXTEXTINFO *txt );
+protected:
+ bool IsHBITMAPAlphaValid( HBITMAP hbmp );
+public:
+#endif //CXIMAGE_SUPPORT_WINDOWS
+//@}
+
+ // file operations
+#if CXIMAGE_SUPPORT_DECODE
+/** \addtogroup Decode */ //@{
+#ifdef WIN32
+ //bool Load(LPCWSTR filename, uint32_t imagetype=0);
+ bool LoadResource(HRSRC hRes, uint32_t imagetype, HMODULE hModule=NULL);
+#endif
+ // For UNICODE support: char -> TCHAR
+ bool Load(const TCHAR* filename, uint32_t imagetype=0);
+ //bool Load(const char * filename, uint32_t imagetype=0);
+ bool Decode(FILE * hFile, uint32_t imagetype);
+ bool Decode(CxFile * hFile, uint32_t imagetype);
+ bool Decode(uint8_t * buffer, uint32_t size, uint32_t imagetype);
+
+ bool CheckFormat(CxFile * hFile, uint32_t imagetype = 0);
+ bool CheckFormat(uint8_t * buffer, uint32_t size, uint32_t imagetype = 0);
+//@}
+#endif //CXIMAGE_SUPPORT_DECODE
+
+#if CXIMAGE_SUPPORT_ENCODE
+protected:
+/** \addtogroup Protected */ //@{
+ bool EncodeSafeCheck(CxFile *hFile);
+//@}
+
+public:
+/** \addtogroup Encode */ //@{
+#ifdef WIN32
+ //bool Save(LPCWSTR filename, uint32_t imagetype=0);
+#endif
+ // For UNICODE support: char -> TCHAR
+ bool Save(const TCHAR* filename, uint32_t imagetype);
+ //bool Save(const char * filename, uint32_t imagetype=0);
+ bool Encode(FILE * hFile, uint32_t imagetype);
+ bool Encode(CxFile * hFile, uint32_t imagetype);
+ bool Encode(CxFile * hFile, CxImage ** pImages, int32_t pagecount, uint32_t imagetype);
+ bool Encode(FILE *hFile, CxImage ** pImages, int32_t pagecount, uint32_t imagetype);
+ bool Encode(uint8_t * &buffer, int32_t &size, uint32_t imagetype);
+
+ bool Encode2RGBA(CxFile *hFile, bool bFlipY = false);
+ bool Encode2RGBA(uint8_t * &buffer, int32_t &size, bool bFlipY = false);
+//@}
+#endif //CXIMAGE_SUPPORT_ENCODE
+
+/** \addtogroup Attributes */ //@{
+ //misc.
+ bool IsValid() const;
+ bool IsEnabled() const;
+ void Enable(bool enable=true);
+
+ // frame operations
+ int32_t GetNumFrames() const;
+ int32_t GetFrame() const;
+ void SetFrame(int32_t nFrame);
+//@}
+
+#if CXIMAGE_SUPPORT_BASICTRANSFORMATIONS
+/** \addtogroup BasicTransformations */ //@{
+ bool GrayScale();
+ bool Flip(bool bFlipSelection = false, bool bFlipAlpha = true);
+ bool Mirror(bool bMirrorSelection = false, bool bMirrorAlpha = true);
+ bool Negative();
+ bool RotateLeft(CxImage* iDst = NULL);
+ bool RotateRight(CxImage* iDst = NULL);
+ bool IncreaseBpp(uint32_t nbit);
+//@}
+#endif //CXIMAGE_SUPPORT_BASICTRANSFORMATIONS
+
+#if CXIMAGE_SUPPORT_TRANSFORMATION
+/** \addtogroup Transformations */ //@{
+ // image operations
+ bool Rotate(float angle, CxImage* iDst = NULL);
+ bool Rotate2(float angle, CxImage *iDst = NULL, InterpolationMethod inMethod=IM_BILINEAR,
+ OverflowMethod ofMethod=OM_BACKGROUND, RGBQUAD *replColor=0,
+ bool const optimizeRightAngles=true, bool const bKeepOriginalSize=false);
+ bool Rotate180(CxImage* iDst = NULL);
+ bool Resample(int32_t newx, int32_t newy, int32_t mode = 1, CxImage* iDst = NULL);
+ bool Resample2(int32_t newx, int32_t newy, InterpolationMethod const inMethod=IM_BICUBIC2,
+ OverflowMethod const ofMethod=OM_REPEAT, CxImage* const iDst = NULL,
+ bool const disableAveraging=false);
+ bool DecreaseBpp(uint32_t nbit, bool errordiffusion, RGBQUAD* ppal = 0, uint32_t clrimportant = 0);
+ bool Dither(int32_t method = 0);
+ bool Crop(int32_t left, int32_t top, int32_t right, int32_t bottom, CxImage* iDst = NULL);
+ bool Crop(const RECT& rect, CxImage* iDst = NULL);
+ bool CropRotatedRectangle( int32_t topx, int32_t topy, int32_t width, int32_t height, float angle, CxImage* iDst = NULL);
+ bool Skew(float xgain, float ygain, int32_t xpivot=0, int32_t ypivot=0, bool bEnableInterpolation = false);
+ bool Expand(int32_t left, int32_t top, int32_t right, int32_t bottom, RGBQUAD canvascolor, CxImage* iDst = 0);
+ bool Expand(int32_t newx, int32_t newy, RGBQUAD canvascolor, CxImage* iDst = 0);
+ bool Thumbnail(int32_t newx, int32_t newy, RGBQUAD canvascolor, CxImage* iDst = 0);
+ bool CircleTransform(int32_t type,int32_t rmax=0,float Koeff=1.0f);
+ bool QIShrink(int32_t newx, int32_t newy, CxImage* const iDst = NULL, bool bChangeBpp = false);
+
+//@}
+#endif //CXIMAGE_SUPPORT_TRANSFORMATION
+
+#if CXIMAGE_SUPPORT_DSP
+/** \addtogroup DSP */ //@{
+ bool Contour();
+ bool HistogramStretch(int32_t method = 0, double threshold = 0);
+ bool HistogramEqualize();
+ bool HistogramNormalize();
+ bool HistogramRoot();
+ bool HistogramLog();
+ int32_t Histogram(int32_t* red, int32_t* green = 0, int32_t* blue = 0, int32_t* gray = 0, int32_t colorspace = 0);
+ bool Jitter(int32_t radius=2);
+ bool Repair(float radius = 0.25f, int32_t niterations = 1, int32_t colorspace = 0);
+ bool Combine(CxImage* r,CxImage* g,CxImage* b,CxImage* a, int32_t colorspace = 0);
+ bool FFT2(CxImage* srcReal, CxImage* srcImag, CxImage* dstReal, CxImage* dstImag, int32_t direction = 1, bool bForceFFT = true, bool bMagnitude = true);
+ bool Noise(int32_t level);
+ bool Median(int32_t Ksize=3);
+ bool Gamma(float gamma);
+ bool GammaRGB(float gammaR, float gammaG, float gammaB);
+ bool ShiftRGB(int32_t r, int32_t g, int32_t b);
+ bool Threshold(uint8_t level);
+ bool Threshold(CxImage* pThresholdMask);
+ bool Threshold2(uint8_t level, bool bDirection, RGBQUAD nBkgndColor, bool bSetAlpha = false);
+ bool Colorize(uint8_t hue, uint8_t sat, float blend = 1.0f);
+ bool Light(int32_t brightness, int32_t contrast = 0);
+ float Mean();
+ bool Filter(int32_t* kernel, int32_t Ksize, int32_t Kfactor, int32_t Koffset);
+ bool Erode(int32_t Ksize=2);
+ bool Dilate(int32_t Ksize=2);
+ bool Edge(int32_t Ksize=2);
+ void HuePalette(float correction=1);
+ enum ImageOpType { OpAdd, OpAnd, OpXor, OpOr, OpMask, OpSrcCopy, OpDstCopy, OpSub, OpSrcBlend, OpScreen, OpAvg, OpBlendAlpha };
+ void Mix(CxImage & imgsrc2, ImageOpType op, int32_t lXOffset = 0, int32_t lYOffset = 0, bool bMixAlpha = false);
+ void MixFrom(CxImage & imagesrc2, int32_t lXOffset, int32_t lYOffset);
+ bool UnsharpMask(float radius = 5.0f, float amount = 0.5f, int32_t threshold = 0);
+ bool Lut(uint8_t* pLut);
+ bool Lut(uint8_t* pLutR, uint8_t* pLutG, uint8_t* pLutB, uint8_t* pLutA = 0);
+ bool GaussianBlur(float radius = 1.0f, CxImage* iDst = 0);
+ bool TextBlur(uint8_t threshold = 100, uint8_t decay = 2, uint8_t max_depth = 5, bool bBlurHorizontal = true, bool bBlurVertical = true, CxImage* iDst = 0);
+ bool SelectiveBlur(float radius = 1.0f, uint8_t threshold = 25, CxImage* iDst = 0);
+ bool Solarize(uint8_t level = 128, bool bLinkedChannels = true);
+ bool FloodFill(const int32_t xStart, const int32_t yStart, const RGBQUAD cFillColor, const uint8_t tolerance = 0,
+ uint8_t nOpacity = 255, const bool bSelectFilledArea = false, const uint8_t nSelectionLevel = 255);
+ bool Saturate(const int32_t saturation, const int32_t colorspace = 1);
+ bool ConvertColorSpace(const int32_t dstColorSpace, const int32_t srcColorSpace);
+ int32_t OptimalThreshold(int32_t method = 0, RECT * pBox = 0, CxImage* pContrastMask = 0);
+ bool AdaptiveThreshold(int32_t method = 0, int32_t nBoxSize = 64, CxImage* pContrastMask = 0, int32_t nBias = 0, float fGlobalLocalBalance = 0.5f);
+ bool RedEyeRemove(float strength = 0.8f);
+ bool Trace(RGBQUAD color_target, RGBQUAD color_trace);
+
+//@}
+
+protected:
+/** \addtogroup Protected */ //@{
+ bool IsPowerof2(int32_t x);
+ bool FFT(int32_t dir,int32_t m,double *x,double *y);
+ bool DFT(int32_t dir,int32_t m,double *x1,double *y1,double *x2,double *y2);
+ bool RepairChannel(CxImage *ch, float radius);
+ // <nipper>
+ int32_t gen_convolve_matrix (float radius, float **cmatrix_p);
+ float* gen_lookup_table (float *cmatrix, int32_t cmatrix_length);
+ void blur_line (float *ctable, float *cmatrix, int32_t cmatrix_length, uint8_t* cur_col, uint8_t* dest_col, int32_t y, int32_t bytes);
+ void blur_text (uint8_t threshold, uint8_t decay, uint8_t max_depth, CxImage* iSrc, CxImage* iDst, uint8_t bytes);
+//@}
+
+public:
+/** \addtogroup ColorSpace */ //@{
+ bool SplitRGB(CxImage* r,CxImage* g,CxImage* b);
+ bool SplitYUV(CxImage* y,CxImage* u,CxImage* v);
+ bool SplitHSL(CxImage* h,CxImage* s,CxImage* l);
+ bool SplitYIQ(CxImage* y,CxImage* i,CxImage* q);
+ bool SplitXYZ(CxImage* x,CxImage* y,CxImage* z);
+ bool SplitCMYK(CxImage* c,CxImage* m,CxImage* y,CxImage* k);
+ static RGBQUAD HSLtoRGB(COLORREF cHSLColor);
+ static RGBQUAD RGBtoHSL(RGBQUAD lRGBColor);
+ static RGBQUAD HSLtoRGB(RGBQUAD lHSLColor);
+ static RGBQUAD YUVtoRGB(RGBQUAD lYUVColor);
+ static RGBQUAD RGBtoYUV(RGBQUAD lRGBColor);
+ static RGBQUAD YIQtoRGB(RGBQUAD lYIQColor);
+ static RGBQUAD RGBtoYIQ(RGBQUAD lRGBColor);
+ static RGBQUAD XYZtoRGB(RGBQUAD lXYZColor);
+ static RGBQUAD RGBtoXYZ(RGBQUAD lRGBColor);
+#endif //CXIMAGE_SUPPORT_DSP
+ static RGBQUAD RGBtoRGBQUAD(COLORREF cr);
+ static COLORREF RGBQUADtoRGB (RGBQUAD c);
+//@}
+
+/** \addtogroup Selection */ //@{
+ bool SelectionIsValid();
+#if CXIMAGE_SUPPORT_SELECTION
+ bool SelectionClear(uint8_t level = 0);
+ bool SelectionCreate();
+ bool SelectionDelete();
+ bool SelectionInvert();
+ bool SelectionMirror();
+ bool SelectionFlip();
+ bool SelectionAddRect(RECT r, uint8_t level = 255);
+ bool SelectionAddEllipse(RECT r, uint8_t level = 255);
+ bool SelectionAddPolygon(POINT *points, int32_t npoints, uint8_t level = 255);
+ bool SelectionAddColor(RGBQUAD c, uint8_t level = 255);
+ bool SelectionAddPixel(int32_t x, int32_t y, uint8_t level = 255);
+ bool SelectionCopy(CxImage &from);
+ bool SelectionIsInside(int32_t x, int32_t y);
+ void SelectionGetBox(RECT& r);
+ bool SelectionToHRGN(HRGN& region);
+ bool SelectionSplit(CxImage *dest);
+ uint8_t SelectionGet(const int32_t x,const int32_t y);
+ bool SelectionSet(CxImage &from);
+ void SelectionRebuildBox();
+ uint8_t* SelectionGetPointer(const int32_t x = 0,const int32_t y = 0);
+//@}
+
+protected:
+/** \addtogroup Protected */ //@{
+ bool BlindSelectionIsInside(int32_t x, int32_t y);
+ uint8_t BlindSelectionGet(const int32_t x,const int32_t y);
+ void SelectionSet(const int32_t x,const int32_t y,const uint8_t level);
+
+public:
+
+#endif //CXIMAGE_SUPPORT_SELECTION
+//@}
+
+#if CXIMAGE_SUPPORT_ALPHA
+/** \addtogroup Alpha */ //@{
+ void AlphaClear();
+ bool AlphaCreate();
+ void AlphaDelete();
+ void AlphaInvert();
+ bool AlphaMirror();
+ bool AlphaFlip();
+ bool AlphaCopy(CxImage &from);
+ bool AlphaSplit(CxImage *dest);
+ void AlphaStrip();
+ void AlphaSet(uint8_t level);
+ bool AlphaSet(CxImage &from);
+ void AlphaSet(const int32_t x,const int32_t y,const uint8_t level);
+ uint8_t AlphaGet(const int32_t x,const int32_t y);
+ uint8_t AlphaGetMax() const;
+ void AlphaSetMax(uint8_t nAlphaMax);
+ bool AlphaIsValid();
+ uint8_t* AlphaGetPointer(const int32_t x = 0,const int32_t y = 0);
+ bool AlphaFromTransparency();
+
+ void AlphaPaletteClear();
+ void AlphaPaletteEnable(bool enable=true);
+ bool AlphaPaletteIsEnabled();
+ bool AlphaPaletteIsValid();
+ bool AlphaPaletteSplit(CxImage *dest);
+//@}
+
+protected:
+/** \addtogroup Protected */ //@{
+ uint8_t BlindAlphaGet(const int32_t x,const int32_t y);
+//@}
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+public:
+#if CXIMAGE_SUPPORT_LAYERS
+/** \addtogroup Layers */ //@{
+ bool LayerCreate(int32_t position = -1);
+ bool LayerDelete(int32_t position = -1);
+ void LayerDeleteAll();
+ CxImage* GetLayer(int32_t position);
+ CxImage* GetParent() const;
+ int32_t GetNumLayers() const;
+ int32_t LayerDrawAll(HDC hdc, int32_t x=0, int32_t y=0, int32_t cx = -1, int32_t cy = -1, RECT* pClipRect = 0, bool bSmooth = false);
+ int32_t LayerDrawAll(HDC hdc, const RECT& rect, RECT* pClipRect=NULL, bool bSmooth = false);
+//@}
+#endif //CXIMAGE_SUPPORT_LAYERS
+
+protected:
+/** \addtogroup Protected */ //@{
+ void Startup(uint32_t imagetype = 0);
+ void CopyInfo(const CxImage &src);
+ void Ghost(const CxImage *src);
+ void RGBtoBGR(uint8_t *buffer, int32_t length);
+ static float HueToRGB(float n1,float n2, float hue);
+ void Bitfield2RGB(uint8_t *src, uint32_t redmask, uint32_t greenmask, uint32_t bluemask, uint8_t bpp);
+ static int32_t CompareColors(const void *elem1, const void *elem2);
+ int16_t m_ntohs(const int16_t word);
+ int32_t m_ntohl(const int32_t dword);
+ void bihtoh(BITMAPINFOHEADER* bih);
+
+ void* pDib; //contains the header, the palette, the pixels
+ BITMAPINFOHEADER head; //standard header
+ CXIMAGEINFO info; //extended information
+ uint8_t* pSelection; //selected region
+ uint8_t* pAlpha; //alpha channel
+ CxImage** ppLayers; //generic layers
+ CxImage** ppFrames;
+//@}
+};
+
+////////////////////////////////////////////////////////////////////////////
+#endif // !defined(__CXIMAGE_H)
diff --git a/archive/hge/CxImage/ximagif.cpp b/archive/hge/CxImage/ximagif.cpp new file mode 100644 index 0000000..8c94b9e --- /dev/null +++ b/archive/hge/CxImage/ximagif.cpp @@ -0,0 +1,1681 @@ +/*
+ * File: ximagif.cpp
+ * Purpose: Platform Independent GIF Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximagif.h"
+
+#if CXIMAGE_SUPPORT_GIF
+
+#include "ximaiter.h"
+
+#if defined (_WIN32_WCE)
+ #define assert(s)
+#else
+ #include <assert.h>
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+CxImageGIF::CxImageGIF(): CxImage(CXIMAGE_FORMAT_GIF)
+{
+ buf = new uint8_t [GIFBUFTAM + 1];
+
+ stack = new uint8_t [MAX_CODES + 1];
+ suffix = new uint8_t [MAX_CODES + 1];
+ prefix = new uint16_t [MAX_CODES + 1];
+
+ htab = new int32_t [HSIZE];
+ codetab = new uint16_t [HSIZE];
+
+ byte_buff = new uint8_t [257];
+ accum = new char [256];
+ m_comment = new char [256];
+
+ m_loops=0;
+ info.dispmeth=0;
+ m_comment[0]='\0';
+
+}
+////////////////////////////////////////////////////////////////////////////////
+CxImageGIF::~CxImageGIF()
+{
+ delete [] buf;
+
+ delete [] stack;
+ delete [] suffix;
+ delete [] prefix;
+
+ delete [] htab;
+ delete [] codetab;
+
+ delete [] byte_buff;
+ delete [] accum;
+ delete [] m_comment;
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageGIF::Decode(CxFile *fp)
+{
+ /* AD - for transparency */
+ struct_dscgif dscgif;
+ struct_image image;
+ struct_TabCol TabCol;
+
+ if (fp == NULL) return false;
+
+ fp->Read(&dscgif,/*sizeof(dscgif)*/13,1);
+ //if (strncmp(dscgif.header,"GIF8",3)!=0) {
+ if (strncmp(dscgif.header,"GIF8",4)!=0) return FALSE;
+
+ // Avoid Byte order problem with Mac <AMSN>
+ dscgif.scrheight = m_ntohs(dscgif.scrheight);
+ dscgif.scrwidth = m_ntohs(dscgif.scrwidth);
+
+ if (info.nEscape == -1) {
+ // Return output dimensions only
+ head.biWidth = dscgif.scrwidth;
+ head.biHeight = dscgif.scrheight;
+ info.dwType = CXIMAGE_FORMAT_GIF;
+ return true;
+ }
+
+ /* AD - for interlace */
+ TabCol.sogct = (int16_t)(1 << ((dscgif.pflds & 0x07)+1));
+ TabCol.colres = (int16_t)(((dscgif.pflds & 0x70) >> 4) + 1);
+
+ // assume that the image is a truecolor-gif if
+ // 1) no global color map found
+ // 2) (image.w, image.h) of the 1st image != (dscgif.scrwidth, dscgif.scrheight)
+ int32_t bTrueColor=0;
+ CxImage* imaRGB=NULL;
+
+ // Global colour map?
+ if (dscgif.pflds & 0x80)
+ fp->Read(TabCol.paleta,sizeof(struct rgb_color)*TabCol.sogct,1);
+ else
+ bTrueColor++; //first chance for a truecolor gif
+
+ int32_t first_transparent_index = 0;
+
+ int32_t iImage = 0;
+ info.nNumFrames=get_num_frames(fp,&TabCol,&dscgif);
+
+ if ((info.nFrame<0)||(info.nFrame>=info.nNumFrames)) return false;
+
+ //it cannot be a true color GIF with only one frame
+ if (info.nNumFrames == 1)
+ bTrueColor=0;
+
+ char ch;
+ bool bPreviousWasNull = true;
+ int32_t prevdispmeth = 0;
+ CxImage *previousFrame = NULL;
+
+ for (BOOL bContinue = TRUE; bContinue; )
+ {
+ if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;}
+
+ if (info.nEscape > 0) return false; // <vho> - cancel decoding
+ if (bPreviousWasNull || ch==0)
+ {
+ switch (ch)
+ {
+ case '!': // extension
+ {
+ bContinue = DecodeExtension(fp);
+ break;
+ }
+ case ',': // image
+ {
+ assert(sizeof(image) == 9);
+ fp->Read(&image,sizeof(image),1);
+ //avoid byte order problems with Solaris <candan> <AMSN>
+ image.l = m_ntohs(image.l);
+ image.t = m_ntohs(image.t);
+ image.w = m_ntohs(image.w);
+ image.h = m_ntohs(image.h);
+
+ if (((image.l + image.w) > dscgif.scrwidth)||((image.t + image.h) > dscgif.scrheight))
+ break;
+
+ // check if it could be a truecolor gif
+ if ((iImage==0) && (image.w != dscgif.scrwidth) && (image.h != dscgif.scrheight))
+ bTrueColor++;
+
+ rgb_color locpal[256]; //Local Palette
+ rgb_color* pcurpal = TabCol.paleta; //Current Palette
+ int16_t palcount = TabCol.sogct; //Current Palette color count
+
+ // Local colour map?
+ if (image.pf & 0x80) {
+ palcount = (int16_t)(1 << ((image.pf & 0x07) +1));
+ assert(3 == sizeof(struct rgb_color));
+ fp->Read(locpal,sizeof(struct rgb_color)*palcount,1);
+ pcurpal = locpal;
+ }
+
+ int32_t bpp; //<DP> select the correct bit per pixel value
+ if (palcount <= 2) bpp = 1;
+ else if (palcount <= 16) bpp = 4;
+ else bpp = 8;
+
+ CxImageGIF backimage;
+ backimage.CopyInfo(*this);
+ if (iImage==0){
+ //first frame: build image background
+ backimage.Create(dscgif.scrwidth, dscgif.scrheight, bpp, CXIMAGE_FORMAT_GIF);
+ first_transparent_index = info.nBkgndIndex;
+ backimage.Clear((uint8_t)gifgce.transpcolindex);
+ previousFrame = new CxImage(backimage);
+ previousFrame->SetRetreiveAllFrames(false);
+ } else {
+ //generic frame: handle disposal method from previous one
+ /*Values : 0 - No disposal specified. The decoder is
+ not required to take any action.
+ 1 - Do not dispose. The graphic is to be left
+ in place.
+ 2 - Restore to background color. The area used by the
+ graphic must be restored to the background color.
+ 3 - Restore to previous. The decoder is required to
+ restore the area overwritten by the graphic with
+ what was there prior to rendering the graphic.
+ */
+ /* backimage.Copy(*this);
+ if (prevdispmeth==2){
+ backimage.Clear((uint8_t)first_transparent_index);
+ }*/
+ if (prevdispmeth==2){
+ backimage.Copy(*this,false,false,false);
+ backimage.Clear((uint8_t)first_transparent_index);
+ } else if (prevdispmeth==3) {
+ backimage.Copy(*this,false,false,false);
+ backimage.Create(previousFrame->GetWidth(),
+ previousFrame->GetHeight(),
+ previousFrame->GetBpp(),CXIMAGE_FORMAT_GIF);
+ memcpy(backimage.GetDIB(),previousFrame->GetDIB(),
+ backimage.GetSize());
+ //backimage.AlphaSet(*previousFrame);
+ } else {
+ backimage.Copy(*this);
+ }
+ }
+
+ //active frame
+ Create(image.w, image.h, bpp, CXIMAGE_FORMAT_GIF);
+
+ if ((image.pf & 0x80) || (dscgif.pflds & 0x80)) {
+ uint8_t r[256], g[256], b[256];
+ int32_t i;//, has_white = 0;
+
+ for (i=0; i < palcount; i++) {
+ r[i] = pcurpal[i].r;
+ g[i] = pcurpal[i].g;
+ b[i] = pcurpal[i].b;
+ //if (RGB(r[i],g[i],b[i]) == 0xFFFFFF) has_white = 1;
+ }
+
+ // Force transparency colour white...
+ //if (0) if (info.nBkgndIndex >= 0)
+ // r[info.nBkgndIndex] = g[info.nBkgndIndex] = b[info.nBkgndIndex] = 255;
+ // Fill in with white // AD
+ if (info.nBkgndIndex >= 0) {
+ while (i < 256) {
+ //has_white = 1;
+ r[i] = g[i] = b[i] = 255;
+ i++;
+ }
+ }
+
+ // Force last colour to white... // AD
+ //if ((info.nBkgndIndex >= 0) && !has_white) {
+ // r[255] = g[255] = b[255] = 255;
+ //}
+
+ SetPalette((info.nBkgndIndex >= 0 ? 256 : palcount), r, g, b);
+ }
+
+ CImageIterator* iter = new CImageIterator(this);
+ iter->Upset();
+ int32_t badcode=0;
+ ibf = GIFBUFTAM+1;
+
+ interlaced = image.pf & 0x40;
+ iheight = image.h;
+ istep = 8;
+ iypos = 0;
+ ipass = 0;
+
+ int32_t pos_start = fp->Tell();
+ //if (interlaced) log << "Interlaced" << endl;
+ decoder(fp, iter, image.w, badcode);
+ delete iter;
+
+ if (info.nEscape) return false; // <vho> - cancel decoding
+
+ if (bTrueColor<2 ){ //standard GIF: mix frame with background
+ backimage.IncreaseBpp(bpp);
+ backimage.GifMix(*this,image);
+ backimage.SetTransIndex(first_transparent_index);
+ backimage.SetPalette(GetPalette());
+ Transfer(backimage,false);
+ } else { //it's a truecolor gif!
+ //force full image decoding
+ info.nFrame=info.nNumFrames-1;
+ //build the RGB image
+ if (imaRGB==NULL) imaRGB = new CxImage(dscgif.scrwidth,dscgif.scrheight,24,CXIMAGE_FORMAT_GIF);
+ //copy the partial image into the full RGB image
+ for(int32_t y=0;y<image.h;y++){
+ for (int32_t x=0;x<image.w;x++){
+ imaRGB->SetPixelColor(x+image.l,dscgif.scrheight-1-image.t-y,GetPixelColor(x,image.h-y-1));
+ }
+ }
+ }
+
+ prevdispmeth = (gifgce.flags >> 2) & 0x7;
+
+ //restore the correct position in the file for the next image
+ if (badcode){
+ seek_next_image(fp,pos_start);
+ } else {
+ fp->Seek(-(ibfmax - ibf - 1), SEEK_CUR);
+ }
+
+ if (info.bGetAllFrames && imaRGB == NULL) {
+ if (iImage == 0) {
+ DestroyFrames();
+ ppFrames = new CxImage*[info.nNumFrames];
+ for(int32_t frameIdx = 0; frameIdx < info.nNumFrames; frameIdx++){
+ ppFrames[frameIdx] = NULL;
+ }
+ }
+ ppFrames[iImage] = new CxImage(*this);
+ ppFrames[iImage]->SetRetreiveAllFrames(false);
+ }
+ if (prevdispmeth <= 1) {
+ delete previousFrame;
+ previousFrame = new CxImage(*this);
+ previousFrame->SetRetreiveAllFrames(false);
+ }
+
+ if ((info.nFrame==iImage) && (info.bGetAllFrames==false)) bContinue=false; else iImage++;
+
+ break;
+ }
+ case ';': //terminator
+ bContinue=false;
+ break;
+ default:
+ bPreviousWasNull = (ch==0);
+ break;
+ }
+ }
+ }
+
+ if (bTrueColor>=2 && imaRGB){
+ if (gifgce.flags & 0x1){
+ imaRGB->SetTransColor(GetPaletteColor((uint8_t)info.nBkgndIndex));
+ imaRGB->SetTransIndex(0);
+ }
+ Transfer(*imaRGB);
+ }
+ delete imaRGB;
+
+ delete previousFrame;
+
+ return true;
+
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageGIF::DecodeExtension(CxFile *fp)
+{
+ bool bContinue;
+ uint8_t count;
+ uint8_t fc;
+
+ bContinue = (1 == fp->Read(&fc, sizeof(fc), 1));
+ if (bContinue) {
+ /* AD - for transparency */
+ if (fc == 0xF9) {
+ bContinue = (1 == fp->Read(&count, sizeof(count), 1));
+ if (bContinue) {
+ assert(sizeof(gifgce) == 4);
+ bContinue = (count == fp->Read(&gifgce, 1, sizeof(gifgce)));
+ gifgce.delaytime = m_ntohs(gifgce.delaytime); // Avoid Byte order problem with Mac <AMSN>
+ if (bContinue) {
+ info.nBkgndIndex = (gifgce.flags & 0x1) ? gifgce.transpcolindex : -1;
+ info.dwFrameDelay = gifgce.delaytime;
+ SetDisposalMethod((gifgce.flags >> 2) & 0x7);
+ } } }
+
+ if (fc == 0xFE) { //<DP> Comment block
+ bContinue = (1 == fp->Read(&count, sizeof(count), 1));
+ if (bContinue) {
+ bContinue = (1 == fp->Read(m_comment, count, 1));
+ m_comment[count]='\0';
+ } }
+
+ if (fc == 0xFF) { //<DP> Application Extension block
+ bContinue = (1 == fp->Read(&count, sizeof(count), 1));
+ if (bContinue) {
+ bContinue = (count==11);
+ if (bContinue){
+ char AppID[11];
+ bContinue = (1 == fp->Read(AppID, count, 1));
+ if (bContinue) {
+ bContinue = (1 == fp->Read(&count, sizeof(count), 1));
+ if (bContinue) {
+ uint8_t* dati = (uint8_t*)malloc(count);
+ bContinue = (dati!=NULL);
+ if (bContinue){
+ bContinue = (1 == fp->Read(dati, count, 1));
+ if (count>2){
+ m_loops = dati[1]+256*dati[2];
+ }
+ }
+ free(dati);
+ } } } } }
+
+ while (bContinue && fp->Read(&count, sizeof(count), 1) && count) {
+ //log << "Skipping " << count << " bytes" << endl;
+ fp->Seek(count, SEEK_CUR);
+ }
+ }
+ return bContinue;
+
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+
+// - This external (machine specific) function is expected to return
+// either the next uint8_t from the GIF file, or a negative error number.
+int32_t CxImageGIF::get_byte(CxFile* file)
+{
+ if (ibf>=GIFBUFTAM){
+ // FW 06/02/98 >>>
+ ibfmax = (int32_t)file->Read( buf , 1 , GIFBUFTAM) ;
+ if( ibfmax < GIFBUFTAM ) buf[ ibfmax ] = 255 ;
+ // FW 06/02/98 <<<
+ ibf = 0;
+ }
+ if (ibf>=ibfmax) return -1; //<DP> avoid overflows
+ return buf[ibf++];
+}
+////////////////////////////////////////////////////////////////////////////////
+/* - This function takes a full line of pixels (one uint8_t per pixel) and
+ * displays them (or does whatever your program wants with them...). It
+ * should return zero, or negative if an error or some other event occurs
+ * which would require aborting the decode process... Note that the length
+ * passed will almost always be equal to the line length passed to the
+ * decoder function, with the sole exception occurring when an ending code
+ * occurs in an odd place in the GIF file... In any case, linelen will be
+ * equal to the number of pixels passed...
+*/
+int32_t CxImageGIF::out_line(CImageIterator* iter, uint8_t *pixels, int32_t linelen)
+{
+ if (iter == NULL || pixels == NULL)
+ return -1;
+
+ //<DP> for 1 & 4 bpp images, the pixels are compressed
+ if (head.biBitCount < 8){
+ for(int32_t x=0;x<head.biWidth;x++){
+ uint8_t pos;
+ uint8_t* iDst= pixels + (x*head.biBitCount >> 3);
+ if (head.biBitCount==4){
+ pos = (uint8_t)(4*(1-x%2));
+ *iDst &= ~(0x0F<<pos);
+ *iDst |= ((pixels[x] & 0x0F)<<pos);
+ } else if (head.biBitCount==1){
+ pos = (uint8_t)(7-x%8);
+ *iDst &= ~(0x01<<pos);
+ *iDst |= ((pixels[x] & 0x01)<<pos);
+ }
+ }
+ }
+
+ /* AD - for interlace */
+ if (interlaced) {
+ iter->SetY(iheight-iypos-1);
+ iter->SetRow(pixels, linelen);
+
+ if ((iypos += istep) >= iheight) {
+ do {
+ if (ipass++ > 0) istep /= 2;
+ iypos = istep / 2;
+ }
+ while (iypos > iheight);
+ }
+ return 0;
+ } else {
+ if (iter->ItOK()) {
+ iter->SetRow(pixels, linelen);
+ (void)iter->PrevRow();
+ return 0;
+ } else {
+ // puts("chafeo");
+ return -1;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+// SaveFile - writes GIF87a gif file
+// Randy Spann 6/15/97
+// R.Spann@ConnRiver.net
+bool CxImageGIF::Encode(CxFile * fp)
+{
+ if (EncodeSafeCheck(fp)) return false;
+
+ if(head.biBitCount > 8) {
+ //strcpy(info.szLastError,"GIF Images must be 8 bit or less");
+ //return FALSE;
+ return EncodeRGB(fp);
+ }
+
+ if ( GetNumFrames()>1 && ppFrames ) {
+ return Encode(fp, ppFrames, GetNumFrames() );
+ }
+
+ EncodeHeader(fp);
+
+ EncodeExtension(fp);
+
+ EncodeComment(fp);
+
+ EncodeBody(fp);
+
+ fp->PutC(';'); // Write the GIF file terminator
+
+ return true; // done!
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageGIF::Encode(CxFile * fp, CxImage ** pImages, int32_t pagecount, bool bLocalColorMap, bool bLocalDispMeth)
+{
+ cx_try {
+ if (fp==NULL) cx_throw("invalid file pointer");
+ if (pImages==NULL || pagecount<=0 || pImages[0]==NULL) cx_throw("multipage GIF, no images!");
+
+ int32_t i;
+ for (i=0; i<pagecount; i++){
+ if (pImages[i]==NULL)
+ cx_throw("Bad image pointer");
+ if (!(pImages[i]->IsValid()))
+ cx_throw("Empty image");
+ if (pImages[i]->GetNumColors()==0)
+ cx_throw("CxImageGIF::Encode cannot create animated GIFs with a true color frame. Use DecreaseBpp before");
+ }
+
+ CxImageGIF ghost;
+
+ //write the first image
+ ghost.Ghost(pImages[0]);
+ ghost.EncodeHeader(fp);
+
+ if (m_loops!=1){
+ ghost.SetLoops(max(0,m_loops-1));
+ ghost.EncodeLoopExtension(fp);
+ }
+
+ if (bLocalDispMeth) {
+ ghost.EncodeExtension(fp);
+ } else {
+ uint8_t dm = ghost.GetDisposalMethod();
+ ghost.SetDisposalMethod(GetDisposalMethod());
+ ghost.EncodeExtension(fp);
+ ghost.SetDisposalMethod(dm);
+ }
+
+ EncodeComment(fp);
+
+ ghost.EncodeBody(fp);
+
+ for (i=1; i<pagecount; i++){
+ ghost.Ghost(pImages[i]);
+
+ if (bLocalDispMeth) {
+ ghost.EncodeExtension(fp);
+ } else {
+ uint8_t dm = ghost.GetDisposalMethod();
+ ghost.SetDisposalMethod(GetDisposalMethod());
+ ghost.EncodeExtension(fp);
+ ghost.SetDisposalMethod(dm);
+ }
+
+ ghost.EncodeBody(fp,bLocalColorMap);
+ }
+
+ fp->PutC(';'); // Write the GIF file terminator
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::EncodeHeader(CxFile *fp)
+{
+ fp->Write("GIF89a",1,6); //GIF Header
+
+ Putword(head.biWidth,fp); //Logical screen descriptor
+ Putword(head.biHeight,fp);
+
+ uint8_t Flags;
+ if (head.biClrUsed==0){
+ Flags=0x11;
+ } else {
+ Flags = 0x80;
+ Flags |=(head.biBitCount - 1) << 5;
+ Flags |=(head.biBitCount - 1);
+ }
+
+ fp->PutC(Flags); //GIF "packed fields"
+ fp->PutC(0); //GIF "BackGround"
+ fp->PutC(0); //GIF "pixel aspect ratio"
+
+ if (head.biClrUsed!=0){
+ RGBQUAD* pPal = GetPalette();
+ for(uint32_t i=0; i<head.biClrUsed; ++i)
+ {
+ fp->PutC(pPal[i].rgbRed);
+ fp->PutC(pPal[i].rgbGreen);
+ fp->PutC(pPal[i].rgbBlue);
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::EncodeExtension(CxFile *fp)
+{
+ // TRK BEGIN : transparency
+ fp->PutC('!');
+ fp->PutC(TRANSPARENCY_CODE);
+
+ gifgce.flags = 0;
+ gifgce.flags |= ((info.nBkgndIndex != -1) ? 1 : 0);
+ gifgce.flags |= ((GetDisposalMethod() & 0x7) << 2);
+ gifgce.delaytime = (uint16_t)info.dwFrameDelay;
+ gifgce.transpcolindex = (uint8_t)info.nBkgndIndex;
+
+ //Invert byte order in case we use a byte order arch, then set it back <AMSN>
+ gifgce.delaytime = m_ntohs(gifgce.delaytime);
+ fp->PutC(sizeof(gifgce));
+ fp->Write(&gifgce, sizeof(gifgce), 1);
+ gifgce.delaytime = m_ntohs(gifgce.delaytime);
+
+ fp->PutC(0);
+ // TRK END
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::EncodeLoopExtension(CxFile *fp)
+{
+ fp->PutC('!'); //byte 1 : 33 (hex 0x21) GIF Extension code
+ fp->PutC(255); //byte 2 : 255 (hex 0xFF) Application Extension Label
+ fp->PutC(11); //byte 3 : 11 (hex (0x0B) Length of Application Block (eleven bytes of data to follow)
+ fp->Write("NETSCAPE2.0",11,1);
+ fp->PutC(3); //byte 15 : 3 (hex 0x03) Length of Data Sub-Block (three bytes of data to follow)
+ fp->PutC(1); //byte 16 : 1 (hex 0x01)
+ Putword(m_loops,fp); //bytes 17 to 18 : 0 to 65535, an unsigned integer in lo-hi byte format.
+ //This indicate the number of iterations the loop should be executed.
+ fp->PutC(0); //bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator.
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::EncodeBody(CxFile *fp, bool bLocalColorMap)
+{
+ curx = 0;
+ cury = head.biHeight - 1; //because we read the image bottom to top
+ CountDown = (int32_t)head.biWidth * (int32_t)head.biHeight;
+
+ fp->PutC(',');
+
+ Putword(info.xOffset,fp);
+ Putword(info.yOffset,fp);
+ Putword(head.biWidth,fp);
+ Putword(head.biHeight,fp);
+
+ uint8_t Flags=0x00; //non-interlaced (0x40 = interlaced) (0x80 = LocalColorMap)
+ if (bLocalColorMap) { Flags|=0x80; Flags|=head.biBitCount-1; }
+ fp->PutC(Flags);
+
+ if (bLocalColorMap){
+ Flags|=0x87;
+ RGBQUAD* pPal = GetPalette();
+ for(uint32_t i=0; i<head.biClrUsed; ++i)
+ {
+ fp->PutC(pPal[i].rgbRed);
+ fp->PutC(pPal[i].rgbGreen);
+ fp->PutC(pPal[i].rgbBlue);
+ }
+ }
+
+ int32_t InitCodeSize = head.biBitCount <=1 ? 2 : head.biBitCount;
+ // Write out the initial code size
+ fp->PutC((uint8_t)InitCodeSize);
+
+ // Go and actually compress the data
+ switch (GetCodecOption(CXIMAGE_FORMAT_GIF))
+ {
+ case 1: //uncompressed
+ compressNONE(InitCodeSize+1, fp);
+ break;
+ case 2: //RLE
+ compressRLE(InitCodeSize+1, fp);
+ break;
+ default: //LZW
+ compressLZW(InitCodeSize+1, fp);
+ }
+
+ // Write out a Zero-length packet (to end the series)
+ fp->PutC(0);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::EncodeComment(CxFile *fp)
+{
+ uint32_t n = (uint32_t) strlen(m_comment);
+ if (n>255) n=255;
+ if (n) {
+ fp->PutC('!'); //extension code:
+ fp->PutC(254); //comment extension
+ fp->PutC((uint8_t)n); //size of comment
+ fp->Write(m_comment,n,1);
+ fp->PutC(0); //block terminator
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageGIF::EncodeRGB(CxFile *fp)
+{
+ EncodeHeader(fp);
+
+// EncodeLoopExtension(fp);
+
+ EncodeComment(fp);
+
+ uint32_t w,h;
+ w=h=0;
+ const int32_t cellw = 17;
+ const int32_t cellh = 15;
+ CxImageGIF tmp;
+ for (int32_t y=0;y<head.biHeight;y+=cellh){
+ for (int32_t x=0;x<head.biWidth;x+=cellw){
+ if ((head.biWidth -x)<cellw) w=head.biWidth -x; else w=cellw;
+ if ((head.biHeight-y)<cellh) h=head.biHeight-y; else h=cellh;
+
+ if (w!=tmp.GetWidth() || h!=tmp.GetHeight()) tmp.Create(w,h,8);
+
+ if (IsTransparent()){
+ tmp.SetTransIndex(0);
+ tmp.SetPaletteColor(0,GetTransColor());
+ }
+
+ uint8_t i;
+ for (uint32_t j=0;j<h;j++){
+ for (uint32_t k=0;k<w;k++){
+ i=(uint8_t)(1+k+cellw*j);
+ tmp.SetPaletteColor(i,GetPixelColor(x+k,head.biHeight-y-h+j));
+ tmp.SetPixelIndex(k,j,tmp.GetNearestIndex(tmp.GetPaletteColor(i)));
+ }
+ }
+
+ tmp.SetOffset(x,y);
+ tmp.EncodeExtension(fp);
+ tmp.EncodeBody(fp,true);
+ }
+ }
+
+ fp->PutC(';'); // Write the GIF file terminator
+
+ return true; // done!
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+// Return the next pixel from the image
+// <DP> fix for 1 & 4 bpp images
+int32_t CxImageGIF::GifNextPixel( )
+{
+ if( CountDown == 0 ) return EOF;
+ --CountDown;
+ int32_t r = GetPixelIndex(curx,cury);
+ // Bump the current X position
+ ++curx;
+ if( curx == head.biWidth ){
+ curx = 0;
+ cury--; //bottom to top
+ }
+ return r;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::Putword(int32_t w, CxFile *fp )
+{
+ fp->PutC((uint8_t)(w & 0xff));
+ fp->PutC((uint8_t)((w >> 8) & 0xff));
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::compressNONE( int32_t init_bits, CxFile* outfile)
+{
+ register int32_t c;
+ register int32_t ent;
+
+ // g_init_bits - initial number of bits
+ // g_outfile - pointer to output file
+ g_init_bits = init_bits;
+ g_outfile = outfile;
+
+ // Set up the necessary values
+ cur_accum = cur_bits = clear_flg = 0;
+ maxcode = (int16_t)MAXCODE(n_bits = g_init_bits);
+ code_int maxmaxcode = (code_int)1 << MAXBITSCODES;
+
+ ClearCode = (1 << (init_bits - 1));
+ EOFCode = ClearCode + 1;
+ free_ent = (int16_t)(ClearCode + 2);
+
+ a_count=0;
+ ent = GifNextPixel( );
+
+ output( (code_int)ClearCode );
+
+ while ( ent != EOF ) {
+ c = GifNextPixel();
+
+ output ( (code_int) ent );
+ ent = c;
+ if ( free_ent < maxmaxcode ) {
+ free_ent++;
+ } else {
+ free_ent=(int16_t)(ClearCode+2);
+ clear_flg=1;
+ output((code_int)ClearCode);
+ }
+ }
+ // Put out the final code.
+ output( (code_int) EOFCode );
+}
+////////////////////////////////////////////////////////////////////////////////
+
+/***************************************************************************
+ *
+ * GIFCOMPR.C - LZW GIF Image compression routines
+ *
+ ***************************************************************************/
+
+void CxImageGIF::compressLZW( int32_t init_bits, CxFile* outfile)
+{
+ register int32_t fcode;
+ register int32_t c;
+ register int32_t ent;
+ register int32_t hshift;
+ register int32_t disp;
+ register int32_t i;
+
+ // g_init_bits - initial number of bits
+ // g_outfile - pointer to output file
+ g_init_bits = init_bits;
+ g_outfile = outfile;
+
+ // Set up the necessary values
+ cur_accum = cur_bits = clear_flg = 0;
+ maxcode = (int16_t)MAXCODE(n_bits = g_init_bits);
+ code_int maxmaxcode = (code_int)1 << MAXBITSCODES;
+
+ ClearCode = (1 << (init_bits - 1));
+ EOFCode = ClearCode + 1;
+ free_ent = (int16_t)(ClearCode + 2);
+
+ a_count=0;
+ ent = GifNextPixel( );
+
+ hshift = 0;
+ for ( fcode = (int32_t) HSIZE; fcode < 65536L; fcode *= 2L ) ++hshift;
+ hshift = 8 - hshift; /* set hash code range bound */
+ cl_hash((int32_t)HSIZE); /* clear hash table */
+ output( (code_int)ClearCode );
+
+ while ( (c = GifNextPixel( )) != EOF ) {
+
+ fcode = (int32_t) (((int32_t) c << MAXBITSCODES) + ent);
+ i = (((code_int)c << hshift) ^ ent); /* xor hashing */
+
+ if ( HashTabOf (i) == fcode ) {
+ ent = CodeTabOf (i);
+ continue;
+ } else if ( (int32_t)HashTabOf (i) < 0 ) /* empty slot */
+ goto nomatch;
+ disp = HSIZE - i; /* secondary hash (after G. Knott) */
+ if ( i == 0 ) disp = 1;
+probe:
+ if ( (i -= disp) < 0 ) i += HSIZE;
+ if ( HashTabOf (i) == fcode ) { ent = CodeTabOf (i); continue; }
+ if ( (int32_t)HashTabOf (i) > 0 ) goto probe;
+nomatch:
+ output ( (code_int) ent );
+ ent = c;
+ if ( free_ent < maxmaxcode ) {
+ CodeTabOf (i) = free_ent++; /* code -> hashtable */
+ HashTabOf (i) = fcode;
+ } else {
+ cl_hash((int32_t)HSIZE);
+ free_ent=(int16_t)(ClearCode+2);
+ clear_flg=1;
+ output((code_int)ClearCode);
+ }
+ }
+ // Put out the final code.
+ output( (code_int)ent );
+ output( (code_int) EOFCode );
+}
+////////////////////////////////////////////////////////////////////////////////
+
+static const uint32_t code_mask[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::output( code_int code)
+{
+ cur_accum &= code_mask[ cur_bits ];
+
+ if( cur_bits > 0 )
+ cur_accum |= ((int32_t)code << cur_bits);
+ else
+ cur_accum = code;
+
+ cur_bits += n_bits;
+
+ while( cur_bits >= 8 ) {
+ char_out( (uint32_t)(cur_accum & 0xff) );
+ cur_accum >>= 8;
+ cur_bits -= 8;
+ }
+
+ /*
+ * If the next entry is going to be too big for the code size,
+ * then increase it, if possible.
+ */
+
+ if ( free_ent > maxcode || clear_flg ) {
+ if( clear_flg ) {
+ maxcode = (int16_t)MAXCODE(n_bits = g_init_bits);
+ clear_flg = 0;
+ } else {
+ ++n_bits;
+ if ( n_bits == MAXBITSCODES )
+ maxcode = (code_int)1 << MAXBITSCODES; /* should NEVER generate this code */
+ else
+ maxcode = (int16_t)MAXCODE(n_bits);
+ }
+ }
+
+ if( code == EOFCode ) {
+ // At EOF, write the rest of the buffer.
+ while( cur_bits > 0 ) {
+ char_out( (uint32_t)(cur_accum & 0xff) );
+ cur_accum >>= 8;
+ cur_bits -= 8;
+ }
+
+ flush_char();
+ g_outfile->Flush();
+
+ if(g_outfile->Error()) strcpy(info.szLastError,"Write Error in GIF file");
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+
+void CxImageGIF::cl_hash(int32_t hsize)
+
+{
+ register int32_t *htab_p = htab+hsize;
+
+ register int32_t i;
+ register int32_t m1 = -1L;
+
+ i = hsize - 16;
+
+ do {
+ *(htab_p-16)=m1;
+ *(htab_p-15)=m1;
+ *(htab_p-14)=m1;
+ *(htab_p-13)=m1;
+ *(htab_p-12)=m1;
+ *(htab_p-11)=m1;
+ *(htab_p-10)=m1;
+ *(htab_p-9)=m1;
+ *(htab_p-8)=m1;
+ *(htab_p-7)=m1;
+ *(htab_p-6)=m1;
+ *(htab_p-5)=m1;
+ *(htab_p-4)=m1;
+ *(htab_p-3)=m1;
+ *(htab_p-2)=m1;
+ *(htab_p-1)=m1;
+
+ htab_p-=16;
+ } while ((i-=16) >=0);
+
+ for (i+=16;i>0;--i)
+ *--htab_p=m1;
+}
+
+/*******************************************************************************
+* GIF specific
+*******************************************************************************/
+
+void CxImageGIF::char_out(int32_t c)
+{
+ accum[a_count++]=(char)c;
+ if (a_count >=254)
+ flush_char();
+}
+
+void CxImageGIF::flush_char()
+{
+ if (a_count > 0) {
+ g_outfile->PutC((uint8_t)a_count);
+ g_outfile->Write(accum,1,a_count);
+ a_count=0;
+ }
+}
+
+/*******************************************************************************
+* GIF decoder
+*******************************************************************************/
+/* DECODE.C - An LZW decoder for GIF
+ * Copyright (C) 1987, by Steven A. Bennett
+ * Copyright (C) 1994, C++ version by Alejandro Aguilar Sierra
+*
+ * Permission is given by the author to freely redistribute and include
+ * this code in any program as int32_t as this credit is given where due.
+ *
+ * In accordance with the above, I want to credit Steve Wilhite who wrote
+ * the code which this is heavily inspired by...
+ *
+ * GIF and 'Graphics Interchange Format' are trademarks (tm) of
+ * Compuserve, Incorporated, an H&R Block Company.
+ *
+ * Release Notes: This file contains a decoder routine for GIF images
+ * which is similar, structurally, to the original routine by Steve Wilhite.
+ * It is, however, somewhat noticably faster in most cases.
+ *
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+
+int16_t CxImageGIF::init_exp(int16_t size)
+{
+ curr_size = (int16_t)(size + 1);
+ top_slot = (int16_t)(1 << curr_size);
+ clear = (int16_t)(1 << size);
+ ending = (int16_t)(clear + 1);
+ slot = newcodes = (int16_t)(ending + 1);
+ navail_bytes = nbits_left = 0;
+
+ memset(stack,0,MAX_CODES + 1);
+ memset(prefix,0,MAX_CODES + 1);
+ memset(suffix,0,MAX_CODES + 1);
+ return(0);
+}
+////////////////////////////////////////////////////////////////////////////////
+
+/* get_next_code()
+ * - gets the next code from the GIF file. Returns the code, or else
+ * a negative number in case of file errors...
+ */
+int16_t CxImageGIF::get_next_code(CxFile* file)
+{
+ int16_t i, x;
+ uint32_t ret;
+
+ if (nbits_left == 0) {
+ if (navail_bytes <= 0) {
+ /* Out of bytes in current block, so read next block */
+ pbytes = byte_buff;
+ if ((navail_bytes = (int16_t)get_byte(file)) < 0)
+ return(navail_bytes);
+ else if (navail_bytes) {
+ for (i = 0; i < navail_bytes; ++i) {
+ if ((x = (int16_t)get_byte(file)) < 0) return(x);
+ byte_buff[i] = (uint8_t)x;
+ }
+ }
+ }
+ b1 = *pbytes++;
+ nbits_left = 8;
+ --navail_bytes;
+ }
+
+ if (navail_bytes<0) return ending; // prevent deadlocks (thanks to Mike Melnikov)
+
+ ret = b1 >> (8 - nbits_left);
+ while (curr_size > nbits_left){
+ if (navail_bytes <= 0){
+ /* Out of bytes in current block, so read next block*/
+ pbytes = byte_buff;
+ if ((navail_bytes = (int16_t)get_byte(file)) < 0)
+ return(navail_bytes);
+ else if (navail_bytes){
+ for (i = 0; i < navail_bytes; ++i){
+ if ((x = (int16_t)get_byte(file)) < 0) return(x);
+ byte_buff[i] = (uint8_t)x;
+ }
+ }
+ }
+ b1 = *pbytes++;
+ ret |= b1 << nbits_left;
+ nbits_left += 8;
+ --navail_bytes;
+ }
+ nbits_left = (int16_t)(nbits_left-curr_size);
+ ret &= code_mask[curr_size];
+ return((int16_t)(ret));
+}
+////////////////////////////////////////////////////////////////////////////////
+
+/* int16_t decoder(linewidth)
+ * int16_t linewidth; * Pixels per line of image *
+ *
+ * - This function decodes an LZW image, according to the method used
+ * in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
+ * will generate a call to out_line(), which is a user specific function
+ * to display a line of pixels. The function gets it's codes from
+ * get_next_code() which is responsible for reading blocks of data and
+ * seperating them into the proper size codes. Finally, get_byte() is
+ * the global routine to read the next uint8_t from the GIF file.
+ *
+ * It is generally a good idea to have linewidth correspond to the actual
+ * width of a line (as specified in the Image header) to make your own
+ * code a bit simpler, but it isn't absolutely necessary.
+ *
+ * Returns: 0 if successful, else negative. (See ERRS.H)
+ *
+ */
+/* bad_code_count is incremented each time an out of range code is read.
+ * When this value is non-zero after a decode, your GIF file is probably
+ * corrupt in some way...
+ */
+int16_t CxImageGIF::decoder(CxFile* file, CImageIterator* iter, int16_t linewidth, int32_t &bad_code_count)
+{
+ register uint8_t *sp, *bufptr;
+ uint8_t *buf;
+ register int16_t code, fc, oc, bufcnt;
+ int16_t c, size, ret;
+
+ if (linewidth<=0)
+ return BAD_LINE_WIDTH;
+
+ /* Initialize for decoding a new image... */
+ bad_code_count = 0;
+ if ((size = (int16_t)get_byte(file)) < 0) return(size);
+ if (size < 2 || 9 < size) return(BAD_CODE_SIZE);
+ // out_line = outline;
+ init_exp(size);
+ //printf("L %d %x\n",linewidth,size);
+
+ /* Initialize in case they forgot to put in a clear code.
+ * (This shouldn't happen, but we'll try and decode it anyway...)
+ */
+ oc = fc = 0;
+
+ /* Allocate space for the decode buffer */
+ if ((buf = new uint8_t[linewidth + 1]) == NULL) return(OUT_OF_MEMORY);
+
+ /* Set up the stack pointer and decode buffer pointer */
+ sp = stack;
+ bufptr = buf;
+ bufcnt = linewidth;
+
+ /* This is the main loop. For each code we get we pass through the
+ * linked list of prefix codes, pushing the corresponding "character" for
+ * each code onto the stack. When the list reaches a single "character"
+ * we push that on the stack too, and then start unstacking each
+ * character for output in the correct order. Special handling is
+ * included for the clear code, and the whole thing ends when we get
+ * an ending code.
+ */
+ while ((c = get_next_code(file)) != ending) {
+ /* If we had a file error, return without completing the decode*/
+ if (c < 0){
+ delete [] buf;
+ return(0);
+ }
+ /* If the code is a clear code, reinitialize all necessary items.*/
+ if (c == clear){
+ curr_size = (int16_t)(size + 1);
+ slot = newcodes;
+ top_slot = (int16_t)(1 << curr_size);
+
+ /* Continue reading codes until we get a non-clear code
+ * (Another unlikely, but possible case...)
+ */
+ while ((c = get_next_code(file)) == clear);
+
+ /* If we get an ending code immediately after a clear code
+ * (Yet another unlikely case), then break out of the loop.
+ */
+ if (c == ending) break;
+
+ /* Finally, if the code is beyond the range of already set codes,
+ * (This one had better NOT happen... I have no idea what will
+ * result from this, but I doubt it will look good...) then set it
+ * to color zero.
+ */
+ if (c >= slot) c = 0;
+ oc = fc = c;
+
+ /* And let us not forget to put the char into the buffer... And
+ * if, on the off chance, we were exactly one pixel from the end
+ * of the line, we have to send the buffer to the out_line()
+ * routine...
+ */
+ *bufptr++ = (uint8_t)c;
+ if (--bufcnt == 0) {
+ if (iter) {
+ if ((ret = (int16_t)out_line(iter, buf, linewidth)) < 0) {
+ delete [] buf;
+ return(ret);
+ }
+ }
+ bufptr = buf;
+ bufcnt = linewidth;
+ }
+ } else {
+ /* In this case, it's not a clear code or an ending code, so
+ * it must be a code code... So we can now decode the code into
+ * a stack of character codes. (Clear as mud, right?)
+ */
+ code = c;
+
+ /* Here we go again with one of those off chances... If, on the
+ * off chance, the code we got is beyond the range of those already
+ * set up (Another thing which had better NOT happen...) we trick
+ * the decoder into thinking it actually got the last code read.
+ * (Hmmn... I'm not sure why this works... But it does...)
+ */
+ if (code >= slot && sp<(stack+MAX_CODES-1)) {
+ if (code > slot)
+ ++bad_code_count;
+ code = oc;
+ *sp++ = (uint8_t)fc;
+ }
+
+ /* Here we scan back along the linked list of prefixes, pushing
+ * helpless characters (ie. suffixes) onto the stack as we do so.
+ */
+ while (code >= newcodes && sp<(stack+MAX_CODES-1)) {
+ *sp++ = suffix[code];
+ code = prefix[code];
+ }
+
+ /* Push the last character on the stack, and set up the new
+ * prefix and suffix, and if the required slot number is greater
+ * than that allowed by the current bit size, increase the bit
+ * size. (NOTE - If we are all full, we *don't* save the new
+ * suffix and prefix... I'm not certain if this is correct...
+ * it might be more proper to overwrite the last code...
+ */
+ *sp++ = (uint8_t)code;
+ if (slot < top_slot){
+ suffix[slot] = (uint8_t)(fc = (uint8_t)code);
+ prefix[slot++] = oc;
+ oc = c;
+ }
+ if (slot >= top_slot){
+ if (curr_size < 12) {
+ top_slot <<= 1;
+ ++curr_size;
+ }
+ }
+
+ /* Now that we've pushed the decoded string (in reverse order)
+ * onto the stack, lets pop it off and put it into our decode
+ * buffer... And when the decode buffer is full, write another
+ * line...
+ */
+ while (sp > stack) {
+ *bufptr++ = *(--sp);
+ if (--bufcnt == 0) {
+ if (iter) {
+ if ((ret = (int16_t)out_line(iter, buf, linewidth)) < 0) {
+ delete [] buf;
+ return(ret);
+ }
+ }
+ bufptr = buf;
+ bufcnt = linewidth;
+ }
+ }
+ }
+ }
+ ret = 0;
+ if (bufcnt != linewidth && iter)
+ ret = (int16_t)out_line(iter, buf, (linewidth - bufcnt));
+ delete [] buf;
+ return(ret);
+}
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImageGIF::get_num_frames(CxFile *fp,struct_TabCol* TabColSrc,struct_dscgif* dscgif)
+{
+ struct_image image;
+
+ int32_t pos=fp->Tell();
+ int32_t nframes=0;
+
+ struct_TabCol TempTabCol;
+ memcpy(&TempTabCol,TabColSrc,sizeof(struct_TabCol));
+
+ char ch;
+ bool bPreviousWasNull = true;
+
+ for (BOOL bContinue = TRUE; bContinue; )
+ {
+ if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;}
+
+ if (bPreviousWasNull || ch==0)
+ {
+ switch (ch)
+ {
+ case '!': // extension
+ {
+ DecodeExtension(fp);
+ break;
+ }
+ case ',': // image
+ {
+
+ assert(sizeof(image) == 9);
+ //log << "Image header" << endl;
+ fp->Read(&image,sizeof(image),1);
+
+ //avoid byte order problems with Solaris <candan> <AMSN>
+ image.l = m_ntohs(image.l);
+ image.t = m_ntohs(image.t);
+ image.w = m_ntohs(image.w);
+ image.h = m_ntohs(image.h);
+
+ // in case of images with empty screen descriptor, give a last chance
+ if (dscgif->scrwidth==0 && dscgif->scrheight==0){
+ dscgif->scrwidth = image.w;
+ dscgif->scrheight = image.h;
+ }
+
+ if (((image.l + image.w) > dscgif->scrwidth)||((image.t + image.h) > dscgif->scrheight))
+ break;
+
+ nframes++;
+
+ // Local colour map?
+ if (image.pf & 0x80) {
+ TempTabCol.sogct = (int16_t)(1 << ((image.pf & 0x07) +1));
+ assert(3 == sizeof(struct rgb_color));
+ fp->Read(TempTabCol.paleta,sizeof(struct rgb_color)*TempTabCol.sogct,1);
+ //log << "Local colour map" << endl;
+ }
+
+ int32_t badcode=0;
+ ibf = GIFBUFTAM+1;
+
+ interlaced = image.pf & 0x40;
+ iheight = image.h;
+ istep = 8;
+ iypos = 0;
+ ipass = 0;
+
+ int32_t pos_start = fp->Tell();
+
+ //if (interlaced) log << "Interlaced" << endl;
+ decoder(fp, 0, image.w, badcode);
+
+ if (badcode){
+ seek_next_image(fp,pos_start);
+ } else {
+ fp->Seek(-(ibfmax - ibf - 1), SEEK_CUR);
+ }
+
+ break;
+ }
+ case ';': //terminator
+ bContinue=false;
+ break;
+ default:
+ bPreviousWasNull = (ch==0);
+ break;
+ }
+ }
+ }
+
+ fp->Seek(pos,SEEK_SET);
+ return nframes;
+}
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImageGIF::seek_next_image(CxFile* fp, int32_t position)
+{
+ fp->Seek(position, SEEK_SET);
+ char ch1,ch2;
+ ch1=ch2=0;
+ while(fp->Read(&ch2,sizeof(char),1)>0){
+ if (ch1 == 0 && ch2 == ','){
+ fp->Seek(-1,SEEK_CUR);
+ return fp->Tell();
+ } else {
+ ch1 = ch2;
+ }
+ }
+ return -1;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::SetLoops(int32_t loops)
+{ m_loops=loops; }
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImageGIF::GetLoops()
+{ return m_loops; }
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::SetComment(const char* sz_comment_in)
+{ if (sz_comment_in) strncpy(m_comment,sz_comment_in,255); }
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::GetComment(char* sz_comment_out)
+{ if (sz_comment_out) strncpy(sz_comment_out,m_comment,255); }
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::GifMix(CxImage & imgsrc2, struct_image & imgdesc)
+{
+ int32_t ymin = max(0,(int32_t)(GetHeight()-imgdesc.t - imgdesc.h));
+ int32_t ymax = GetHeight()-imgdesc.t;
+ int32_t xmin = imgdesc.l;
+ int32_t xmax = min(GetWidth(), (uint32_t)(imgdesc.l + imgdesc.w));
+
+ int32_t ibg2= imgsrc2.GetTransIndex();
+ uint8_t i2;
+
+ for(int32_t y = ymin; y < ymax; y++){
+ for(int32_t x = xmin; x < xmax; x++){
+ i2 = imgsrc2.GetPixelIndex(x-xmin,y-ymin);
+ if(i2!=ibg2) SetPixelIndex(x,y,i2);
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/*-----------------------------------------------------------------------
+ *
+ * miGIF Compression - mouse and ivo's GIF-compatible compression
+ *
+ * -run length encoding compression routines-
+ *
+ * Copyright (C) 1998 Hutchison Avenue Software Corporation
+ * http://www.hasc.com
+ * info@hasc.com
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. This software is provided "AS IS." The Hutchison Avenue
+ * Software Corporation disclaims all warranties, either express or implied,
+ * including but not limited to implied warranties of merchantability and
+ * fitness for a particular purpose, with respect to this code and accompanying
+ * documentation.
+ *
+ * The miGIF compression routines do not, strictly speaking, generate files
+ * conforming to the GIF spec, since the image data is not LZW-compressed
+ * (this is the point: in order to avoid transgression of the Unisys patent
+ * on the LZW algorithm.) However, miGIF generates data streams that any
+ * reasonably sane LZW decompresser will decompress to what we want.
+ *
+ * miGIF compression uses run length encoding. It compresses horizontal runs
+ * of pixels of the same color. This type of compression gives good results
+ * on images with many runs, for example images with lines, text and solid
+ * shapes on a solid-colored background. It gives little or no compression
+ * on images with few runs, for example digital or scanned photos.
+ *
+ * der Mouse
+ * mouse@rodents.montreal.qc.ca
+ * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
+ *
+ * ivo@hasc.com
+ *
+ * The Graphics Interchange Format(c) is the Copyright property of
+ * CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ * CompuServe Incorporated.
+ *
+ */
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_clear(struct_RLE* rle)
+{
+ rle->out_bits = rle->out_bits_init;
+ rle->out_bump = rle->out_bump_init;
+ rle->out_clear = rle->out_clear_init;
+ rle->out_count = 0;
+ rle->rl_table_max = 0;
+ rle->just_cleared = 1;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_flush(struct_RLE* rle)
+{
+ if (rle->rl_count == 1){
+ rle_output_plain(rle->rl_pixel,rle);
+ rle->rl_count = 0;
+ return;
+ }
+ if (rle->just_cleared){
+ rle_flush_fromclear(rle->rl_count,rle);
+ } else if ((rle->rl_table_max < 2) || (rle->rl_table_pixel != rle->rl_pixel)) {
+ rle_flush_clearorrep(rle->rl_count,rle);
+ } else {
+ rle_flush_withtable(rle->rl_count,rle);
+ }
+ rle->rl_count = 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_output_plain(int32_t c,struct_RLE* rle)
+{
+ rle->just_cleared = 0;
+ rle_output(c,rle);
+ rle->out_count++;
+ if (rle->out_count >= rle->out_bump){
+ rle->out_bits ++;
+ rle->out_bump += 1 << (rle->out_bits - 1);
+ }
+ if (rle->out_count >= rle->out_clear){
+ rle_output(rle->code_clear,rle);
+ rle_clear(rle);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_flush_fromclear(int32_t count,struct_RLE* rle)
+{
+ int32_t n;
+
+ rle->out_clear = rle->max_ocodes;
+ rle->rl_table_pixel = rle->rl_pixel;
+ n = 1;
+ while (count > 0){
+ if (n == 1){
+ rle->rl_table_max = 1;
+ rle_output_plain(rle->rl_pixel,rle);
+ count --;
+ } else if (count >= n){
+ rle->rl_table_max = n;
+ rle_output_plain(rle->rl_basecode+n-2,rle);
+ count -= n;
+ } else if (count == 1){
+ rle->rl_table_max ++;
+ rle_output_plain(rle->rl_pixel,rle);
+ count = 0;
+ } else {
+ rle->rl_table_max ++;
+ rle_output_plain(rle->rl_basecode+count-2,rle);
+ count = 0;
+ }
+ if (rle->out_count == 0) n = 1; else n ++;
+ }
+ rle_reset_out_clear(rle);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_reset_out_clear(struct_RLE* rle)
+{
+ rle->out_clear = rle->out_clear_init;
+ if (rle->out_count >= rle->out_clear){
+ rle_output(rle->code_clear,rle);
+ rle_clear(rle);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_flush_withtable(int32_t count, struct_RLE* rle)
+{
+ int32_t repmax;
+ int32_t repleft;
+ int32_t leftover;
+
+ repmax = count / rle->rl_table_max;
+ leftover = count % rle->rl_table_max;
+ repleft = (leftover ? 1 : 0);
+ if (rle->out_count+repmax+repleft > rle->max_ocodes){
+ repmax = rle->max_ocodes - rle->out_count;
+ leftover = count - (repmax * rle->rl_table_max);
+ repleft = 1 + rle_compute_triangle_count(leftover,rle->max_ocodes);
+ }
+ if (1+rle_compute_triangle_count(count,rle->max_ocodes) < (uint32_t)(repmax+repleft)){
+ rle_output(rle->code_clear,rle);
+ rle_clear(rle);
+ rle_flush_fromclear(count,rle);
+ return;
+ }
+ rle->out_clear = rle->max_ocodes;
+ for (;repmax>0;repmax--) rle_output_plain(rle->rl_basecode+rle->rl_table_max-2,rle);
+ if (leftover){
+ if (rle->just_cleared){
+ rle_flush_fromclear(leftover,rle);
+ } else if (leftover == 1){
+ rle_output_plain(rle->rl_pixel,rle);
+ } else {
+ rle_output_plain(rle->rl_basecode+leftover-2,rle);
+ }
+ }
+ rle_reset_out_clear(rle);
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImageGIF::rle_compute_triangle_count(uint32_t count, uint32_t nrepcodes)
+{
+ uint32_t perrep;
+ uint32_t cost;
+
+ cost = 0;
+ perrep = (nrepcodes * (nrepcodes+1)) / 2;
+ while (count >= perrep){
+ cost += nrepcodes;
+ count -= perrep;
+ }
+ if (count > 0){
+ uint32_t n;
+ n = rle_isqrt(count);
+ while ((n*(n+1)) >= 2*count) n --;
+ while ((n*(n+1)) < 2*count) n ++;
+ cost += n;
+ }
+ return(cost);
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImageGIF::rle_isqrt(uint32_t x)
+{
+ uint32_t r;
+ uint32_t v;
+
+ if (x < 2) return(x);
+ for (v=x,r=1;v;v>>=2,r<<=1) ;
+ for( ;; )
+ {
+ v = ((x / r) + r) / 2;
+ if ((v == r) || (v == r+1)) return(r);
+ r = v;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_flush_clearorrep(int32_t count, struct_RLE* rle)
+{
+ int32_t withclr;
+ withclr = 1 + rle_compute_triangle_count(count,rle->max_ocodes);
+ if (withclr < count) {
+ rle_output(rle->code_clear,rle);
+ rle_clear(rle);
+ rle_flush_fromclear(count,rle);
+ } else {
+ for (;count>0;count--) rle_output_plain(rle->rl_pixel,rle);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_write_block(struct_RLE* rle)
+{
+ g_outfile->PutC((uint8_t)rle->oblen);
+ g_outfile->Write(rle->oblock,1,rle->oblen);
+ rle->oblen = 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_block_out(uint8_t c, struct_RLE* rle)
+{
+ rle->oblock[rle->oblen++] = c;
+ if (rle->oblen >= 255) rle_write_block(rle);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_block_flush(struct_RLE* rle)
+{
+ if (rle->oblen > 0) rle_write_block(rle);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_output(int32_t val, struct_RLE* rle)
+{
+ rle->obuf |= val << rle->obits;
+ rle->obits += rle->out_bits;
+ while (rle->obits >= 8){
+ rle_block_out((uint8_t)(rle->obuf&0xff),rle);
+ rle->obuf >>= 8;
+ rle->obits -= 8;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_output_flush(struct_RLE* rle)
+{
+ if (rle->obits > 0) rle_block_out((uint8_t)(rle->obuf),rle);
+ rle_block_flush(rle);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::compressRLE( int32_t init_bits, CxFile* outfile)
+{
+ g_init_bits = init_bits;
+ g_outfile = outfile;
+
+ struct_RLE rle;
+ rle.code_clear = 1 << (init_bits - 1);
+ rle.code_eof = rle.code_clear + 1;
+ rle.rl_basecode = rle.code_eof + 1;
+ rle.out_bump_init = (1 << (init_bits - 1)) - 1;
+ rle.out_clear_init = (init_bits <= 3) ? 9 : (rle.out_bump_init-1);
+ rle.out_bits_init = init_bits;
+ rle.max_ocodes = (1 << MAXBITSCODES) - ((1 << (rle.out_bits_init - 1)) + 3);
+ rle.rl_count = 0;
+ rle_clear(&rle);
+ rle.obuf = 0;
+ rle.obits = 0;
+ rle.oblen = 0;
+
+ rle_output(rle.code_clear,&rle);
+
+ int32_t c;
+ for( ;; )
+ {
+ c = GifNextPixel();
+ if ((rle.rl_count > 0) && (c != rle.rl_pixel)) rle_flush(&rle);
+ if (c == EOF) break;
+ if (rle.rl_pixel == c){
+ rle.rl_count++;
+ } else {
+ rle.rl_pixel = c;
+ rle.rl_count = 1;
+ }
+ }
+ rle_output(rle.code_eof,&rle);
+ rle_output_flush(&rle);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_GIF
diff --git a/archive/hge/CxImage/ximagif.h b/archive/hge/CxImage/ximagif.h new file mode 100644 index 0000000..4eec35e --- /dev/null +++ b/archive/hge/CxImage/ximagif.h @@ -0,0 +1,244 @@ +/*
+ * File: ximagif.h
+ * Purpose: GIF Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageGIF (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes
+ *
+ * original CImageGIF and CImageIterator implementation are:
+ * Copyright: (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>
+ *
+ * 6/15/97 Randy Spann: Added GIF87a writing support
+ * R.Spann@ConnRiver.net
+ *
+ * DECODE.C - An LZW decoder for GIF
+ * Copyright (C) 1987, by Steven A. Bennett
+ * Copyright (C) 1994, C++ version by Alejandro Aguilar Sierra
+ *
+ * In accordance with the above, I want to credit Steve Wilhite who wrote
+ * the code which this is heavily inspired by...
+ *
+ * GIF and 'Graphics Interchange Format' are trademarks (tm) of
+ * Compuserve, Incorporated, an H&R Block Company.
+ *
+ * Release Notes: This file contains a decoder routine for GIF images
+ * which is similar, structurally, to the original routine by Steve Wilhite.
+ * It is, however, somewhat noticably faster in most cases.
+ *
+ * ==========================================================
+ */
+
+#if !defined(__ximaGIF_h)
+#define __ximaGIF_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_GIF
+
+typedef int16_t code_int;
+
+/* Various error codes used by decoder */
+#define OUT_OF_MEMORY -10
+#define BAD_CODE_SIZE -20
+#define READ_ERROR -1
+#define WRITE_ERROR -2
+#define OPEN_ERROR -3
+#define CREATE_ERROR -4
+#define BAD_LINE_WIDTH -5
+#define MAX_CODES 4095
+#define GIFBUFTAM 16383
+#define TRANSPARENCY_CODE 0xF9
+
+//LZW GIF Image compression
+#define MAXBITSCODES 12
+#define HSIZE 5003 /* 80% occupancy */
+#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
+#define HashTabOf(i) htab[i]
+#define CodeTabOf(i) codetab[i]
+
+
+class CImageIterator;
+class DLL_EXP CxImageGIF: public CxImage
+{
+#pragma pack(1)
+
+typedef struct tag_gifgce{
+ uint8_t flags; /*res:3|dispmeth:3|userinputflag:1|transpcolflag:1*/
+ uint16_t delaytime;
+ uint8_t transpcolindex;
+} struct_gifgce;
+
+typedef struct tag_dscgif{ /* Logic Screen Descriptor */
+ char header[6]; /* Firma and version */
+ uint16_t scrwidth;
+ uint16_t scrheight;
+ char pflds;
+ char bcindx;
+ char pxasrat;
+} struct_dscgif;
+
+typedef struct tag_image{ /* Image Descriptor */
+ uint16_t l;
+ uint16_t t;
+ uint16_t w;
+ uint16_t h;
+ uint8_t pf;
+} struct_image;
+
+typedef struct tag_TabCol{ /* Tabla de colores */
+ int16_t colres; /* color resolution */
+ int16_t sogct; /* size of global color table */
+ rgb_color paleta[256]; /* paleta */
+} struct_TabCol;
+
+typedef struct tag_RLE{
+ int32_t rl_pixel;
+ int32_t rl_basecode;
+ int32_t rl_count;
+ int32_t rl_table_pixel;
+ int32_t rl_table_max;
+ int32_t just_cleared;
+ int32_t out_bits;
+ int32_t out_bits_init;
+ int32_t out_count;
+ int32_t out_bump;
+ int32_t out_bump_init;
+ int32_t out_clear;
+ int32_t out_clear_init;
+ int32_t max_ocodes;
+ int32_t code_clear;
+ int32_t code_eof;
+ uint32_t obuf;
+ int32_t obits;
+ uint8_t oblock[256];
+ int32_t oblen;
+} struct_RLE;
+#pragma pack()
+
+public:
+ CxImageGIF();
+ ~CxImageGIF();
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_GIF);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_GIF);}
+
+ bool Decode(CxFile * fp);
+ bool Decode(FILE *fp) { CxIOFile file(fp); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * fp);
+ bool Encode(CxFile * fp, CxImage ** pImages, int32_t pagecount, bool bLocalColorMap = false, bool bLocalDispMeth = false);
+ bool Encode(FILE *fp) { CxIOFile file(fp); return Encode(&file); }
+ bool Encode(FILE *fp, CxImage ** pImages, int32_t pagecount, bool bLocalColorMap = false)
+ { CxIOFile file(fp); return Encode(&file, pImages, pagecount, bLocalColorMap); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+ void SetLoops(int32_t loops);
+ int32_t GetLoops();
+ void SetComment(const char* sz_comment_in);
+ void GetComment(char* sz_comment_out);
+
+protected:
+ bool DecodeExtension(CxFile *fp);
+ void EncodeHeader(CxFile *fp);
+ void EncodeLoopExtension(CxFile *fp);
+ void EncodeExtension(CxFile *fp);
+ void EncodeBody(CxFile *fp, bool bLocalColorMap = false);
+ void EncodeComment(CxFile *fp);
+ bool EncodeRGB(CxFile *fp);
+ void GifMix(CxImage & imgsrc2, struct_image & imgdesc);
+
+ struct_gifgce gifgce;
+
+ int32_t curx, cury;
+ int32_t CountDown;
+ uint32_t cur_accum;
+ int32_t cur_bits;
+ int32_t interlaced, iypos, istep, iheight, ipass;
+ int32_t ibf;
+ int32_t ibfmax;
+ uint8_t * buf;
+// Implementation
+ int32_t GifNextPixel ();
+ void Putword (int32_t w, CxFile* fp );
+ void compressNONE (int32_t init_bits, CxFile* outfile);
+ void compressLZW (int32_t init_bits, CxFile* outfile);
+ void output (code_int code );
+ void cl_hash (int32_t hsize);
+ void char_out (int32_t c);
+ void flush_char ();
+ int16_t init_exp(int16_t size);
+ int16_t get_next_code(CxFile*);
+ int16_t decoder(CxFile*, CImageIterator* iter, int16_t linewidth, int32_t &bad_code_count);
+ int32_t get_byte(CxFile*);
+ int32_t out_line(CImageIterator* iter, uint8_t *pixels, int32_t linelen);
+ int32_t get_num_frames(CxFile *f,struct_TabCol* TabColSrc,struct_dscgif* dscgif);
+ int32_t seek_next_image(CxFile* fp, int32_t position);
+
+ int16_t curr_size; /* The current code size */
+ int16_t clear; /* Value for a clear code */
+ int16_t ending; /* Value for a ending code */
+ int16_t newcodes; /* First available code */
+ int16_t top_slot; /* Highest code for current size */
+ int16_t slot; /* Last read code */
+
+ /* The following static variables are used
+ * for seperating out codes */
+ int16_t navail_bytes; /* # bytes left in block */
+ int16_t nbits_left; /* # bits left in current uint8_t */
+ uint8_t b1; /* Current uint8_t */
+ uint8_t * byte_buff; /* Current block */
+ uint8_t *pbytes; /* Pointer to next uint8_t in block */
+ /* The reason we have these seperated like this instead of using
+ * a structure like the original Wilhite code did, is because this
+ * stuff generally produces significantly faster code when compiled...
+ * This code is full of similar speedups... (For a good book on writing
+ * C for speed or for space optomisation, see Efficient C by Tom Plum,
+ * published by Plum-Hall Associates...)
+ */
+ uint8_t * stack; /* Stack for storing pixels */
+ uint8_t * suffix; /* Suffix table */
+ uint16_t * prefix; /* Prefix linked list */
+
+//LZW GIF Image compression routines
+ int32_t * htab;
+ uint16_t * codetab;
+ int32_t n_bits; /* number of bits/code */
+ code_int maxcode; /* maximum code, given n_bits */
+ code_int free_ent; /* first unused entry */
+ int32_t clear_flg;
+ int32_t g_init_bits;
+ CxFile* g_outfile;
+ int32_t ClearCode;
+ int32_t EOFCode;
+
+ int32_t a_count;
+ char * accum;
+
+ char * m_comment;
+ int32_t m_loops;
+
+//RLE compression routines
+ void compressRLE( int32_t init_bits, CxFile* outfile);
+ void rle_clear(struct_RLE* rle);
+ void rle_flush(struct_RLE* rle);
+ void rle_flush_withtable(int32_t count, struct_RLE* rle);
+ void rle_flush_clearorrep(int32_t count, struct_RLE* rle);
+ void rle_flush_fromclear(int32_t count,struct_RLE* rle);
+ void rle_output_plain(int32_t c,struct_RLE* rle);
+ void rle_reset_out_clear(struct_RLE* rle);
+ uint32_t rle_compute_triangle_count(uint32_t count, uint32_t nrepcodes);
+ uint32_t rle_isqrt(uint32_t x);
+ void rle_write_block(struct_RLE* rle);
+ void rle_block_out(uint8_t c, struct_RLE* rle);
+ void rle_block_flush(struct_RLE* rle);
+ void rle_output(int32_t val, struct_RLE* rle);
+ void rle_output_flush(struct_RLE* rle);
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximahist.cpp b/archive/hge/CxImage/ximahist.cpp new file mode 100644 index 0000000..830337f --- /dev/null +++ b/archive/hge/CxImage/ximahist.cpp @@ -0,0 +1,627 @@ +// xImaHist.cpp : histogram functions
+/* 28/01/2004 v1.00 - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_DSP
+
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImage::Histogram(int32_t* red, int32_t* green, int32_t* blue, int32_t* gray, int32_t colorspace)
+{
+ if (!pDib) return 0;
+ RGBQUAD color;
+
+ if (red) memset(red,0,256*sizeof(int32_t));
+ if (green) memset(green,0,256*sizeof(int32_t));
+ if (blue) memset(blue,0,256*sizeof(int32_t));
+ if (gray) memset(gray,0,256*sizeof(int32_t));
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ for(int32_t y=ymin; y<ymax; y++){
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ switch (colorspace){
+ case 1:
+ color = HSLtoRGB(BlindGetPixelColor(x,y));
+ break;
+ case 2:
+ color = YUVtoRGB(BlindGetPixelColor(x,y));
+ break;
+ case 3:
+ color = YIQtoRGB(BlindGetPixelColor(x,y));
+ break;
+ case 4:
+ color = XYZtoRGB(BlindGetPixelColor(x,y));
+ break;
+ default:
+ color = BlindGetPixelColor(x,y);
+ }
+
+ if (red) red[color.rgbRed]++;
+ if (green) green[color.rgbGreen]++;
+ if (blue) blue[color.rgbBlue]++;
+ if (gray) gray[(uint8_t)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)]++;
+ }
+ }
+ }
+
+ int32_t n=0;
+ for (int32_t i=0; i<256; i++){
+ if (red && red[i]>n) n=red[i];
+ if (green && green[i]>n) n=green[i];
+ if (blue && blue[i]>n) n=blue[i];
+ if (gray && gray[i]>n) n=gray[i];
+ }
+
+ return n;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * HistogramStretch
+ * \param method: 0 = luminance (default), 1 = linked channels , 2 = independent channels.
+ * \param threshold: minimum percentage level in the histogram to recognize it as meaningful. Range: 0.0 to 1.0; default = 0; typical = 0.005 (0.5%);
+ * \return true if everything is ok
+ * \author [dave] and [nipper]; changes [DP]
+ */
+bool CxImage::HistogramStretch(int32_t method, double threshold)
+{
+ if (!pDib) return false;
+
+ double dbScaler = 50.0/head.biHeight;
+ int32_t x,y;
+
+ if ((head.biBitCount==8) && IsGrayScale()){
+
+ double p[256];
+ memset(p, 0, 256*sizeof(double));
+ for (y=0; y<head.biHeight; y++)
+ {
+ info.nProgress = (int32_t)(y*dbScaler);
+ if (info.nEscape) break;
+ for (x=0; x<head.biWidth; x++) {
+ p[BlindGetPixelIndex(x, y)]++;
+ }
+ }
+
+ double maxh = 0;
+ for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y];
+ threshold *= maxh;
+ int32_t minc = 0;
+ while (minc<255 && p[minc]<=threshold) minc++;
+ int32_t maxc = 255;
+ while (maxc>0 && p[maxc]<=threshold) maxc--;
+
+ if (minc == 0 && maxc == 255) return true;
+ if (minc >= maxc) return true;
+
+ // calculate LUT
+ uint8_t lut[256];
+ for (x = 0; x <256; x++){
+ lut[x] = (uint8_t)max(0,min(255,(255 * (x - minc) / (maxc - minc))));
+ }
+
+ for (y=0; y<head.biHeight; y++) {
+ if (info.nEscape) break;
+ info.nProgress = (int32_t)(50.0+y*dbScaler);
+ for (x=0; x<head.biWidth; x++)
+ {
+ BlindSetPixelIndex(x, y, lut[BlindGetPixelIndex(x, y)]);
+ }
+ }
+ } else {
+ switch(method){
+ case 1:
+ { // <nipper>
+ double p[256];
+ memset(p, 0, 256*sizeof(double));
+ for (y=0; y<head.biHeight; y++)
+ {
+ info.nProgress = (int32_t)(y*dbScaler);
+ if (info.nEscape) break;
+ for (x=0; x<head.biWidth; x++) {
+ RGBQUAD color = BlindGetPixelColor(x, y);
+ p[color.rgbRed]++;
+ p[color.rgbBlue]++;
+ p[color.rgbGreen]++;
+ }
+ }
+ double maxh = 0;
+ for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y];
+ threshold *= maxh;
+ int32_t minc = 0;
+ while (minc<255 && p[minc]<=threshold) minc++;
+ int32_t maxc = 255;
+ while (maxc>0 && p[maxc]<=threshold) maxc--;
+
+ if (minc == 0 && maxc == 255) return true;
+ if (minc >= maxc) return true;
+
+ // calculate LUT
+ uint8_t lut[256];
+ for (x = 0; x <256; x++){
+ lut[x] = (uint8_t)max(0,min(255,(255 * (x - minc) / (maxc - minc))));
+ }
+
+ // normalize image
+ for (y=0; y<head.biHeight; y++) {
+ if (info.nEscape) break;
+ info.nProgress = (int32_t)(50.0+y*dbScaler);
+
+ for (x=0; x<head.biWidth; x++)
+ {
+ RGBQUAD color = BlindGetPixelColor(x, y);
+
+ color.rgbRed = lut[color.rgbRed];
+ color.rgbBlue = lut[color.rgbBlue];
+ color.rgbGreen = lut[color.rgbGreen];
+
+ BlindSetPixelColor(x, y, color);
+ }
+ }
+ }
+ break;
+ case 2:
+ { // <nipper>
+ double pR[256];
+ memset(pR, 0, 256*sizeof(double));
+ double pG[256];
+ memset(pG, 0, 256*sizeof(double));
+ double pB[256];
+ memset(pB, 0, 256*sizeof(double));
+ for (y=0; y<head.biHeight; y++)
+ {
+ info.nProgress = (int32_t)(y*dbScaler);
+ if (info.nEscape) break;
+ for (int32_t x=0; x<head.biWidth; x++) {
+ RGBQUAD color = BlindGetPixelColor(x, y);
+ pR[color.rgbRed]++;
+ pB[color.rgbBlue]++;
+ pG[color.rgbGreen]++;
+ }
+ }
+
+ double maxh = 0;
+ for (y=0; y<255; y++) if (maxh < pR[y]) maxh = pR[y];
+ double threshold2 = threshold*maxh;
+ int32_t minR = 0;
+ while (minR<255 && pR[minR]<=threshold2) minR++;
+ int32_t maxR = 255;
+ while (maxR>0 && pR[maxR]<=threshold2) maxR--;
+
+ maxh = 0;
+ for (y=0; y<255; y++) if (maxh < pG[y]) maxh = pG[y];
+ threshold2 = threshold*maxh;
+ int32_t minG = 0;
+ while (minG<255 && pG[minG]<=threshold2) minG++;
+ int32_t maxG = 255;
+ while (maxG>0 && pG[maxG]<=threshold2) maxG--;
+
+ maxh = 0;
+ for (y=0; y<255; y++) if (maxh < pB[y]) maxh = pB[y];
+ threshold2 = threshold*maxh;
+ int32_t minB = 0;
+ while (minB<255 && pB[minB]<=threshold2) minB++;
+ int32_t maxB = 255;
+ while (maxB>0 && pB[maxB]<=threshold2) maxB--;
+
+ if (minR == 0 && maxR == 255 && minG == 0 && maxG == 255 && minB == 0 && maxB == 255)
+ return true;
+
+ // calculate LUT
+ uint8_t lutR[256];
+ uint8_t range = maxR - minR;
+ if (range != 0) {
+ for (x = 0; x <256; x++){
+ lutR[x] = (uint8_t)max(0,min(255,(255 * (x - minR) / range)));
+ }
+ } else lutR[minR] = minR;
+
+ uint8_t lutG[256];
+ range = maxG - minG;
+ if (range != 0) {
+ for (x = 0; x <256; x++){
+ lutG[x] = (uint8_t)max(0,min(255,(255 * (x - minG) / range)));
+ }
+ } else lutG[minG] = minG;
+
+ uint8_t lutB[256];
+ range = maxB - minB;
+ if (range != 0) {
+ for (x = 0; x <256; x++){
+ lutB[x] = (uint8_t)max(0,min(255,(255 * (x - minB) / range)));
+ }
+ } else lutB[minB] = minB;
+
+ // normalize image
+ for (y=0; y<head.biHeight; y++)
+ {
+ info.nProgress = (int32_t)(50.0+y*dbScaler);
+ if (info.nEscape) break;
+
+ for (x=0; x<head.biWidth; x++)
+ {
+ RGBQUAD color = BlindGetPixelColor(x, y);
+
+ color.rgbRed = lutR[color.rgbRed];
+ color.rgbBlue = lutB[color.rgbBlue];
+ color.rgbGreen = lutG[color.rgbGreen];
+
+ BlindSetPixelColor(x, y, color);
+ }
+ }
+ }
+ break;
+ default:
+ { // <dave>
+ double p[256];
+ memset(p, 0, 256*sizeof(double));
+ for (y=0; y<head.biHeight; y++)
+ {
+ info.nProgress = (int32_t)(y*dbScaler);
+ if (info.nEscape) break;
+ for (x=0; x<head.biWidth; x++) {
+ RGBQUAD color = BlindGetPixelColor(x, y);
+ p[RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue)]++;
+ }
+ }
+
+ double maxh = 0;
+ for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y];
+ threshold *= maxh;
+ int32_t minc = 0;
+ while (minc<255 && p[minc]<=threshold) minc++;
+ int32_t maxc = 255;
+ while (maxc>0 && p[maxc]<=threshold) maxc--;
+
+ if (minc == 0 && maxc == 255) return true;
+ if (minc >= maxc) return true;
+
+ // calculate LUT
+ uint8_t lut[256];
+ for (x = 0; x <256; x++){
+ lut[x] = (uint8_t)max(0,min(255,(255 * (x - minc) / (maxc - minc))));
+ }
+
+ for(y=0; y<head.biHeight; y++){
+ info.nProgress = (int32_t)(50.0+y*dbScaler);
+ if (info.nEscape) break;
+ for(x=0; x<head.biWidth; x++){
+
+ RGBQUAD color = BlindGetPixelColor( x, y );
+ RGBQUAD yuvClr = RGBtoYUV(color);
+ yuvClr.rgbRed = lut[yuvClr.rgbRed];
+ color = YUVtoRGB(yuvClr);
+ BlindSetPixelColor( x, y, color );
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+// HistogramEqualize function by <dave> : dave(at)posortho(dot)com
+bool CxImage::HistogramEqualize()
+{
+ if (!pDib) return false;
+
+ int32_t histogram[256];
+ int32_t map[256];
+ int32_t equalize_map[256];
+ int32_t x, y, i, j;
+ RGBQUAD color;
+ RGBQUAD yuvClr;
+ uint32_t YVal, high, low;
+
+ memset( &histogram, 0, sizeof(int32_t) * 256 );
+ memset( &map, 0, sizeof(int32_t) * 256 );
+ memset( &equalize_map, 0, sizeof(int32_t) * 256 );
+
+ // form histogram
+ for(y=0; y < head.biHeight; y++){
+ info.nProgress = (int32_t)(50*y/head.biHeight);
+ if (info.nEscape) break;
+ for(x=0; x < head.biWidth; x++){
+ color = BlindGetPixelColor( x, y );
+ YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+ histogram[YVal]++;
+ }
+ }
+
+ // integrate the histogram to get the equalization map.
+ j = 0;
+ for(i=0; i <= 255; i++){
+ j += histogram[i];
+ map[i] = j;
+ }
+
+ // equalize
+ low = map[0];
+ high = map[255];
+ if (low == high) return false;
+ for( i = 0; i <= 255; i++ ){
+ equalize_map[i] = (uint32_t)((((double)( map[i] - low ) ) * 255) / ( high - low ) );
+ }
+
+ // stretch the histogram
+ if(head.biClrUsed == 0){ // No Palette
+ for( y = 0; y < head.biHeight; y++ ){
+ info.nProgress = (int32_t)(50+50*y/head.biHeight);
+ if (info.nEscape) break;
+ for( x = 0; x < head.biWidth; x++ ){
+
+ color = BlindGetPixelColor( x, y );
+ yuvClr = RGBtoYUV(color);
+
+ yuvClr.rgbRed = (uint8_t)equalize_map[yuvClr.rgbRed];
+
+ color = YUVtoRGB(yuvClr);
+ BlindSetPixelColor( x, y, color );
+ }
+ }
+ } else { // Palette
+ for( i = 0; i < (int32_t)head.biClrUsed; i++ ){
+
+ color = GetPaletteColor((uint8_t)i);
+ yuvClr = RGBtoYUV(color);
+
+ yuvClr.rgbRed = (uint8_t)equalize_map[yuvClr.rgbRed];
+
+ color = YUVtoRGB(yuvClr);
+ SetPaletteColor( (uint8_t)i, color );
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+// HistogramNormalize function by <dave> : dave(at)posortho(dot)com
+bool CxImage::HistogramNormalize()
+{
+ if (!pDib) return false;
+
+ int32_t histogram[256];
+ int32_t threshold_intensity, intense;
+ int32_t x, y, i;
+ uint32_t normalize_map[256];
+ uint32_t high, low, YVal;
+
+ RGBQUAD color;
+ RGBQUAD yuvClr;
+
+ memset( &histogram, 0, sizeof( int32_t ) * 256 );
+ memset( &normalize_map, 0, sizeof( uint32_t ) * 256 );
+
+ // form histogram
+ for(y=0; y < head.biHeight; y++){
+ info.nProgress = (int32_t)(50*y/head.biHeight);
+ if (info.nEscape) break;
+ for(x=0; x < head.biWidth; x++){
+ color = BlindGetPixelColor( x, y );
+ YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+ histogram[YVal]++;
+ }
+ }
+
+ // find histogram boundaries by locating the 1 percent levels
+ threshold_intensity = ( head.biWidth * head.biHeight) / 100;
+
+ intense = 0;
+ for( low = 0; low < 255; low++ ){
+ intense += histogram[low];
+ if( intense > threshold_intensity ) break;
+ }
+
+ intense = 0;
+ for( high = 255; high != 0; high--){
+ intense += histogram[ high ];
+ if( intense > threshold_intensity ) break;
+ }
+
+ if ( low == high ){
+ // Unreasonable contrast; use zero threshold to determine boundaries.
+ threshold_intensity = 0;
+ intense = 0;
+ for( low = 0; low < 255; low++){
+ intense += histogram[low];
+ if( intense > threshold_intensity ) break;
+ }
+ intense = 0;
+ for( high = 255; high != 0; high-- ){
+ intense += histogram [high ];
+ if( intense > threshold_intensity ) break;
+ }
+ }
+ if( low == high ) return false; // zero span bound
+
+ // Stretch the histogram to create the normalized image mapping.
+ for(i = 0; i <= 255; i++){
+ if ( i < (int32_t) low ){
+ normalize_map[i] = 0;
+ } else {
+ if(i > (int32_t) high)
+ normalize_map[i] = 255;
+ else
+ normalize_map[i] = ( 255 - 1) * ( i - low) / ( high - low );
+ }
+ }
+
+ // Normalize
+ if( head.biClrUsed == 0 ){
+ for( y = 0; y < head.biHeight; y++ ){
+ info.nProgress = (int32_t)(50+50*y/head.biHeight);
+ if (info.nEscape) break;
+ for( x = 0; x < head.biWidth; x++ ){
+
+ color = BlindGetPixelColor( x, y );
+ yuvClr = RGBtoYUV( color );
+
+ yuvClr.rgbRed = (uint8_t)normalize_map[yuvClr.rgbRed];
+
+ color = YUVtoRGB( yuvClr );
+ BlindSetPixelColor( x, y, color );
+ }
+ }
+ } else {
+ for(i = 0; i < (int32_t)head.biClrUsed; i++){
+
+ color = GetPaletteColor( (uint8_t)i );
+ yuvClr = RGBtoYUV( color );
+
+ yuvClr.rgbRed = (uint8_t)normalize_map[yuvClr.rgbRed];
+
+ color = YUVtoRGB( yuvClr );
+ SetPaletteColor( (uint8_t)i, color );
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+// HistogramLog function by <dave> : dave(at)posortho(dot)com
+bool CxImage::HistogramLog()
+{
+ if (!pDib) return false;
+
+ //q(i,j) = 255/log(1 + |high|) * log(1 + |p(i,j)|);
+ int32_t x, y, i;
+ RGBQUAD color;
+ RGBQUAD yuvClr;
+
+ uint32_t YVal, high = 1;
+
+ // Find Highest Luminance Value in the Image
+ if( head.biClrUsed == 0 ){ // No Palette
+ for(y=0; y < head.biHeight; y++){
+ info.nProgress = (int32_t)(50*y/head.biHeight);
+ if (info.nEscape) break;
+ for(x=0; x < head.biWidth; x++){
+ color = BlindGetPixelColor( x, y );
+ YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+ if (YVal > high ) high = YVal;
+ }
+ }
+ } else { // Palette
+ for(i = 0; i < (int32_t)head.biClrUsed; i++){
+ color = GetPaletteColor((uint8_t)i);
+ YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+ if (YVal > high ) high = YVal;
+ }
+ }
+
+ // Logarithm Operator
+ double k = 255.0 / ::log( 1.0 + (double)high );
+ if( head.biClrUsed == 0 ){
+ for( y = 0; y < head.biHeight; y++ ){
+ info.nProgress = (int32_t)(50+50*y/head.biHeight);
+ if (info.nEscape) break;
+ for( x = 0; x < head.biWidth; x++ ){
+
+ color = BlindGetPixelColor( x, y );
+ yuvClr = RGBtoYUV( color );
+
+ yuvClr.rgbRed = (uint8_t)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) );
+
+ color = YUVtoRGB( yuvClr );
+ BlindSetPixelColor( x, y, color );
+ }
+ }
+ } else {
+ for(i = 0; i < (int32_t)head.biClrUsed; i++){
+
+ color = GetPaletteColor( (uint8_t)i );
+ yuvClr = RGBtoYUV( color );
+
+ yuvClr.rgbRed = (uint8_t)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) );
+
+ color = YUVtoRGB( yuvClr );
+ SetPaletteColor( (uint8_t)i, color );
+ }
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// HistogramRoot function by <dave> : dave(at)posortho(dot)com
+bool CxImage::HistogramRoot()
+{
+ if (!pDib) return false;
+ //q(i,j) = sqrt(|p(i,j)|);
+
+ int32_t x, y, i;
+ RGBQUAD color;
+ RGBQUAD yuvClr;
+ double dtmp;
+ uint32_t YVal, high = 1;
+
+ // Find Highest Luminance Value in the Image
+ if( head.biClrUsed == 0 ){ // No Palette
+ for(y=0; y < head.biHeight; y++){
+ info.nProgress = (int32_t)(50*y/head.biHeight);
+ if (info.nEscape) break;
+ for(x=0; x < head.biWidth; x++){
+ color = BlindGetPixelColor( x, y );
+ YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+ if (YVal > high ) high = YVal;
+ }
+ }
+ } else { // Palette
+ for(i = 0; i < (int32_t)head.biClrUsed; i++){
+ color = GetPaletteColor((uint8_t)i);
+ YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+ if (YVal > high ) high = YVal;
+ }
+ }
+
+ // Root Operator
+ double k = 256.0 / ::sqrt( 1.0 + (double)high );
+ if( head.biClrUsed == 0 ){
+ for( y = 0; y < head.biHeight; y++ ){
+ info.nProgress = (int32_t)(50+50*y/head.biHeight);
+ if (info.nEscape) break;
+ for( x = 0; x < head.biWidth; x++ ){
+
+ color = BlindGetPixelColor( x, y );
+ yuvClr = RGBtoYUV( color );
+
+ dtmp = k * ::sqrt( (double)yuvClr.rgbRed );
+ if ( dtmp > 255.0 ) dtmp = 255.0;
+ if ( dtmp < 0 ) dtmp = 0;
+ yuvClr.rgbRed = (uint8_t)dtmp;
+
+ color = YUVtoRGB( yuvClr );
+ BlindSetPixelColor( x, y, color );
+ }
+ }
+ } else {
+ for(i = 0; i < (int32_t)head.biClrUsed; i++){
+
+ color = GetPaletteColor( (uint8_t)i );
+ yuvClr = RGBtoYUV( color );
+
+ dtmp = k * ::sqrt( (double)yuvClr.rgbRed );
+ if ( dtmp > 255.0 ) dtmp = 255.0;
+ if ( dtmp < 0 ) dtmp = 0;
+ yuvClr.rgbRed = (uint8_t)dtmp;
+
+ color = YUVtoRGB( yuvClr );
+ SetPaletteColor( (uint8_t)i, color );
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif
diff --git a/archive/hge/CxImage/ximaico.cpp b/archive/hge/CxImage/ximaico.cpp new file mode 100644 index 0000000..a808697 --- /dev/null +++ b/archive/hge/CxImage/ximaico.cpp @@ -0,0 +1,470 @@ +/*
+ * File: ximaico.cpp
+ * Purpose: Platform Independent ICON Image Class Loader and Writer (MS version)
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximaico.h"
+
+#if CXIMAGE_SUPPORT_ICO
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageICO::Decode(CxFile *hFile)
+{
+ if (hFile==NULL) return false;
+
+ uint32_t off = hFile->Tell(); //<yuandi>
+ int32_t page=info.nFrame; //internal icon structure indexes
+
+ // read the first part of the header
+ ICONHEADER icon_header;
+ hFile->Read(&icon_header,sizeof(ICONHEADER),1);
+
+ icon_header.idType = m_ntohs(icon_header.idType);
+ icon_header.idCount = m_ntohs(icon_header.idCount);
+
+ // check if it's an icon or a cursor
+ if ((icon_header.idReserved == 0) && ((icon_header.idType == 1)||(icon_header.idType == 2))) {
+
+ info.nNumFrames = icon_header.idCount;
+
+ // load the icon descriptions
+ ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header.idCount * sizeof(ICONDIRENTRY));
+ int32_t c;
+ for (c = 0; c < icon_header.idCount; c++) {
+ hFile->Read(icon_list + c, sizeof(ICONDIRENTRY), 1);
+
+ icon_list[c].wPlanes = m_ntohs(icon_list[c].wPlanes);
+ icon_list[c].wBitCount = m_ntohs(icon_list[c].wBitCount);
+ icon_list[c].dwBytesInRes = m_ntohl(icon_list[c].dwBytesInRes);
+ icon_list[c].dwImageOffset = m_ntohl(icon_list[c].dwImageOffset);
+ }
+
+ if ((page>=0)&&(page<icon_header.idCount)){
+
+ if (info.nEscape == -1) {
+ // Return output dimensions only
+ head.biWidth = icon_list[page].bWidth;
+ head.biHeight = icon_list[page].bHeight;
+#if CXIMAGE_SUPPORT_PNG
+ if (head.biWidth==0 && head.biHeight==0)
+ { // Vista icon support
+ hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET);
+ CxImage png;
+ png.SetEscape(-1);
+ if (png.Decode(hFile,CXIMAGE_FORMAT_PNG)){
+ Transfer(png);
+ info.nNumFrames = icon_header.idCount;
+ }
+ }
+#endif //CXIMAGE_SUPPORT_PNG
+ free(icon_list);
+ info.dwType = CXIMAGE_FORMAT_ICO;
+ return true;
+ }
+
+ // get the bit count for the colors in the icon <CoreyRLucier>
+ BITMAPINFOHEADER bih;
+ hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET);
+
+ if (icon_list[page].bWidth==0 && icon_list[page].bHeight==0)
+ { // Vista icon support
+#if CXIMAGE_SUPPORT_PNG
+ CxImage png;
+ if (png.Decode(hFile,CXIMAGE_FORMAT_PNG)){
+ Transfer(png);
+ info.nNumFrames = icon_header.idCount;
+ }
+ SetType(CXIMAGE_FORMAT_ICO);
+#endif //CXIMAGE_SUPPORT_PNG
+ }
+ else
+ { // standard icon
+ hFile->Read(&bih,sizeof(BITMAPINFOHEADER),1);
+
+ bihtoh(&bih);
+
+ c = bih.biBitCount;
+
+ // allocate memory for one icon
+ Create(icon_list[page].bWidth,icon_list[page].bHeight, c, CXIMAGE_FORMAT_ICO); //image creation
+
+ // read the palette
+ RGBQUAD pal[256];
+ if (bih.biClrUsed)
+ hFile->Read(pal,bih.biClrUsed*sizeof(RGBQUAD), 1);
+ else
+ hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1);
+
+ SetPalette(pal,head.biClrUsed); //palette assign
+
+ //read the icon
+ if (c<=24){
+ hFile->Read(info.pImage, head.biSizeImage, 1);
+ } else { // 32 bit icon
+ uint8_t* buf=(uint8_t*)malloc(4*head.biHeight*head.biWidth);
+ uint8_t* src = buf;
+ hFile->Read(buf, 4*head.biHeight*head.biWidth, 1);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (!AlphaIsValid()) AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+ for (int32_t y = 0; y < head.biHeight; y++) {
+ uint8_t* dst = GetBits(y);
+ for(int32_t x=0;x<head.biWidth;x++){
+ *dst++=src[0];
+ *dst++=src[1];
+ *dst++=src[2];
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaSet(x,y,src[3]);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ src+=4;
+ }
+ }
+ free(buf);
+ }
+ // apply the AND and XOR masks
+ int32_t maskwdt = ((head.biWidth+31) / 32) * 4; //line width of AND mask (always 1 Bpp)
+ int32_t masksize = head.biHeight * maskwdt; //size of mask
+ uint8_t *mask = (uint8_t *)malloc(masksize);
+ if (hFile->Read(mask, masksize, 1)){
+
+ bool bGoodMask=false;
+ for (int32_t im=0;im<masksize;im++){
+ if (mask[im]!=255){
+ bGoodMask=true;
+ break;
+ }
+ }
+
+ if (bGoodMask){
+#if CXIMAGE_SUPPORT_ALPHA
+ bool bNeedAlpha = false;
+ if (!AlphaIsValid()){
+ AlphaCreate();
+ } else {
+ bNeedAlpha=true; //32bit icon
+ }
+ int32_t x,y;
+ for (y = 0; y < head.biHeight; y++) {
+ for (x = 0; x < head.biWidth; x++) {
+ if (((mask[y*maskwdt+(x>>3)]>>(7-x%8))&0x01)){
+ AlphaSet(x,y,0);
+ bNeedAlpha=true;
+ }
+ }
+ }
+ if (!bNeedAlpha) AlphaDelete();
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ //check if there is only one transparent color
+ RGBQUAD cc,ct;
+ int32_t nTransColors=0;
+ int32_t nTransIndex=0;
+ for (y = 0; y < head.biHeight; y++){
+ for (x = 0; x < head.biWidth; x++){
+ if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){
+ cc = GetPixelColor(x,y,false);
+ if (nTransColors==0){
+ nTransIndex = GetPixelIndex(x,y);
+ nTransColors++;
+ ct = cc;
+ } else {
+ if (memcmp(&cc, &ct, sizeof(RGBQUAD)) != 0){
+ nTransColors++;
+ }
+ }
+ }
+ }
+ }
+ if (nTransColors==1 && c<=8){
+ SetTransColor(ct);
+ SetTransIndex(nTransIndex);
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaDelete(); //because we have a unique transparent color in the image
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+
+ // <vho> - Transparency support w/o Alpha support
+ if (c <= 8){ // only for icons with less than 256 colors (XP icons need alpha).
+
+ // find a color index, which is not used in the image
+ // it is almost sure to find one, bcs. nobody uses all possible colors for an icon
+
+ uint8_t colorsUsed[256];
+ memset(colorsUsed, 0, sizeof(colorsUsed));
+
+ for (y = 0; y < head.biHeight; y++){
+ for (x = 0; x < head.biWidth; x++){
+ colorsUsed[BlindGetPixelIndex(x,y)] = 1;
+ }
+ }
+
+ int32_t iTransIdx = -1;
+ for (x = (int32_t)(head.biClrUsed-1); x>=0 ; x--){
+ if (colorsUsed[x] == 0){
+ iTransIdx = x; // this one is not in use. we may use it as transparent color
+ break;
+ }
+ }
+
+ // Go thru image and set unused color as transparent index if needed
+ if (iTransIdx >= 0){
+ bool bNeedTrans = false;
+ for (y = 0; y < head.biHeight; y++){
+ for (x = 0; x < head.biWidth; x++){
+ // AND mask (Each Byte represents 8 Pixels)
+ if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){
+ // AND mask is set (!=0). This is a transparent part
+ SetPixelIndex(x, y, (uint8_t)iTransIdx);
+ bNeedTrans = true;
+ }
+ }
+ }
+ // set transparent index if needed
+ if (bNeedTrans) SetTransIndex(iTransIdx);
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaDelete(); //because we have a transparent color in the palette
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+ } else {
+ SetTransIndex(0); //empty mask, set black as transparent color
+ Negative();
+ }
+ }
+ free(mask);
+ }
+ free(icon_list);
+ // icon has been loaded successfully!
+ return true;
+ }
+ free(icon_list);
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+// Thanks to <Alas>
+bool CxImageICO::Encode(CxFile * hFile, CxImage ** pImages, int32_t nPageCount)
+{
+ cx_try
+ {
+ if (hFile==NULL) cx_throw("invalid file pointer");
+ if (pImages==NULL || nPageCount<=0) cx_throw("multipage ICO, no images!");
+
+ int32_t i;
+ for (i=0; i<nPageCount; i++){
+ if (pImages[i]==NULL)
+ cx_throw("Bad image pointer");
+ if (!(pImages[i]->IsValid()))
+ cx_throw("Empty image");
+ }
+
+ CxImageICO ghost;
+ for (i=0; i<nPageCount; i++){ //write headers
+ ghost.Ghost(pImages[i]);
+ ghost.info.nNumFrames = nPageCount;
+ if (i==0) {
+ if (!ghost.Encode(hFile,false,nPageCount))
+ cx_throw("Error writing ICO file header");
+ }
+ if (!ghost.Encode(hFile,true,nPageCount))
+ cx_throw("Error saving ICO image header");
+ }
+ for (i=0; i<nPageCount; i++){ //write bodies
+ ghost.Ghost(pImages[i]);
+ ghost.info.nNumFrames = nPageCount;
+ if (!ghost.Encode(hFile,true,i))
+ cx_throw("Error saving ICO body");
+ }
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageICO::Encode(CxFile * hFile, bool bAppend, int32_t nPageCount)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+#if CXIMAGE_SUPPORT_PNG == 0
+ //check format limits
+ if ((head.biWidth>255)||(head.biHeight>255)){
+ strcpy(info.szLastError,"Can't save this image as icon");
+ return false;
+ }
+#endif
+
+ //prepare the palette struct
+ RGBQUAD* pal=GetPalette();
+ if (head.biBitCount<=8 && pal==NULL) return false;
+
+ int32_t maskwdt=((head.biWidth+31)/32)*4; //mask line width
+ int32_t masksize=head.biHeight * maskwdt; //size of mask
+ int32_t bitcount=head.biBitCount;
+ int32_t imagesize=head.biSizeImage;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid() && head.biClrUsed==0){
+ bitcount=32;
+ imagesize=4*head.biHeight*head.biWidth;
+ }
+#endif
+
+ //fill the icon headers
+ int32_t nPages = nPageCount;
+ if (nPages<1) nPages = 1;
+
+ ICONHEADER icon_header={0,1,nPages};
+
+ if (!bAppend)
+ m_dwImageOffset = sizeof(ICONHEADER) + nPages * sizeof(ICONDIRENTRY);
+
+ uint32_t dwBytesInRes = sizeof(BITMAPINFOHEADER)+head.biClrUsed*sizeof(RGBQUAD)+imagesize+masksize;
+
+ ICONDIRENTRY icon_list={
+ (uint8_t)head.biWidth,
+ (uint8_t)head.biHeight,
+ (uint8_t)head.biClrUsed,
+ 0, 0,
+ (uint16_t)bitcount,
+ dwBytesInRes,
+ m_dwImageOffset
+ };
+
+ BITMAPINFOHEADER bi={
+ sizeof(BITMAPINFOHEADER),
+ head.biWidth,
+ 2*head.biHeight,
+ 1,
+ (uint16_t)bitcount,
+ 0, imagesize,
+ 0, 0, 0, 0
+ };
+
+#if CXIMAGE_SUPPORT_PNG // Vista icon support
+ CxImage png(*this);
+ CxMemFile memfile;
+ if (head.biWidth>255 || head.biHeight>255){
+ icon_list.bWidth = icon_list.bHeight = 0;
+ memfile.Open();
+ png.Encode(&memfile,CXIMAGE_FORMAT_PNG);
+ icon_list.dwBytesInRes = dwBytesInRes = memfile.Size();
+ }
+#endif //CXIMAGE_SUPPORT_PNG
+
+ if (!bAppend){
+ icon_header.idType = m_ntohs(icon_header.idType);
+ icon_header.idCount = m_ntohs(icon_header.idCount);
+ hFile->Write(&icon_header,sizeof(ICONHEADER),1); //write the file header
+ icon_header.idType = m_ntohs(icon_header.idType);
+ icon_header.idCount = m_ntohs(icon_header.idCount);
+ }
+
+
+ if ((bAppend && nPageCount==info.nNumFrames) || (!bAppend && nPageCount==0)){
+ icon_list.wPlanes = m_ntohs(icon_list.wPlanes);
+ icon_list.wBitCount = m_ntohs(icon_list.wBitCount);
+ icon_list.dwBytesInRes = m_ntohl(icon_list.dwBytesInRes);
+ icon_list.dwImageOffset = m_ntohl(icon_list.dwImageOffset);
+ hFile->Write(&icon_list,sizeof(ICONDIRENTRY),1); //write the image entry
+ icon_list.wPlanes = m_ntohs(icon_list.wPlanes);
+ icon_list.wBitCount = m_ntohs(icon_list.wBitCount);
+ icon_list.dwBytesInRes = m_ntohl(icon_list.dwBytesInRes);
+ icon_list.dwImageOffset = m_ntohl(icon_list.dwImageOffset);
+
+ m_dwImageOffset += dwBytesInRes; //update offset for next header
+ }
+
+ if ((bAppend && nPageCount<info.nNumFrames) || (!bAppend && nPageCount==0))
+ {
+#if CXIMAGE_SUPPORT_PNG
+ if (icon_list.bWidth==0 && icon_list.bHeight==0) { // Vista icon support
+ hFile->Write(memfile.GetBuffer(false),dwBytesInRes,1);
+ } else
+#endif //CXIMAGE_SUPPORT_PNG
+ { // standard icon
+ bihtoh(&bi);
+ hFile->Write(&bi,sizeof(BITMAPINFOHEADER),1); //write the image header
+ bihtoh(&bi);
+
+ bool bTransparent = info.nBkgndIndex >= 0;
+ RGBQUAD ct = GetTransColor();
+ if (pal){
+ if (bTransparent) SetPaletteColor((uint8_t)info.nBkgndIndex,0,0,0,0);
+ hFile->Write(pal,head.biClrUsed*sizeof(RGBQUAD),1); //write palette
+ if (bTransparent) SetPaletteColor((uint8_t)info.nBkgndIndex,ct);
+ }
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid() && head.biClrUsed==0){
+ uint8_t* buf=(uint8_t*)malloc(imagesize);
+ uint8_t* dst = buf;
+ for (int32_t y = 0; y < head.biHeight; y++) {
+ uint8_t* src = GetBits(y);
+ for(int32_t x=0;x<head.biWidth;x++){
+ *dst++=*src++;
+ *dst++=*src++;
+ *dst++=*src++;
+ *dst++=AlphaGet(x,y);
+ }
+ }
+ hFile->Write(buf,imagesize, 1);
+ free(buf);
+ } else {
+ hFile->Write(info.pImage,imagesize,1); //write image
+ }
+#else
+ hFile->Write(info.pImage,imagesize,1); //write image
+#endif
+
+ //save transparency mask
+ uint8_t* mask=(uint8_t*)calloc(masksize,1); //create empty AND/XOR masks
+ if (!mask) return false;
+
+ //prepare the variables to build the mask
+ uint8_t* iDst;
+ int32_t pos,i;
+ RGBQUAD c={0,0,0,0};
+ int32_t* pc = (int32_t*)&c;
+ int32_t* pct= (int32_t*)&ct;
+#if CXIMAGE_SUPPORT_ALPHA
+ bool bAlphaPaletteIsValid = AlphaPaletteIsValid();
+ bool bAlphaIsValid = AlphaIsValid();
+#endif
+ //build the mask
+ for (int32_t y = 0; y < head.biHeight; y++) {
+ for (int32_t x = 0; x < head.biWidth; x++) {
+ i=0;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (bAlphaIsValid && AlphaGet(x,y)==0) i=1;
+ if (bAlphaPaletteIsValid && BlindGetPixelColor(x,y).rgbReserved==0) i=1;
+#endif
+ c=GetPixelColor(x,y,false);
+ if (bTransparent && *pc==*pct) i=1;
+ iDst = mask + y*maskwdt + (x>>3);
+ pos = 7-x%8;
+ *iDst &= ~(0x01<<pos);
+ *iDst |= ((i & 0x01)<<pos);
+ }
+ }
+ //write AND/XOR masks
+ hFile->Write(mask,masksize,1);
+ free(mask);
+ }
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ICO
+
diff --git a/archive/hge/CxImage/ximaico.h b/archive/hge/CxImage/ximaico.h new file mode 100644 index 0000000..8d81b02 --- /dev/null +++ b/archive/hge/CxImage/ximaico.h @@ -0,0 +1,58 @@ +/*
+ * File: ximaico.h
+ * Purpose: ICON Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageICO (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ * ==========================================================
+ */
+#if !defined(__ximaICO_h)
+#define __ximaICO_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_ICO
+
+class CxImageICO: public CxImage
+{
+typedef struct tagIconDirectoryEntry {
+ uint8_t bWidth;
+ uint8_t bHeight;
+ uint8_t bColorCount;
+ uint8_t bReserved;
+ uint16_t wPlanes;
+ uint16_t wBitCount;
+ uint32_t dwBytesInRes;
+ uint32_t dwImageOffset;
+} ICONDIRENTRY;
+
+typedef struct tagIconDir {
+ uint16_t idReserved;
+ uint16_t idType;
+ uint16_t idCount;
+} ICONHEADER;
+
+public:
+ CxImageICO(): CxImage(CXIMAGE_FORMAT_ICO) {m_dwImageOffset=0;}
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_ICO);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_ICO);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile, bool bAppend=false, int32_t nPageCount=0);
+ bool Encode(CxFile * hFile, CxImage ** pImages, int32_t nPageCount);
+ bool Encode(FILE *hFile, bool bAppend=false, int32_t nPageCount=0)
+ { CxIOFile file(hFile); return Encode(&file,bAppend,nPageCount); }
+ bool Encode(FILE *hFile, CxImage ** pImages, int32_t nPageCount)
+ { CxIOFile file(hFile); return Encode(&file, pImages, nPageCount); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+protected:
+ uint32_t m_dwImageOffset;
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximainfo.cpp b/archive/hge/CxImage/ximainfo.cpp new file mode 100644 index 0000000..582d9ed --- /dev/null +++ b/archive/hge/CxImage/ximainfo.cpp @@ -0,0 +1,958 @@ +// ximainfo.cpp : main attributes
+/* 03/10/2004 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+#if defined(_LINUX) || defined(__APPLE__)
+ #define _tcsnicmp(a,b,c) strcasecmp(a,b)
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return the color used for transparency, and/or for background color
+ */
+RGBQUAD CxImage::GetTransColor()
+{
+ if (head.biBitCount<24 && info.nBkgndIndex>=0) return GetPaletteColor((uint8_t)info.nBkgndIndex);
+ return info.nBkgndColor;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the index used for transparency. Returns -1 for no transparancy.
+ */
+int32_t CxImage::GetTransIndex() const
+{
+ return info.nBkgndIndex;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the index used for transparency with 1, 4 and 8 bpp images. Set to -1 to remove the effect.
+ */
+void CxImage::SetTransIndex(int32_t idx)
+{
+ if (idx<(int32_t)head.biClrUsed)
+ info.nBkgndIndex = idx;
+ else
+ info.nBkgndIndex = 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the color used for transparency with 24 bpp images.
+ * You must call SetTransIndex(0) to enable the effect, SetTransIndex(-1) to disable it.
+ */
+void CxImage::SetTransColor(RGBQUAD rgb)
+{
+ rgb.rgbReserved=0;
+ info.nBkgndColor = rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::IsTransparent() const
+{
+ return info.nBkgndIndex>=0; // <vho>
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns true if the image has 256 colors or less.
+ */
+bool CxImage::IsIndexed() const
+{
+ return head.biClrUsed!=0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return 1 = indexed, 2 = RGB, 4 = RGBA
+ */
+uint8_t CxImage::GetColorType()
+{
+ uint8_t b = (uint8_t)((head.biBitCount>8) ? 2 /*COLORTYPE_COLOR*/ : 1 /*COLORTYPE_PALETTE*/);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) b = 4 /*COLORTYPE_ALPHA*/;
+#endif //CXIMAGE_SUPPORT_ALPHA
+ return b;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return Resolution for TIFF, JPEG, PNG and BMP formats.
+ */
+int32_t CxImage::GetXDPI() const
+{
+ return info.xDPI;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return Resolution for TIFF, JPEG, PNG and BMP formats.
+ */
+int32_t CxImage::GetYDPI() const
+{
+ return info.yDPI;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Set resolution for TIFF, JPEG, PNG and BMP formats.
+ */
+void CxImage::SetXDPI(int32_t dpi)
+{
+ if (dpi<=0) dpi = CXIMAGE_DEFAULT_DPI;
+ info.xDPI = dpi;
+ head.biXPelsPerMeter = (int32_t) floor(dpi * 10000.0 / 254.0 + 0.5);
+ if (pDib) ((BITMAPINFOHEADER*)pDib)->biXPelsPerMeter = head.biXPelsPerMeter;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Set resolution for TIFF, JPEG, PNG and BMP formats.
+ */
+void CxImage::SetYDPI(int32_t dpi)
+{
+ if (dpi<=0) dpi = CXIMAGE_DEFAULT_DPI;
+ info.yDPI = dpi;
+ head.biYPelsPerMeter = (int32_t) floor(dpi * 10000.0 / 254.0 + 0.5);
+ if (pDib) ((BITMAPINFOHEADER*)pDib)->biYPelsPerMeter = head.biYPelsPerMeter;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetFlags
+ */
+uint32_t CxImage::GetFlags() const
+{
+ return info.dwFlags;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Image flags, for future use
+ * \param flags
+ * - 0x??00000 = reserved for 16 bit, CMYK, multilayer
+ * - 0x00??0000 = blend modes
+ * - 0x0000???? = layer id or user flags
+ *
+ * \param bLockReservedFlags protects the "reserved" and "blend modes" flags
+ */
+void CxImage::SetFlags(uint32_t flags, bool bLockReservedFlags)
+{
+ if (bLockReservedFlags) info.dwFlags = flags & 0x0000ffff;
+ else info.dwFlags = flags;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetCodecOption
+ */
+uint32_t CxImage::GetCodecOption(uint32_t imagetype)
+{
+ imagetype = GetTypeIndexFromId(imagetype);
+ if (imagetype==0){
+ imagetype = GetTypeIndexFromId(GetType());
+ }
+ return info.dwCodecOpt[imagetype];
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Encode option for GIF, TIF, JPG, PNG and RAW
+ * - GIF : 0 = LZW (default), 1 = none, 2 = RLE.
+ * - TIF : 0 = automatic (default), or a valid compression code as defined in "tiff.h" (COMPRESSION_NONE = 1, COMPRESSION_CCITTRLE = 2, ...)
+ * - JPG : valid values stored in enum CODEC_OPTION ( ENCODE_BASELINE = 0x01, ENCODE_PROGRESSIVE = 0x10, ...)
+ * - PNG : combination of interlace option and compression option
+ * interlace option : 1 = interlace, 0 = no interlace
+ * compression option : 2 = no compression, 4 = best speed, 6 = best compression, 8 = default compression
+ * default is no interlace and default compression
+ * example : 5 = 1+4 = interlace + best speed
+ * - RAW : valid values stored in enum CODEC_OPTION ( DECODE_QUALITY_LIN = 0x00, DECODE_QUALITY_VNG = 0x01, ...)
+ *
+ * \return true if everything is ok
+ */
+bool CxImage::SetCodecOption(uint32_t opt, uint32_t imagetype)
+{
+ imagetype = GetTypeIndexFromId(imagetype);
+ if (imagetype==0){
+ imagetype = GetTypeIndexFromId(GetType());
+ }
+ info.dwCodecOpt[imagetype] = opt;
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return internal hDib object..
+ */
+void* CxImage::GetDIB() const
+{
+ return pDib;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImage::GetHeight() const
+{
+ return head.biHeight;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImage::GetWidth() const
+{
+ return head.biWidth;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return uint32_t aligned width of the image.
+ */
+uint32_t CxImage::GetEffWidth() const
+{
+ return info.dwEffWidth;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return 2, 16, 256; 0 for RGB images.
+ */
+uint32_t CxImage::GetNumColors() const
+{
+ return head.biClrUsed;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return: 1, 4, 8, 24.
+ */
+uint16_t CxImage::GetBpp() const
+{
+ return head.biBitCount;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return original image format
+ * \sa ENUM_CXIMAGE_FORMATS.
+ */
+uint32_t CxImage::GetType() const
+{
+ return info.dwType;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * change image format identifier
+ * \sa ENUM_CXIMAGE_FORMATS.
+ */
+bool CxImage::SetType(uint32_t type)
+{
+ switch (type){
+#if CXIMAGE_SUPPORT_BMP
+ case CXIMAGE_FORMAT_BMP:
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ case CXIMAGE_FORMAT_GIF:
+#endif
+#if CXIMAGE_SUPPORT_JPG
+ case CXIMAGE_FORMAT_JPG:
+#endif
+#if CXIMAGE_SUPPORT_PNG
+ case CXIMAGE_FORMAT_PNG:
+#endif
+#if CXIMAGE_SUPPORT_MNG
+ case CXIMAGE_FORMAT_MNG:
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ case CXIMAGE_FORMAT_ICO:
+#endif
+#if CXIMAGE_SUPPORT_TIF
+ case CXIMAGE_FORMAT_TIF:
+#endif
+#if CXIMAGE_SUPPORT_TGA
+ case CXIMAGE_FORMAT_TGA:
+#endif
+#if CXIMAGE_SUPPORT_PCX
+ case CXIMAGE_FORMAT_PCX:
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+ case CXIMAGE_FORMAT_WBMP:
+#endif
+#if CXIMAGE_SUPPORT_WMF
+ case CXIMAGE_FORMAT_WMF:
+#endif
+#if CXIMAGE_SUPPORT_JBG
+ case CXIMAGE_FORMAT_JBG:
+#endif
+#if CXIMAGE_SUPPORT_JP2
+ case CXIMAGE_FORMAT_JP2:
+#endif
+#if CXIMAGE_SUPPORT_JPC
+ case CXIMAGE_FORMAT_JPC:
+#endif
+#if CXIMAGE_SUPPORT_PGX
+ case CXIMAGE_FORMAT_PGX:
+#endif
+#if CXIMAGE_SUPPORT_PNM
+ case CXIMAGE_FORMAT_PNM:
+#endif
+#if CXIMAGE_SUPPORT_RAS
+ case CXIMAGE_FORMAT_RAS:
+#endif
+#if CXIMAGE_SUPPORT_SKA
+ case CXIMAGE_FORMAT_SKA:
+#endif
+#if CXIMAGE_SUPPORT_RAW
+ case CXIMAGE_FORMAT_RAW:
+#endif
+#if CXIMAGE_SUPPORT_PSD
+ case CXIMAGE_FORMAT_PSD:
+#endif
+ info.dwType = type;
+ return true;
+ case CXIMAGE_FORMAT_UNKNOWN:
+ default:
+ info.dwType = CXIMAGE_FORMAT_UNKNOWN;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImage::GetNumTypes()
+{
+ return CMAX_IMAGE_FORMATS-1;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImage::GetTypeIdFromName(const TCHAR* ext)
+{
+#if CXIMAGE_SUPPORT_BMP
+ if (_tcsnicmp(ext,_T("bmp"),3)==0 ) return CXIMAGE_FORMAT_BMP;
+#endif
+#if CXIMAGE_SUPPORT_JPG
+ if (_tcsnicmp(ext,_T("jpg"),3)==0 ||
+ _tcsnicmp(ext,_T("jpe"),3)==0 ||
+ _tcsnicmp(ext,_T("jfi"),3)==0 ) return CXIMAGE_FORMAT_JPG;
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ if (_tcsnicmp(ext,_T("gif"),3)==0 ) return CXIMAGE_FORMAT_GIF;
+#endif
+#if CXIMAGE_SUPPORT_PNG
+ if (_tcsnicmp(ext,_T("png"),3)==0 ) return CXIMAGE_FORMAT_PNG;
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ if (_tcsnicmp(ext,_T("ico"),3)==0 ||
+ _tcsnicmp(ext,_T("cur"),3)==0 ) return CXIMAGE_FORMAT_ICO;
+#endif
+#if CXIMAGE_SUPPORT_TIF
+ if (_tcsnicmp(ext,_T("tif"),3)==0 ) return CXIMAGE_FORMAT_TIF;
+#endif
+#if CXIMAGE_SUPPORT_TGA
+ if (_tcsnicmp(ext,_T("tga"),3)==0 ) return CXIMAGE_FORMAT_TGA;
+#endif
+#if CXIMAGE_SUPPORT_PCX
+ if (_tcsnicmp(ext,_T("pcx"),3)==0 ) return CXIMAGE_FORMAT_PCX;
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+ if (_tcsnicmp(ext,_T("wbm"),3)==0 ) return CXIMAGE_FORMAT_WBMP;
+#endif
+#if CXIMAGE_SUPPORT_WMF
+ if (_tcsnicmp(ext,_T("wmf"),3)==0 ||
+ _tcsnicmp(ext,_T("emf"),3)==0 ) return CXIMAGE_FORMAT_WMF;
+#endif
+#if CXIMAGE_SUPPORT_JP2
+ if (_tcsnicmp(ext,_T("jp2"),3)==0 ||
+ _tcsnicmp(ext,_T("j2k"),3)==0 ) return CXIMAGE_FORMAT_JP2;
+#endif
+#if CXIMAGE_SUPPORT_JPC
+ if (_tcsnicmp(ext,_T("jpc"),3)==0 ||
+ _tcsnicmp(ext,_T("j2c"),3)==0 ) return CXIMAGE_FORMAT_JPC;
+#endif
+#if CXIMAGE_SUPPORT_PGX
+ if (_tcsnicmp(ext,_T("pgx"),3)==0 ) return CXIMAGE_FORMAT_PGX;
+#endif
+#if CXIMAGE_SUPPORT_RAS
+ if (_tcsnicmp(ext,_T("ras"),3)==0 ) return CXIMAGE_FORMAT_RAS;
+#endif
+#if CXIMAGE_SUPPORT_PNM
+ if (_tcsnicmp(ext,_T("pnm"),3)==0 ||
+ _tcsnicmp(ext,_T("pgm"),3)==0 ||
+ _tcsnicmp(ext,_T("ppm"),3)==0 ) return CXIMAGE_FORMAT_PNM;
+#endif
+#if CXIMAGE_SUPPORT_JBG
+ if (_tcsnicmp(ext,_T("jbg"),3)==0 ) return CXIMAGE_FORMAT_JBG;
+#endif
+#if CXIMAGE_SUPPORT_MNG
+ if (_tcsnicmp(ext,_T("mng"),3)==0 ||
+ _tcsnicmp(ext,_T("jng"),3)==0 ) return CXIMAGE_FORMAT_MNG;
+#endif
+#if CXIMAGE_SUPPORT_SKA
+ if (_tcsnicmp(ext,_T("ska"),3)==0 ) return CXIMAGE_FORMAT_SKA;
+#endif
+#if CXIMAGE_SUPPORT_PSD
+ if (_tcsnicmp(ext,_T("psd"),3)==0 ) return CXIMAGE_FORMAT_PSD;
+#endif
+#if CXIMAGE_SUPPORT_RAW
+ if (_tcsnicmp(ext,_T("nef"),3)==0 ||
+ _tcsnicmp(ext,_T("crw"),3)==0 ||
+ _tcsnicmp(ext,_T("cr2"),3)==0 ||
+ _tcsnicmp(ext,_T("dng"),3)==0 ||
+ _tcsnicmp(ext,_T("arw"),3)==0 ||
+ _tcsnicmp(ext,_T("erf"),3)==0 ||
+ _tcsnicmp(ext,_T("3fr"),3)==0 ||
+ _tcsnicmp(ext,_T("dcr"),3)==0 ||
+ _tcsnicmp(ext,_T("raw"),3)==0 ||
+ _tcsnicmp(ext,_T("x3f"),3)==0 ||
+ _tcsnicmp(ext,_T("mef"),3)==0 ||
+ _tcsnicmp(ext,_T("raf"),3)==0 ||
+ _tcsnicmp(ext,_T("mrw"),3)==0 ||
+ _tcsnicmp(ext,_T("pef"),3)==0 ||
+ _tcsnicmp(ext,_T("sr2"),3)==0 ||
+ _tcsnicmp(ext,_T("orf"),3)==0 ) return CXIMAGE_FORMAT_RAW;
+#endif
+
+ return CXIMAGE_FORMAT_UNKNOWN;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImage::GetTypeIdFromIndex(const uint32_t index)
+{
+ uint32_t n;
+
+ n=0; if (index == n) return CXIMAGE_FORMAT_UNKNOWN;
+#if CXIMAGE_SUPPORT_BMP
+ n++; if (index == n) return CXIMAGE_FORMAT_BMP;
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ n++; if (index == n) return CXIMAGE_FORMAT_GIF;
+#endif
+#if CXIMAGE_SUPPORT_JPG
+ n++; if (index == n) return CXIMAGE_FORMAT_JPG;
+#endif
+#if CXIMAGE_SUPPORT_PNG
+ n++; if (index == n) return CXIMAGE_FORMAT_PNG;
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ n++; if (index == n) return CXIMAGE_FORMAT_ICO;
+#endif
+#if CXIMAGE_SUPPORT_TIF
+ n++; if (index == n) return CXIMAGE_FORMAT_TIF;
+#endif
+#if CXIMAGE_SUPPORT_TGA
+ n++; if (index == n) return CXIMAGE_FORMAT_TGA;
+#endif
+#if CXIMAGE_SUPPORT_PCX
+ n++; if (index == n) return CXIMAGE_FORMAT_PCX;
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+ n++; if (index == n) return CXIMAGE_FORMAT_WBMP;
+#endif
+#if CXIMAGE_SUPPORT_WMF
+ n++; if (index == n) return CXIMAGE_FORMAT_WMF;
+#endif
+#if CXIMAGE_SUPPORT_JP2
+ n++; if (index == n) return CXIMAGE_FORMAT_JP2;
+#endif
+#if CXIMAGE_SUPPORT_JPC
+ n++; if (index == n) return CXIMAGE_FORMAT_JPC;
+#endif
+#if CXIMAGE_SUPPORT_PGX
+ n++; if (index == n) return CXIMAGE_FORMAT_PGX;
+#endif
+#if CXIMAGE_SUPPORT_PNM
+ n++; if (index == n) return CXIMAGE_FORMAT_PNM;
+#endif
+#if CXIMAGE_SUPPORT_RAS
+ n++; if (index == n) return CXIMAGE_FORMAT_RAS;
+#endif
+#if CXIMAGE_SUPPORT_JBG
+ n++; if (index == n) return CXIMAGE_FORMAT_JBG;
+#endif
+#if CXIMAGE_SUPPORT_MNG
+ n++; if (index == n) return CXIMAGE_FORMAT_MNG;
+#endif
+#if CXIMAGE_SUPPORT_SKA
+ n++; if (index == n) return CXIMAGE_FORMAT_SKA;
+#endif
+#if CXIMAGE_SUPPORT_RAW
+ n++; if (index == n) return CXIMAGE_FORMAT_RAW;
+#endif
+#if CXIMAGE_SUPPORT_PSD
+ n++; if (index == n) return CXIMAGE_FORMAT_PSD;
+#endif
+
+ return CXIMAGE_FORMAT_UNKNOWN;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImage::GetTypeIndexFromId(const uint32_t id)
+{
+ uint32_t n;
+
+ n=0; if (id == CXIMAGE_FORMAT_UNKNOWN) return n;
+#if CXIMAGE_SUPPORT_BMP
+ n++; if (id == CXIMAGE_FORMAT_BMP) return n;
+#endif
+#if CXIMAGE_SUPPORT_GIF
+ n++; if (id == CXIMAGE_FORMAT_GIF) return n;
+#endif
+#if CXIMAGE_SUPPORT_JPG
+ n++; if (id == CXIMAGE_FORMAT_JPG) return n;
+#endif
+#if CXIMAGE_SUPPORT_PNG
+ n++; if (id == CXIMAGE_FORMAT_PNG) return n;
+#endif
+#if CXIMAGE_SUPPORT_ICO
+ n++; if (id == CXIMAGE_FORMAT_ICO) return n;
+#endif
+#if CXIMAGE_SUPPORT_TIF
+ n++; if (id == CXIMAGE_FORMAT_TIF) return n;
+#endif
+#if CXIMAGE_SUPPORT_TGA
+ n++; if (id == CXIMAGE_FORMAT_TGA) return n;
+#endif
+#if CXIMAGE_SUPPORT_PCX
+ n++; if (id == CXIMAGE_FORMAT_PCX) return n;
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+ n++; if (id == CXIMAGE_FORMAT_WBMP) return n;
+#endif
+#if CXIMAGE_SUPPORT_WMF
+ n++; if (id == CXIMAGE_FORMAT_WMF) return n;
+#endif
+#if CXIMAGE_SUPPORT_JP2
+ n++; if (id == CXIMAGE_FORMAT_JP2) return n;
+#endif
+#if CXIMAGE_SUPPORT_JPC
+ n++; if (id == CXIMAGE_FORMAT_JPC) return n;
+#endif
+#if CXIMAGE_SUPPORT_PGX
+ n++; if (id == CXIMAGE_FORMAT_PGX) return n;
+#endif
+#if CXIMAGE_SUPPORT_PNM
+ n++; if (id == CXIMAGE_FORMAT_PNM) return n;
+#endif
+#if CXIMAGE_SUPPORT_RAS
+ n++; if (id == CXIMAGE_FORMAT_RAS) return n;
+#endif
+#if CXIMAGE_SUPPORT_JBG
+ n++; if (id == CXIMAGE_FORMAT_JBG) return n;
+#endif
+#if CXIMAGE_SUPPORT_MNG
+ n++; if (id == CXIMAGE_FORMAT_MNG) return n;
+#endif
+#if CXIMAGE_SUPPORT_SKA
+ n++; if (id == CXIMAGE_FORMAT_SKA) return n;
+#endif
+#if CXIMAGE_SUPPORT_RAW
+ n++; if (id == CXIMAGE_FORMAT_RAW) return n;
+#endif
+#if CXIMAGE_SUPPORT_PSD
+ n++; if (id == CXIMAGE_FORMAT_PSD) return n;
+#endif
+
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return current frame delay in milliseconds. Only for GIF and MNG formats.
+ */
+uint32_t CxImage::GetFrameDelay() const
+{
+ return info.dwFrameDelay;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets current frame delay. Only for GIF format.
+ * \param d = delay in milliseconds
+ */
+void CxImage::SetFrameDelay(uint32_t d)
+{
+ info.dwFrameDelay=d;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::GetOffset(int32_t *x,int32_t *y)
+{
+ *x=info.xOffset;
+ *y=info.yOffset;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetOffset(int32_t x,int32_t y)
+{
+ info.xOffset=x;
+ info.yOffset=y;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetJpegQuality, GetJpegQualityF
+ * \author [DP]; changes [Stefan Schürmans]
+ */
+uint8_t CxImage::GetJpegQuality() const
+{
+ return (uint8_t)(info.fQuality + 0.5f);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetJpegQuality, GetJpegQuality
+ * \author [Stefan Schürmans]
+ */
+float CxImage::GetJpegQualityF() const
+{
+ return info.fQuality;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * quality level for JPEG and JPEG2000
+ * \param q: can be from 0 to 100
+ * \author [DP]; changes [Stefan Schürmans]
+ */
+void CxImage::SetJpegQuality(uint8_t q){
+ info.fQuality = (float)q;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * quality level for JPEG and JPEG2000
+ * necessary for JPEG2000 when quality is between 0.0 and 1.0
+ * \param q: can be from 0.0 to 100.0
+ * \author [Stefan Schürmans]
+ */
+void CxImage::SetJpegQualityF(float q){
+ if (q>0) info.fQuality = q;
+ else info.fQuality = 0.0f;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetJpegScale
+ */
+uint8_t CxImage::GetJpegScale() const
+{
+ return info.nJpegScale;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * scaling down during JPEG decoding valid numbers are 1, 2, 4, 8
+ * \author [ignacio]
+ */
+void CxImage::SetJpegScale(uint8_t q){
+ info.nJpegScale = q;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Used to monitor the slow loops.
+ * \return value is from 0 to 100.
+ * \sa SetProgress
+ */
+int32_t CxImage::GetProgress() const
+{
+ return info.nProgress;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return the escape code.
+ * \sa SetEscape
+ */
+int32_t CxImage::GetEscape() const
+{
+ return info.nEscape;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Forces the value of the internal progress variable.
+ * \param p should be from 0 to 100.
+ * \sa GetProgress
+ */
+void CxImage::SetProgress(int32_t p)
+{
+ info.nProgress = p;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Used to quit the slow loops or the codecs.
+ * - SetEscape(-1) before Decode forces the function to exit, right after
+ * the image width and height are available ( for bmp, jpg, gif, tif )
+ */
+void CxImage::SetEscape(int32_t i)
+{
+ info.nEscape = i;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the image is correctly initializated.
+ */
+bool CxImage::IsValid() const
+{
+ return pDib!=0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * True if the image is enabled for painting.
+ */
+bool CxImage::IsEnabled() const
+{
+ return info.bEnabled;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enables/disables the image.
+ */
+void CxImage::Enable(bool enable)
+{
+ info.bEnabled=enable;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * This function must be used after a Decode() / Load() call.
+ * Use the sequence SetFrame(-1); Load(...); GetNumFrames();
+ * to get the number of images without loading the first image.
+ * \return the number of images in the file.
+ */
+int32_t CxImage::GetNumFrames() const
+{
+ return info.nNumFrames;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return the current selected image (zero-based index).
+ */
+int32_t CxImage::GetFrame() const
+{
+ return info.nFrame;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the image number that the next Decode() / Load() call will load
+ */
+void CxImage::SetFrame(int32_t nFrame){
+ info.nFrame=nFrame;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the method for drawing the frame related to others
+ * \sa GetDisposalMethod
+ */
+void CxImage::SetDisposalMethod(uint8_t dm)
+{ info.dispmeth=dm; }
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the method for drawing the frame related to others
+ * Values : 0 - No disposal specified. The decoder is
+ * not required to take any action.
+ * 1 - Do not dispose. The graphic is to be left
+ * in place.
+ * 2 - Restore to background color. The area used by the
+ * graphic must be restored to the background color.
+ * 3 - Restore to previous. The decoder is required to
+ * restore the area overwritten by the graphic with
+ * what was there prior to rendering the graphic.
+ * 4-7 - To be defined.
+ */
+uint8_t CxImage::GetDisposalMethod() const
+{ return info.dispmeth; }
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::GetRetreiveAllFrames() const
+{ return info.bGetAllFrames; }
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetRetreiveAllFrames(bool flag)
+{ info.bGetAllFrames = flag; }
+////////////////////////////////////////////////////////////////////////////////
+CxImage * CxImage::GetFrame(int32_t nFrame) const
+{
+ if ( ppFrames == NULL) return NULL;
+ if ( info.nNumFrames == 0) return NULL;
+ if ( nFrame >= info.nNumFrames ) return NULL;
+ if ( nFrame < 0) nFrame = info.nNumFrames - 1;
+ return ppFrames[nFrame];
+}
+////////////////////////////////////////////////////////////////////////////////
+int16_t CxImage::m_ntohs(const int16_t word)
+{
+ if (info.bLittleEndianHost) return word;
+ return ( (word & 0xff) << 8 ) | ( (word >> 8) & 0xff );
+}
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImage::m_ntohl(const int32_t dword)
+{
+ if (info.bLittleEndianHost) return dword;
+ return ((dword & 0xff) << 24 ) | ((dword & 0xff00) << 8 ) |
+ ((dword >> 8) & 0xff00) | ((dword >> 24) & 0xff);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::bihtoh(BITMAPINFOHEADER* bih)
+{
+ bih->biSize = m_ntohl(bih->biSize);
+ bih->biWidth = m_ntohl(bih->biWidth);
+ bih->biHeight = m_ntohl(bih->biHeight);
+ bih->biPlanes = m_ntohs(bih->biPlanes);
+ bih->biBitCount = m_ntohs(bih->biBitCount);
+ bih->biCompression = m_ntohl(bih->biCompression);
+ bih->biSizeImage = m_ntohl(bih->biSizeImage);
+ bih->biXPelsPerMeter = m_ntohl(bih->biXPelsPerMeter);
+ bih->biYPelsPerMeter = m_ntohl(bih->biYPelsPerMeter);
+ bih->biClrUsed = m_ntohl(bih->biClrUsed);
+ bih->biClrImportant = m_ntohl(bih->biClrImportant);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the last reported error.
+ */
+const char* CxImage::GetLastError()
+{
+ return info.szLastError;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImage::DumpSize()
+{
+ uint32_t n;
+ n = sizeof(BITMAPINFOHEADER) + sizeof(CXIMAGEINFO) + GetSize();
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pAlpha){
+ n += 1 + head.biWidth * head.biHeight;
+ } else n++;
+#endif
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (pSelection){
+ n += 1 + head.biWidth * head.biHeight;
+ } else n++;
+#endif
+
+#if CXIMAGE_SUPPORT_LAYERS
+ if (ppLayers){
+ for (int32_t m=0; m<GetNumLayers(); m++){
+ if (GetLayer(m)){
+ n += 1 + GetLayer(m)->DumpSize();
+ }
+ }
+ } else n++;
+#endif
+
+ if (ppFrames){
+ for (int32_t m=0; m<GetNumFrames(); m++){
+ if (GetFrame(m)){
+ n += 1 + GetFrame(m)->DumpSize();
+ }
+ }
+ } else n++;
+
+ return n;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImage::Dump(uint8_t * dst)
+{
+ if (!dst) return 0;
+
+ memcpy(dst,&head,sizeof(BITMAPINFOHEADER));
+ dst += sizeof(BITMAPINFOHEADER);
+
+ memcpy(dst,&info,sizeof(CXIMAGEINFO));
+ dst += sizeof(CXIMAGEINFO);
+
+ memcpy(dst,pDib,GetSize());
+ dst += GetSize();
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pAlpha){
+ memset(dst++, 1, 1);
+ memcpy(dst,pAlpha,head.biWidth * head.biHeight);
+ dst += head.biWidth * head.biHeight;
+ } else {
+ memset(dst++, 0, 1);
+ }
+#endif
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (pSelection){
+ memset(dst++, 1, 1);
+ memcpy(dst,pSelection,head.biWidth * head.biHeight);
+ dst += head.biWidth * head.biHeight;
+ } else {
+ memset(dst++, 0, 1);
+ }
+#endif
+
+#if CXIMAGE_SUPPORT_LAYERS
+ if (ppLayers){
+ memset(dst++, 1, 1);
+ for (int32_t m=0; m<GetNumLayers(); m++){
+ if (GetLayer(m)){
+ dst += GetLayer(m)->Dump(dst);
+ }
+ }
+ } else {
+ memset(dst++, 0, 1);
+ }
+#endif
+
+ if (ppFrames){
+ memset(dst++, 1, 1);
+ for (int32_t m=0; m<GetNumFrames(); m++){
+ if (GetFrame(m)){
+ dst += GetFrame(m)->Dump(dst);
+ }
+ }
+ } else {
+ memset(dst++, 0, 1);
+ }
+
+ return DumpSize();
+}
+////////////////////////////////////////////////////////////////////////////////
+uint32_t CxImage::UnDump(const uint8_t * src)
+{
+ if (!src)
+ return 0;
+ if (!Destroy())
+ return 0;
+ if (!DestroyFrames())
+ return 0;
+
+ uint32_t n = 0;
+
+ memcpy(&head,src,sizeof(BITMAPINFOHEADER));
+ n += sizeof(BITMAPINFOHEADER);
+
+ memcpy(&info,&src[n],sizeof(CXIMAGEINFO));
+ n += sizeof(CXIMAGEINFO);
+
+ if (!Create(head.biWidth, head.biHeight, head.biBitCount, info.dwType))
+ return 0;
+
+ memcpy(pDib,&src[n],GetSize());
+ n += GetSize();
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (src[n++]){
+ if (AlphaCreate()){
+ memcpy(pAlpha, &src[n], head.biWidth * head.biHeight);
+ }
+ n += head.biWidth * head.biHeight;
+ }
+#endif
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (src[n++]){
+ RECT box = info.rSelectionBox;
+ if (SelectionCreate()){
+ info.rSelectionBox = box;
+ memcpy(pSelection, &src[n], head.biWidth * head.biHeight);
+ }
+ n += head.biWidth * head.biHeight;
+ }
+#endif
+
+#if CXIMAGE_SUPPORT_LAYERS
+ if (src[n++]){
+ ppLayers = new CxImage*[info.nNumLayers];
+ for (int32_t m=0; m<GetNumLayers(); m++){
+ ppLayers[m] = new CxImage();
+ n += ppLayers[m]->UnDump(&src[n]);
+ }
+ }
+#endif
+
+ if (src[n++]){
+ ppFrames = new CxImage*[info.nNumFrames];
+ for (int32_t m=0; m<GetNumFrames(); m++){
+ ppFrames[m] = new CxImage();
+ n += ppFrames[m]->UnDump(&src[n]);
+ }
+ }
+
+ return n;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return A.BBCCCDDDD
+ * - A = main version
+ * - BB = main revision
+ * - CCC = minor revision (letter)
+ * - DDDD = experimental revision
+ */
+const float CxImage::GetVersionNumber()
+{
+ return 7.000000000f;
+}
+////////////////////////////////////////////////////////////////////////////////
+const TCHAR* CxImage::GetVersion()
+{
+ static const TCHAR CxImageVersion[] = _T("CxImage 7.0.0");
+ return (CxImageVersion);
+}
+////////////////////////////////////////////////////////////////////////////////
diff --git a/archive/hge/CxImage/ximaint.cpp b/archive/hge/CxImage/ximaint.cpp new file mode 100644 index 0000000..5f93038 --- /dev/null +++ b/archive/hge/CxImage/ximaint.cpp @@ -0,0 +1,1046 @@ +// xImaInt.cpp : interpolation functions
+/* 02/2004 - Branko Brevensek
+ * CxImage version 7.0.0 31/Dec/2010 - Davide Pizzolato - www.xdp.it
+ */
+
+#include "ximage.h"
+#include "ximath.h"
+
+#if CXIMAGE_SUPPORT_INTERPOLATION
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Recalculates coordinates according to specified overflow method.
+ * If pixel (x,y) lies within image, nothing changes.
+ *
+ * \param x, y - coordinates of pixel
+ * \param ofMethod - overflow method
+ *
+ * \return x, y - new coordinates (pixel (x,y) now lies inside image)
+ *
+ * \author ***bd*** 2.2004
+ */
+void CxImage::OverflowCoordinates(int32_t &x, int32_t &y, OverflowMethod const ofMethod)
+{
+ if (IsInside(x,y)) return; //if pixel is within bounds, no change
+ switch (ofMethod) {
+ case OM_REPEAT:
+ //clip coordinates
+ x=max(x,0); x=min(x, head.biWidth-1);
+ y=max(y,0); y=min(y, head.biHeight-1);
+ break;
+ case OM_WRAP:
+ //wrap coordinates
+ x = x % head.biWidth;
+ y = y % head.biHeight;
+ if (x<0) x = head.biWidth + x;
+ if (y<0) y = head.biHeight + y;
+ break;
+ case OM_MIRROR:
+ //mirror pixels near border
+ if (x<0) x=((-x) % head.biWidth);
+ else if (x>=head.biWidth) x=head.biWidth-(x % head.biWidth + 1);
+ if (y<0) y=((-y) % head.biHeight);
+ else if (y>=head.biHeight) y=head.biHeight-(y % head.biHeight + 1);
+ break;
+ default:
+ return;
+ }//switch
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * See OverflowCoordinates for integer version
+ * \author ***bd*** 2.2004
+ */
+void CxImage::OverflowCoordinates(float &x, float &y, OverflowMethod const ofMethod)
+{
+ if (x>=0 && x<head.biWidth && y>=0 && y<head.biHeight) return; //if pixel is within bounds, no change
+ switch (ofMethod) {
+ case OM_REPEAT:
+ //clip coordinates
+ x=max(x,0); x=min(x, head.biWidth-1);
+ y=max(y,0); y=min(y, head.biHeight-1);
+ break;
+ case OM_WRAP:
+ //wrap coordinates
+ x = (float)fmod(x, (float) head.biWidth);
+ y = (float)fmod(y, (float) head.biHeight);
+ if (x<0) x = head.biWidth + x;
+ if (y<0) y = head.biHeight + y;
+ break;
+ case OM_MIRROR:
+ //mirror pixels near border
+ if (x<0) x=(float)fmod(-x, (float) head.biWidth);
+ else if (x>=head.biWidth) x=head.biWidth-((float)fmod(x, (float) head.biWidth) + 1);
+ if (y<0) y=(float)fmod(-y, (float) head.biHeight);
+ else if (y>=head.biHeight) y=head.biHeight-((float)fmod(y, (float) head.biHeight) + 1);
+ break;
+ default:
+ return;
+ }//switch
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Method return pixel color. Different methods are implemented for out of bounds pixels.
+ * If an image has alpha channel, alpha value is returned in .RGBReserved.
+ *
+ * \param x,y : pixel coordinates
+ * \param ofMethod : out-of-bounds method:
+ * - OF_WRAP - wrap over to pixels on other side of the image
+ * - OF_REPEAT - repeat last pixel on the edge
+ * - OF_COLOR - return input value of color
+ * - OF_BACKGROUND - return background color (if not set, return input color)
+ * - OF_TRANSPARENT - return transparent pixel
+ *
+ * \param rplColor : input color (returned for out-of-bound coordinates in OF_COLOR mode and if other mode is not applicable)
+ *
+ * \return color : color of pixel
+ * \author ***bd*** 2.2004
+ */
+RGBQUAD CxImage::GetPixelColorWithOverflow(int32_t x, int32_t y, OverflowMethod const ofMethod, RGBQUAD* const rplColor)
+{
+ RGBQUAD color; //color to return
+ if ((!IsInside(x,y)) || pDib==NULL) { //is pixel within bouns?:
+ //pixel is out of bounds or no DIB
+ if (rplColor!=NULL)
+ color=*rplColor;
+ else {
+ color.rgbRed=color.rgbGreen=color.rgbBlue=255; color.rgbReserved=0; //default replacement colour: white transparent
+ }//if
+ if (pDib==NULL) return color;
+ //pixel is out of bounds:
+ switch (ofMethod) {
+ case OM_TRANSPARENT:
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) {
+ //alpha transparency is supported and image has alpha layer
+ color.rgbReserved=0;
+ } else {
+#endif //CXIMAGE_SUPPORT_ALPHA
+ //no alpha transparency
+ if (GetTransIndex()>=0) {
+ color=GetTransColor(); //single color transparency enabled (return transparent color)
+ }//if
+#if CXIMAGE_SUPPORT_ALPHA
+ }//if
+#endif //CXIMAGE_SUPPORT_ALPHA
+ return color;
+ case OM_BACKGROUND:
+ //return background color (if it exists, otherwise input value)
+ if (info.nBkgndIndex >= 0) {
+ if (head.biBitCount<24) color = GetPaletteColor((uint8_t)info.nBkgndIndex);
+ else color = info.nBkgndColor;
+ }//if
+ return color;
+ case OM_REPEAT:
+ case OM_WRAP:
+ case OM_MIRROR:
+ OverflowCoordinates(x,y,ofMethod);
+ break;
+ default:
+ //simply return replacement color (OM_COLOR and others)
+ return color;
+ }//switch
+ }//if
+ //just return specified pixel (it's within bounds)
+ return BlindGetPixelColor(x,y);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * This method reconstructs image according to chosen interpolation method and then returns pixel (x,y).
+ * (x,y) can lie between actual image pixels. If (x,y) lies outside of image, method returns value
+ * according to overflow method.
+ * This method is very useful for geometrical image transformations, where destination pixel
+ * can often assume color value lying between source pixels.
+ *
+ * \param (x,y) - coordinates of pixel to return
+ * GPCI method recreates "analogue" image back from digital data, so x and y
+ * are float values and color value of point (1.1,1) will generally not be same
+ * as (1,1). Center of first pixel is at (0,0) and center of pixel right to it is (1,0).
+ * (0.5,0) is half way between these two pixels.
+ * \param inMethod - interpolation (reconstruction) method (kernel) to use:
+ * - IM_NEAREST_NEIGHBOUR - returns colour of nearest lying pixel (causes stairy look of
+ * processed images)
+ * - IM_BILINEAR - interpolates colour from four neighbouring pixels (softens image a bit)
+ * - IM_BICUBIC - interpolates from 16 neighbouring pixels (can produce "halo" artifacts)
+ * - IM_BICUBIC2 - interpolates from 16 neighbouring pixels (perhaps a bit less halo artifacts
+ than IM_BICUBIC)
+ * - IM_BSPLINE - interpolates from 16 neighbouring pixels (softens image, washes colours)
+ * (As far as I know, image should be prefiltered for this method to give
+ * good results... some other time :) )
+ * This method uses bicubic interpolation kernel from CXImage 5.99a and older
+ * versions.
+ * - IM_LANCZOS - interpolates from 12*12 pixels (slow, ringing artifacts)
+ *
+ * \param ofMethod - overflow method (see comments at GetPixelColorWithOverflow)
+ * \param rplColor - pointer to color used for out of borders pixels in OM_COLOR mode
+ * (and other modes if colour can't calculated in a specified way)
+ *
+ * \return interpolated color value (including interpolated alpha value, if image has alpha layer)
+ *
+ * \author ***bd*** 2.2004
+ */
+RGBQUAD CxImage::GetPixelColorInterpolated(
+ float x,float y,
+ InterpolationMethod const inMethod,
+ OverflowMethod const ofMethod,
+ RGBQUAD* const rplColor)
+{
+ //calculate nearest pixel
+ int32_t xi=(int32_t)(x); if (x<0) xi--; //these replace (incredibly slow) floor (Visual c++ 2003, AMD Athlon)
+ int32_t yi=(int32_t)(y); if (y<0) yi--;
+ RGBQUAD color; //calculated colour
+
+ switch (inMethod) {
+ case IM_NEAREST_NEIGHBOUR:
+ return GetPixelColorWithOverflow((int32_t)(x+0.5f), (int32_t)(y+0.5f), ofMethod, rplColor);
+ default: {
+ //IM_BILINEAR: bilinear interpolation
+ if (xi<-1 || xi>=head.biWidth || yi<-1 || yi>=head.biHeight) { //all 4 points are outside bounds?:
+ switch (ofMethod) {
+ case OM_COLOR: case OM_TRANSPARENT: case OM_BACKGROUND:
+ //we don't need to interpolate anything with all points outside in this case
+ return GetPixelColorWithOverflow(-999, -999, ofMethod, rplColor);
+ default:
+ //recalculate coordinates and use faster method later on
+ OverflowCoordinates(x,y,ofMethod);
+ xi=(int32_t)(x); if (x<0) xi--; //x and/or y have changed ... recalculate xi and yi
+ yi=(int32_t)(y); if (y<0) yi--;
+ }//switch
+ }//if
+ //get four neighbouring pixels
+ if ((xi+1)<head.biWidth && xi>=0 && (yi+1)<head.biHeight && yi>=0 && head.biClrUsed==0) {
+ //all pixels are inside RGB24 image... optimize reading (and use fixed point arithmetic)
+ uint16_t wt1=(uint16_t)((x-xi)*256.0f), wt2=(uint16_t)((y-yi)*256.0f);
+ uint16_t wd=wt1*wt2>>8;
+ uint16_t wb=wt1-wd;
+ uint16_t wc=wt2-wd;
+ uint16_t wa=256-wt1-wc;
+ uint16_t wrr,wgg,wbb;
+ uint8_t *pxptr=(uint8_t*)info.pImage+yi*info.dwEffWidth+xi*3;
+ wbb=wa*(*pxptr++); wgg=wa*(*pxptr++); wrr=wa*(*pxptr++);
+ wbb+=wb*(*pxptr++); wgg+=wb*(*pxptr++); wrr+=wb*(*pxptr);
+ pxptr+=(info.dwEffWidth-5); //move to next row
+ wbb+=wc*(*pxptr++); wgg+=wc*(*pxptr++); wrr+=wc*(*pxptr++);
+ wbb+=wd*(*pxptr++); wgg+=wd*(*pxptr++); wrr+=wd*(*pxptr);
+ color.rgbRed=(uint8_t) (wrr>>8); color.rgbGreen=(uint8_t) (wgg>>8); color.rgbBlue=(uint8_t) (wbb>>8);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pAlpha) {
+ uint16_t waa;
+ //image has alpha layer... we have to do the same for alpha data
+ pxptr=AlphaGetPointer(xi,yi); //pointer to first byte
+ waa=wa*(*pxptr++); waa+=wb*(*pxptr); //first two pixels
+ pxptr+=(head.biWidth-1); //move to next row
+ waa+=wc*(*pxptr++); waa+=wd*(*pxptr); //and second row pixels
+ color.rgbReserved=(uint8_t) (waa>>8);
+ } else
+#endif
+ { //Alpha not supported or no alpha at all
+ color.rgbReserved = 0;
+ }
+ return color;
+ } else {
+ //default (slower) way to get pixels (not RGB24 or some pixels out of borders)
+ float t1=x-xi, t2=y-yi;
+ float d=t1*t2;
+ float b=t1-d;
+ float c=t2-d;
+ float a=1-t1-c;
+ RGBQUAD rgb11,rgb21,rgb12,rgb22;
+ rgb11=GetPixelColorWithOverflow(xi, yi, ofMethod, rplColor);
+ rgb21=GetPixelColorWithOverflow(xi+1, yi, ofMethod, rplColor);
+ rgb12=GetPixelColorWithOverflow(xi, yi+1, ofMethod, rplColor);
+ rgb22=GetPixelColorWithOverflow(xi+1, yi+1, ofMethod, rplColor);
+ //calculate linear interpolation
+ color.rgbRed=(uint8_t) (a*rgb11.rgbRed+b*rgb21.rgbRed+c*rgb12.rgbRed+d*rgb22.rgbRed);
+ color.rgbGreen=(uint8_t) (a*rgb11.rgbGreen+b*rgb21.rgbGreen+c*rgb12.rgbGreen+d*rgb22.rgbGreen);
+ color.rgbBlue=(uint8_t) (a*rgb11.rgbBlue+b*rgb21.rgbBlue+c*rgb12.rgbBlue+d*rgb22.rgbBlue);
+#if CXIMAGE_SUPPORT_ALPHA
+ color.rgbReserved=(uint8_t) (a*rgb11.rgbReserved+b*rgb21.rgbReserved+c*rgb12.rgbReserved+d*rgb22.rgbReserved);
+#else
+ color.rgbReserved = 0;
+#endif
+ return color;
+ }//if
+ }//default
+ case IM_BICUBIC:
+ case IM_BICUBIC2:
+ case IM_BSPLINE:
+ case IM_BOX:
+ case IM_HERMITE:
+ case IM_HAMMING:
+ case IM_SINC:
+ case IM_BLACKMAN:
+ case IM_BESSEL:
+ case IM_GAUSSIAN:
+ case IM_QUADRATIC:
+ case IM_MITCHELL:
+ case IM_CATROM:
+ case IM_HANNING:
+ case IM_POWER:
+ //bicubic interpolation(s)
+ if (((xi+2)<0) || ((xi-1)>=head.biWidth) || ((yi+2)<0) || ((yi-1)>=head.biHeight)) { //all points are outside bounds?:
+ switch (ofMethod) {
+ case OM_COLOR: case OM_TRANSPARENT: case OM_BACKGROUND:
+ //we don't need to interpolate anything with all points outside in this case
+ return GetPixelColorWithOverflow(-999, -999, ofMethod, rplColor);
+ break;
+ default:
+ //recalculate coordinates and use faster method later on
+ OverflowCoordinates(x,y,ofMethod);
+ xi=(int32_t)(x); if (x<0) xi--; //x and/or y have changed ... recalculate xi and yi
+ yi=(int32_t)(y); if (y<0) yi--;
+ }//switch
+ }//if
+
+ //some variables needed from here on
+ int32_t xii,yii; //x any y integer indexes for loops
+ float kernel, kernelyc; //kernel cache
+ float kernelx[12], kernely[4]; //precalculated kernel values
+ float rr,gg,bb,aa; //accumulated color values
+ //calculate multiplication factors for all pixels
+ int32_t i;
+ switch (inMethod) {
+ case IM_BICUBIC:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelCubic((float)(xi+i-1-x));
+ kernely[i]=KernelCubic((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_BICUBIC2:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelGeneralizedCubic((float)(xi+i-1-x), -0.5);
+ kernely[i]=KernelGeneralizedCubic((float)(yi+i-1-y), -0.5);
+ }//for i
+ break;
+ case IM_BSPLINE:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelBSpline((float)(xi+i-1-x));
+ kernely[i]=KernelBSpline((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_BOX:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelBox((float)(xi+i-1-x));
+ kernely[i]=KernelBox((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_HERMITE:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelHermite((float)(xi+i-1-x));
+ kernely[i]=KernelHermite((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_HAMMING:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelHamming((float)(xi+i-1-x));
+ kernely[i]=KernelHamming((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_SINC:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelSinc((float)(xi+i-1-x));
+ kernely[i]=KernelSinc((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_BLACKMAN:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelBlackman((float)(xi+i-1-x));
+ kernely[i]=KernelBlackman((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_BESSEL:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelBessel((float)(xi+i-1-x));
+ kernely[i]=KernelBessel((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_GAUSSIAN:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelGaussian((float)(xi+i-1-x));
+ kernely[i]=KernelGaussian((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_QUADRATIC:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelQuadratic((float)(xi+i-1-x));
+ kernely[i]=KernelQuadratic((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_MITCHELL:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelMitchell((float)(xi+i-1-x));
+ kernely[i]=KernelMitchell((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_CATROM:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelCatrom((float)(xi+i-1-x));
+ kernely[i]=KernelCatrom((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_HANNING:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelHanning((float)(xi+i-1-x));
+ kernely[i]=KernelHanning((float)(yi+i-1-y));
+ }//for i
+ break;
+ case IM_POWER:
+ for (i=0; i<4; i++) {
+ kernelx[i]=KernelPower((float)(xi+i-1-x));
+ kernely[i]=KernelPower((float)(yi+i-1-y));
+ }//for i
+ break; + default:break;
+ }//switch
+ rr=gg=bb=aa=0;
+ if (((xi+2)<head.biWidth) && xi>=1 && ((yi+2)<head.biHeight) && (yi>=1) && !IsIndexed()) {
+ //optimized interpolation (faster pixel reads) for RGB24 images with all pixels inside bounds
+ for (yii=yi-1; yii<yi+3; yii++) {
+ uint8_t *pxptr=(uint8_t *)BlindGetPixelPointer(xi-1, yii); //calculate pointer to first byte in row
+ kernelyc=kernely[yii-(yi-1)];
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) {
+ //alpha is supported and valid (optimized bicubic int32_t. for image with alpha)
+ uint8_t *pxptra=AlphaGetPointer(xi-1, yii);
+ kernel=kernelyc*kernelx[0];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++); aa+=kernel*(*pxptra++);
+ kernel=kernelyc*kernelx[1];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++); aa+=kernel*(*pxptra++);
+ kernel=kernelyc*kernelx[2];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++); aa+=kernel*(*pxptra++);
+ kernel=kernelyc*kernelx[3];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr); aa+=kernel*(*pxptra);
+ } else
+#endif
+ //alpha not supported or valid (optimized bicubic int32_t. for no alpha channel)
+ {
+ kernel=kernelyc*kernelx[0];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++);
+ kernel=kernelyc*kernelx[1];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++);
+ kernel=kernelyc*kernelx[2];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++);
+ kernel=kernelyc*kernelx[3];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr);
+ }
+ }//yii
+ } else {
+ //slower more flexible interpolation for border pixels and paletted images
+ RGBQUAD rgbs;
+ for (yii=yi-1; yii<yi+3; yii++) {
+ kernelyc=kernely[yii-(yi-1)];
+ for (xii=xi-1; xii<xi+3; xii++) {
+ kernel=kernelyc*kernelx[xii-(xi-1)];
+ rgbs=GetPixelColorWithOverflow(xii, yii, ofMethod, rplColor);
+ rr+=kernel*rgbs.rgbRed;
+ gg+=kernel*rgbs.rgbGreen;
+ bb+=kernel*rgbs.rgbBlue;
+#if CXIMAGE_SUPPORT_ALPHA
+ aa+=kernel*rgbs.rgbReserved;
+#endif
+ }//xii
+ }//yii
+ }//if
+ //for all colors, clip to 0..255 and assign to RGBQUAD
+ if (rr>255) rr=255; if (rr<0) rr=0; color.rgbRed=(uint8_t) rr;
+ if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(uint8_t) gg;
+ if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(uint8_t) bb;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(uint8_t) aa;
+#else
+ color.rgbReserved = 0;
+#endif
+ return color;
+ case IM_LANCZOS:
+ //lanczos window (16*16) sinc interpolation
+ if (((xi+6)<0) || ((xi-5)>=head.biWidth) || ((yi+6)<0) || ((yi-5)>=head.biHeight)) {
+ //all points are outside bounds
+ switch (ofMethod) {
+ case OM_COLOR: case OM_TRANSPARENT: case OM_BACKGROUND:
+ //we don't need to interpolate anything with all points outside in this case
+ return GetPixelColorWithOverflow(-999, -999, ofMethod, rplColor);
+ break;
+ default:
+ //recalculate coordinates and use faster method later on
+ OverflowCoordinates(x,y,ofMethod);
+ xi=(int32_t)(x); if (x<0) xi--; //x and/or y have changed ... recalculate xi and yi
+ yi=(int32_t)(y); if (y<0) yi--;
+ }//switch
+ }//if
+
+ for (xii=xi-5; xii<xi+7; xii++) kernelx[xii-(xi-5)]=KernelLanczosSinc((float)(xii-x), 6.0f);
+ rr=gg=bb=aa=0;
+
+ if (((xi+6)<head.biWidth) && ((xi-5)>=0) && ((yi+6)<head.biHeight) && ((yi-5)>=0) && !IsIndexed()) {
+ //optimized interpolation (faster pixel reads) for RGB24 images with all pixels inside bounds
+ for (yii=yi-5; yii<yi+7; yii++) {
+ uint8_t *pxptr=(uint8_t *)BlindGetPixelPointer(xi-5, yii); //calculate pointer to first byte in row
+ kernelyc=KernelLanczosSinc((float)(yii-y),6.0f);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) {
+ //alpha is supported and valid
+ uint8_t *pxptra=AlphaGetPointer(xi-1, yii);
+ for (xii=0; xii<12; xii++) {
+ kernel=kernelyc*kernelx[xii];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++); aa+=kernel*(*pxptra++);
+ }//for xii
+ } else
+#endif
+ //alpha not supported or valid
+ {
+ for (xii=0; xii<12; xii++) {
+ kernel=kernelyc*kernelx[xii];
+ bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++);
+ }//for xii
+ }
+ }//yii
+ } else {
+ //slower more flexible interpolation for border pixels and paletted images
+ RGBQUAD rgbs;
+ for (yii=yi-5; yii<yi+7; yii++) {
+ kernelyc=KernelLanczosSinc((float)(yii-y),6.0f);
+ for (xii=xi-5; xii<xi+7; xii++) {
+ kernel=kernelyc*kernelx[xii-(xi-5)];
+ rgbs=GetPixelColorWithOverflow(xii, yii, ofMethod, rplColor);
+ rr+=kernel*rgbs.rgbRed;
+ gg+=kernel*rgbs.rgbGreen;
+ bb+=kernel*rgbs.rgbBlue;
+#if CXIMAGE_SUPPORT_ALPHA
+ aa+=kernel*rgbs.rgbReserved;
+#endif
+ }//xii
+ }//yii
+ }//if
+ //for all colors, clip to 0..255 and assign to RGBQUAD
+ if (rr>255) rr=255; if (rr<0) rr=0; color.rgbRed=(uint8_t) rr;
+ if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(uint8_t) gg;
+ if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(uint8_t) bb;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(uint8_t) aa;
+#else
+ color.rgbReserved = 0;
+#endif
+ return color;
+ }//switch
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Helper function for GetAreaColorInterpolated.
+ * Adds 'surf' portion of image pixel with color 'color' to (rr,gg,bb,aa).
+ */
+void CxImage::AddAveragingCont(RGBQUAD const &color, float const surf, float &rr, float &gg, float &bb, float &aa)
+{
+ rr+=color.rgbRed*surf;
+ gg+=color.rgbGreen*surf;
+ bb+=color.rgbBlue*surf;
+#if CXIMAGE_SUPPORT_ALPHA
+ aa+=color.rgbReserved*surf;
+#endif
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * This method is similar to GetPixelColorInterpolated, but this method also properly handles
+ * subsampling.
+ * If you need to sample original image with interval of more than 1 pixel (as when shrinking an image),
+ * you should use this method instead of GetPixelColorInterpolated or aliasing will occur.
+ * When area width and height are both less than pixel, this method gets pixel color by interpolating
+ * color of frame center with selected (inMethod) interpolation by calling GetPixelColorInterpolated.
+ * If width and height are more than 1, method calculates color by averaging color of pixels within area.
+ * Interpolation method is not used in this case. Pixel color is interpolated by averaging instead.
+ * If only one of both is more than 1, method uses combination of interpolation and averaging.
+ * Chosen interpolation method is used, but since it is averaged later on, there is little difference
+ * between IM_BILINEAR (perhaps best for this case) and better methods. IM_NEAREST_NEIGHBOUR again
+ * leads to aliasing artifacts.
+ * This method is a bit slower than GetPixelColorInterpolated and when aliasing is not a problem, you should
+ * simply use the later.
+ *
+ * \param xc, yc - center of (rectangular) area
+ * \param w, h - width and height of area
+ * \param inMethod - interpolation method that is used, when interpolation is used (see above)
+ * \param ofMethod - overflow method used when retrieving individual pixel colors
+ * \param rplColor - replacement colour to use, in OM_COLOR
+ *
+ * \author ***bd*** 2.2004
+ */
+RGBQUAD CxImage::GetAreaColorInterpolated(
+ float const xc, float const yc, float const w, float const h,
+ InterpolationMethod const inMethod,
+ OverflowMethod const ofMethod,
+ RGBQUAD* const rplColor)
+{
+ RGBQUAD color; //calculated colour
+
+ if (h<=1 && w<=1) {
+ //both width and height are less than one... we will use interpolation of center point
+ return GetPixelColorInterpolated(xc, yc, inMethod, ofMethod, rplColor);
+ } else {
+ //area is wider and/or taller than one pixel:
+ CxRect2 area(xc-w/2.0f, yc-h/2.0f, xc+w/2.0f, yc+h/2.0f); //area
+ int32_t xi1=(int32_t)(area.botLeft.x+0.49999999f); //low x
+ int32_t yi1=(int32_t)(area.botLeft.y+0.49999999f); //low y
+
+
+ int32_t xi2=(int32_t)(area.topRight.x+0.5f); //top x
+ int32_t yi2=(int32_t)(area.topRight.y+0.5f); //top y (for loops)
+
+ float rr,gg,bb,aa; //red, green, blue and alpha components
+ rr=gg=bb=aa=0;
+ int32_t x,y; //loop counters
+ float s=0; //surface of all pixels
+ float cps; //surface of current crosssection
+ if (h>1 && w>1) {
+ //width and height of area are greater than one pixel, so we can employ "ordinary" averaging
+ CxRect2 intBL, intTR; //bottom left and top right intersection
+ intBL=area.CrossSection(CxRect2(((float)xi1)-0.5f, ((float)yi1)-0.5f, ((float)xi1)+0.5f, ((float)yi1)+0.5f));
+ intTR=area.CrossSection(CxRect2(((float)xi2)-0.5f, ((float)yi2)-0.5f, ((float)xi2)+0.5f, ((float)yi2)+0.5f));
+ float wBL, wTR, hBL, hTR;
+ wBL=intBL.Width(); //width of bottom left pixel-area intersection
+ hBL=intBL.Height(); //height of bottom left...
+ wTR=intTR.Width(); //width of top right...
+ hTR=intTR.Height(); //height of top right...
+
+ AddAveragingCont(GetPixelColorWithOverflow(xi1,yi1,ofMethod,rplColor), wBL*hBL, rr, gg, bb, aa); //bottom left pixel
+ AddAveragingCont(GetPixelColorWithOverflow(xi2,yi1,ofMethod,rplColor), wTR*hBL, rr, gg, bb, aa); //bottom right pixel
+ AddAveragingCont(GetPixelColorWithOverflow(xi1,yi2,ofMethod,rplColor), wBL*hTR, rr, gg, bb, aa); //top left pixel
+ AddAveragingCont(GetPixelColorWithOverflow(xi2,yi2,ofMethod,rplColor), wTR*hTR, rr, gg, bb, aa); //top right pixel
+ //bottom and top row
+ for (x=xi1+1; x<xi2; x++) {
+ AddAveragingCont(GetPixelColorWithOverflow(x,yi1,ofMethod,rplColor), hBL, rr, gg, bb, aa); //bottom row
+ AddAveragingCont(GetPixelColorWithOverflow(x,yi2,ofMethod,rplColor), hTR, rr, gg, bb, aa); //top row
+ }
+ //leftmost and rightmost column
+ for (y=yi1+1; y<yi2; y++) {
+ AddAveragingCont(GetPixelColorWithOverflow(xi1,y,ofMethod,rplColor), wBL, rr, gg, bb, aa); //left column
+ AddAveragingCont(GetPixelColorWithOverflow(xi2,y,ofMethod,rplColor), wTR, rr, gg, bb, aa); //right column
+ }
+ for (y=yi1+1; y<yi2; y++) {
+ for (x=xi1+1; x<xi2; x++) {
+ color=GetPixelColorWithOverflow(x,y,ofMethod,rplColor);
+ rr+=color.rgbRed;
+ gg+=color.rgbGreen;
+ bb+=color.rgbBlue;
+#if CXIMAGE_SUPPORT_ALPHA
+ aa+=color.rgbReserved;
+#endif
+ }//for x
+ }//for y
+ } else {
+ //width or height greater than one:
+ CxRect2 intersect; //intersection with current pixel
+ CxPoint2 center;
+ for (y=yi1; y<=yi2; y++) {
+ for (x=xi1; x<=xi2; x++) {
+ intersect=area.CrossSection(CxRect2(((float)x)-0.5f, ((float)y)-0.5f, ((float)x)+0.5f, ((float)y)+0.5f));
+ center=intersect.Center();
+ color=GetPixelColorInterpolated(center.x, center.y, inMethod, ofMethod, rplColor);
+ cps=intersect.Surface();
+ rr+=color.rgbRed*cps;
+ gg+=color.rgbGreen*cps;
+ bb+=color.rgbBlue*cps;
+#if CXIMAGE_SUPPORT_ALPHA
+ aa+=color.rgbReserved*cps;
+#endif
+ }//for x
+ }//for y
+ }//if
+
+ s=area.Surface();
+ rr/=s; gg/=s; bb/=s; aa/=s;
+ if (rr>255) rr=255; if (rr<0) rr=0; color.rgbRed=(uint8_t) rr;
+ if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(uint8_t) gg;
+ if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(uint8_t) bb;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(uint8_t) aa;
+#else
+ color.rgbReserved = 0;
+#endif
+ }//if
+ return color;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelBSpline(const float x)
+{
+ if (x>2.0f) return 0.0f;
+ // thanks to Kristian Kratzenstein
+ float a, b, c, d;
+ float xm1 = x - 1.0f; // Was calculatet anyway cause the "if((x-1.0f) < 0)"
+ float xp1 = x + 1.0f;
+ float xp2 = x + 2.0f;
+
+ if ((xp2) <= 0.0f) a = 0.0f; else a = xp2*xp2*xp2; // Only float, not float -> double -> float
+ if ((xp1) <= 0.0f) b = 0.0f; else b = xp1*xp1*xp1;
+ if (x <= 0) c = 0.0f; else c = x*x*x;
+ if ((xm1) <= 0.0f) d = 0.0f; else d = xm1*xm1*xm1;
+
+ return (0.16666666666666666667f * (a - (4.0f * b) + (6.0f * c) - (4.0f * d)));
+
+ /* equivalent <Vladimír Kloucek>
+ if (x < -2.0)
+ return(0.0f);
+ if (x < -1.0)
+ return((2.0f+x)*(2.0f+x)*(2.0f+x)*0.16666666666666666667f);
+ if (x < 0.0)
+ return((4.0f+x*x*(-6.0f-3.0f*x))*0.16666666666666666667f);
+ if (x < 1.0)
+ return((4.0f+x*x*(-6.0f+3.0f*x))*0.16666666666666666667f);
+ if (x < 2.0)
+ return((2.0f-x)*(2.0f-x)*(2.0f-x)*0.16666666666666666667f);
+ return(0.0f);
+ */
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Bilinear interpolation kernel:
+ \verbatim
+ /
+ | 1-t , if 0 <= t <= 1
+ h(t) = | t+1 , if -1 <= t < 0
+ | 0 , otherwise
+ \
+ \endverbatim
+ * ***bd*** 2.2004
+ */
+float CxImage::KernelLinear(const float t)
+{
+// if (0<=t && t<=1) return 1-t;
+// if (-1<=t && t<0) return 1+t;
+// return 0;
+
+ //<Vladimír Kloucek>
+ if (t < -1.0f)
+ return 0.0f;
+ if (t < 0.0f)
+ return 1.0f+t;
+ if (t < 1.0f)
+ return 1.0f-t;
+ return 0.0f;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Bicubic interpolation kernel (a=-1):
+ \verbatim
+ /
+ | 1-2|t|**2+|t|**3 , if |t| < 1
+ h(t) = | 4-8|t|+5|t|**2-|t|**3 , if 1<=|t|<2
+ | 0 , otherwise
+ \
+ \endverbatim
+ * ***bd*** 2.2004
+ */
+float CxImage::KernelCubic(const float t)
+{
+ float abs_t = (float)fabs(t);
+ float abs_t_sq = abs_t * abs_t;
+ if (abs_t<1) return 1-2*abs_t_sq+abs_t_sq*abs_t;
+ if (abs_t<2) return 4 - 8*abs_t +5*abs_t_sq - abs_t_sq*abs_t;
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Bicubic kernel (for a=-1 it is the same as BicubicKernel):
+ \verbatim
+ /
+ | (a+2)|t|**3 - (a+3)|t|**2 + 1 , |t| <= 1
+ h(t) = | a|t|**3 - 5a|t|**2 + 8a|t| - 4a , 1 < |t| <= 2
+ | 0 , otherwise
+ \
+ \endverbatim
+ * Often used values for a are -1 and -1/2.
+ */
+float CxImage::KernelGeneralizedCubic(const float t, const float a)
+{
+ float abs_t = (float)fabs(t);
+ float abs_t_sq = abs_t * abs_t;
+ if (abs_t<1) return (a+2)*abs_t_sq*abs_t - (a+3)*abs_t_sq + 1;
+ if (abs_t<2) return a*abs_t_sq*abs_t - 5*a*abs_t_sq + 8*a*abs_t - 4*a;
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Lanczos windowed sinc interpolation kernel with radius r.
+ \verbatim
+ /
+ h(t) = | sinc(t)*sinc(t/r) , if |t|<r
+ | 0 , otherwise
+ \
+ \endverbatim
+ * ***bd*** 2.2004
+ */
+float CxImage::KernelLanczosSinc(const float t, const float r)
+{
+ if (fabs(t) > r) return 0;
+ if (t==0) return 1;
+ float pit=PI*t;
+ float pitd=pit/r;
+ return (float)((sin(pit)/pit) * (sin(pitd)/pitd));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelBox(const float x)
+{
+ if (x < -0.5f)
+ return 0.0f;
+ if (x < 0.5f)
+ return 1.0f;
+ return 0.0f;
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelHermite(const float x)
+{
+ if (x < -1.0f)
+ return 0.0f;
+ if (x < 0.0f)
+ return (-2.0f*x-3.0f)*x*x+1.0f;
+ if (x < 1.0f)
+ return (2.0f*x-3.0f)*x*x+1.0f;
+ return 0.0f;
+// if (fabs(x)>1) return 0.0f;
+// return(0.5f+0.5f*(float)cos(PI*x));
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelHanning(const float x)
+{
+ if (fabs(x)>1) return 0.0f;
+ return (0.5f+0.5f*(float)cos(PI*x))*((float)sin(PI*x)/(PI*x));
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelHamming(const float x)
+{
+ if (x < -1.0f)
+ return 0.0f;
+ if (x < 0.0f)
+ return 0.92f*(-2.0f*x-3.0f)*x*x+1.0f;
+ if (x < 1.0f)
+ return 0.92f*(2.0f*x-3.0f)*x*x+1.0f;
+ return 0.0f;
+// if (fabs(x)>1) return 0.0f;
+// return(0.54f+0.46f*(float)cos(PI*x));
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelSinc(const float x)
+{
+ if (x == 0.0)
+ return(1.0);
+ return((float)sin(PI*x)/(PI*x));
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelBlackman(const float x)
+{
+ //if (fabs(x)>1) return 0.0f;
+ return (0.42f+0.5f*(float)cos(PI*x)+0.08f*(float)cos(2.0f*PI*x));
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelBessel_J1(const float x)
+{
+ double p, q;
+
+ register int32_t i;
+
+ static const double
+ Pone[] =
+ {
+ 0.581199354001606143928050809e+21,
+ -0.6672106568924916298020941484e+20,
+ 0.2316433580634002297931815435e+19,
+ -0.3588817569910106050743641413e+17,
+ 0.2908795263834775409737601689e+15,
+ -0.1322983480332126453125473247e+13,
+ 0.3413234182301700539091292655e+10,
+ -0.4695753530642995859767162166e+7,
+ 0.270112271089232341485679099e+4
+ },
+ Qone[] =
+ {
+ 0.11623987080032122878585294e+22,
+ 0.1185770712190320999837113348e+20,
+ 0.6092061398917521746105196863e+17,
+ 0.2081661221307607351240184229e+15,
+ 0.5243710262167649715406728642e+12,
+ 0.1013863514358673989967045588e+10,
+ 0.1501793594998585505921097578e+7,
+ 0.1606931573481487801970916749e+4,
+ 0.1e+1
+ };
+
+ p = Pone[8];
+ q = Qone[8];
+ for (i=7; i >= 0; i--)
+ {
+ p = p*x*x+Pone[i];
+ q = q*x*x+Qone[i];
+ }
+ return (float)(p/q);
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelBessel_P1(const float x)
+{
+ double p, q;
+
+ register int32_t i;
+
+ static const double
+ Pone[] =
+ {
+ 0.352246649133679798341724373e+5,
+ 0.62758845247161281269005675e+5,
+ 0.313539631109159574238669888e+5,
+ 0.49854832060594338434500455e+4,
+ 0.2111529182853962382105718e+3,
+ 0.12571716929145341558495e+1
+ },
+ Qone[] =
+ {
+ 0.352246649133679798068390431e+5,
+ 0.626943469593560511888833731e+5,
+ 0.312404063819041039923015703e+5,
+ 0.4930396490181088979386097e+4,
+ 0.2030775189134759322293574e+3,
+ 0.1e+1
+ };
+
+ p = Pone[5];
+ q = Qone[5];
+ for (i=4; i >= 0; i--)
+ {
+ p = p*(8.0/x)*(8.0/x)+Pone[i];
+ q = q*(8.0/x)*(8.0/x)+Qone[i];
+ }
+ return (float)(p/q);
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelBessel_Q1(const float x)
+{
+ double p, q;
+
+ register int32_t i;
+
+ static const double
+ Pone[] =
+ {
+ 0.3511751914303552822533318e+3,
+ 0.7210391804904475039280863e+3,
+ 0.4259873011654442389886993e+3,
+ 0.831898957673850827325226e+2,
+ 0.45681716295512267064405e+1,
+ 0.3532840052740123642735e-1
+ },
+ Qone[] =
+ {
+ 0.74917374171809127714519505e+4,
+ 0.154141773392650970499848051e+5,
+ 0.91522317015169922705904727e+4,
+ 0.18111867005523513506724158e+4,
+ 0.1038187585462133728776636e+3,
+ 0.1e+1
+ };
+
+ p = Pone[5];
+ q = Qone[5];
+ for (i=4; i >= 0; i--)
+ {
+ p = p*(8.0/x)*(8.0/x)+Pone[i];
+ q = q*(8.0/x)*(8.0/x)+Qone[i];
+ }
+ return (float)(p/q);
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelBessel_Order1(float x)
+{
+ float p, q;
+
+ if (x == 0.0)
+ return (0.0f);
+ p = x;
+ if (x < 0.0)
+ x=(-x);
+ if (x < 8.0)
+ return(p*KernelBessel_J1(x));
+ q = (float)sqrt(2.0f/(PI*x))*(float)(KernelBessel_P1(x)*(1.0f/sqrt(2.0f)*(sin(x)-cos(x)))-8.0f/x*KernelBessel_Q1(x)*
+ (-1.0f/sqrt(2.0f)*(sin(x)+cos(x))));
+ if (p < 0.0f)
+ q = (-q);
+ return (q);
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelBessel(const float x)
+{
+ if (x == 0.0f)
+ return(PI/4.0f);
+ return(KernelBessel_Order1(PI*x)/(2.0f*x));
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelGaussian(const float x)
+{
+ return (float)(exp(-2.0f*x*x)*0.79788456080287f/*sqrt(2.0f/PI)*/);
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelQuadratic(const float x)
+{
+ if (x < -1.5f)
+ return(0.0f);
+ if (x < -0.5f)
+ return(0.5f*(x+1.5f)*(x+1.5f));
+ if (x < 0.5f)
+ return(0.75f-x*x);
+ if (x < 1.5f)
+ return(0.5f*(x-1.5f)*(x-1.5f));
+ return(0.0f);
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelMitchell(const float x)
+{
+#define KM_B (1.0f/3.0f)
+#define KM_C (1.0f/3.0f)
+#define KM_P0 (( 6.0f - 2.0f * KM_B ) / 6.0f)
+#define KM_P2 ((-18.0f + 12.0f * KM_B + 6.0f * KM_C) / 6.0f)
+#define KM_P3 (( 12.0f - 9.0f * KM_B - 6.0f * KM_C) / 6.0f)
+#define KM_Q0 (( 8.0f * KM_B + 24.0f * KM_C) / 6.0f)
+#define KM_Q1 ((-12.0f * KM_B - 48.0f * KM_C) / 6.0f)
+#define KM_Q2 (( 6.0f * KM_B + 30.0f * KM_C) / 6.0f)
+#define KM_Q3 (( -1.0f * KM_B - 6.0f * KM_C) / 6.0f)
+
+ if (x < -2.0)
+ return(0.0f);
+ if (x < -1.0)
+ return(KM_Q0-x*(KM_Q1-x*(KM_Q2-x*KM_Q3)));
+ if (x < 0.0f)
+ return(KM_P0+x*x*(KM_P2-x*KM_P3));
+ if (x < 1.0f)
+ return(KM_P0+x*x*(KM_P2+x*KM_P3));
+ if (x < 2.0f)
+ return(KM_Q0+x*(KM_Q1+x*(KM_Q2+x*KM_Q3)));
+ return(0.0f);
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelCatrom(const float x)
+{
+ if (x < -2.0)
+ return(0.0f);
+ if (x < -1.0)
+ return(0.5f*(4.0f+x*(8.0f+x*(5.0f+x))));
+ if (x < 0.0)
+ return(0.5f*(2.0f+x*x*(-5.0f-3.0f*x)));
+ if (x < 1.0)
+ return(0.5f*(2.0f+x*x*(-5.0f+3.0f*x)));
+ if (x < 2.0)
+ return(0.5f*(4.0f+x*(-8.0f+x*(5.0f-x))));
+ return(0.0f);
+}
+////////////////////////////////////////////////////////////////////////////////
+float CxImage::KernelPower(const float x, const float a)
+{
+ if (fabs(x)>1) return 0.0f;
+ return (1.0f - (float)fabs(pow(x,a)));
+}
+////////////////////////////////////////////////////////////////////////////////
+
+#endif
diff --git a/archive/hge/CxImage/ximaiter.h b/archive/hge/CxImage/ximaiter.h new file mode 100644 index 0000000..2371d28 --- /dev/null +++ b/archive/hge/CxImage/ximaiter.h @@ -0,0 +1,253 @@ +/*
+ * File: ImaIter.h
+ * Purpose: Declaration of the Platform Independent Image Base Class
+ * Author: Alejandro Aguilar Sierra
+ * Created: 1995
+ * Copyright: (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>
+ *
+ * 07/08/2001 Davide Pizzolato - www.xdp.it
+ * - removed slow loops
+ * - added safe checks
+ *
+ * Permission is given by the author to freely redistribute and include
+ * this code in any program as int32_t as this credit is given where due.
+ *
+ * COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+ * OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+ * THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+ * OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+ * CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+ * THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+ * SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+ * PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+ * THIS DISCLAIMER.
+ *
+ * Use at your own risk!
+ * ==========================================================
+ */
+
+#if !defined(__ImaIter_h)
+#define __ImaIter_h
+
+#include "ximage.h"
+#include "ximadef.h"
+
+class CImageIterator
+{
+friend class CxImage;
+protected:
+ int32_t Itx, Ity; // Counters
+ int32_t Stepx, Stepy;
+ uint8_t* IterImage; // Image pointer
+ CxImage *ima;
+public:
+ // Constructors
+ CImageIterator ( void );
+ CImageIterator ( CxImage *image );
+ operator CxImage* ();
+
+ // Iterators
+ BOOL ItOK ();
+ void Reset ();
+ void Upset ();
+ void SetRow(uint8_t *buf, int32_t n);
+ void GetRow(uint8_t *buf, int32_t n);
+ uint8_t GetByte( ) { return IterImage[Itx]; }
+ void SetByte(uint8_t b) { IterImage[Itx] = b; }
+ uint8_t* GetRow(void);
+ uint8_t* GetRow(int32_t n);
+ BOOL NextRow();
+ BOOL PrevRow();
+ BOOL NextByte();
+ BOOL PrevByte();
+
+ void SetSteps(int32_t x, int32_t y=0) { Stepx = x; Stepy = y; }
+ void GetSteps(int32_t *x, int32_t *y) { *x = Stepx; *y = Stepy; }
+ BOOL NextStep();
+ BOOL PrevStep();
+
+ void SetY(int32_t y); /* AD - for interlace */
+ int32_t GetY() {return Ity;}
+ BOOL GetCol(uint8_t* pCol, uint32_t x);
+ BOOL SetCol(uint8_t* pCol, uint32_t x);
+};
+
+/////////////////////////////////////////////////////////////////////
+inline
+CImageIterator::CImageIterator(void)
+{
+ ima = 0;
+ IterImage = 0;
+ Itx = Ity = 0;
+ Stepx = Stepy = 0;
+}
+/////////////////////////////////////////////////////////////////////
+inline
+CImageIterator::CImageIterator(CxImage *imageImpl): ima(imageImpl)
+{
+ if (ima) IterImage = ima->GetBits();
+ Itx = Ity = 0;
+ Stepx = Stepy = 0;
+}
+/////////////////////////////////////////////////////////////////////
+inline
+CImageIterator::operator CxImage* ()
+{
+ return ima;
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::ItOK ()
+{
+ if (ima) return ima->IsInside(Itx, Ity);
+ else return FALSE;
+}
+/////////////////////////////////////////////////////////////////////
+inline void CImageIterator::Reset()
+{
+ if (ima) IterImage = ima->GetBits();
+ else IterImage=0;
+ Itx = Ity = 0;
+}
+/////////////////////////////////////////////////////////////////////
+inline void CImageIterator::Upset()
+{
+ Itx = 0;
+ Ity = ima->GetHeight()-1;
+ IterImage = ima->GetBits() + ima->GetEffWidth()*(ima->GetHeight()-1);
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::NextRow()
+{
+ if (++Ity >= (int32_t)ima->GetHeight()) return 0;
+ IterImage += ima->GetEffWidth();
+ return 1;
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::PrevRow()
+{
+ if (--Ity < 0) return 0;
+ IterImage -= ima->GetEffWidth();
+ return 1;
+}
+/* AD - for interlace */
+inline void CImageIterator::SetY(int32_t y)
+{
+ if ((y < 0) || (y > (int32_t)ima->GetHeight())) return;
+ Ity = y;
+ IterImage = ima->GetBits() + ima->GetEffWidth()*y;
+}
+/////////////////////////////////////////////////////////////////////
+inline void CImageIterator::SetRow(uint8_t *buf, int32_t n)
+{
+ if (n<0) n = (int32_t)ima->GetEffWidth();
+ else n = min(n,(int32_t)ima->GetEffWidth());
+
+ if ((IterImage!=NULL)&&(buf!=NULL)&&(n>0)) memcpy(IterImage,buf,n);
+}
+/////////////////////////////////////////////////////////////////////
+inline void CImageIterator::GetRow(uint8_t *buf, int32_t n)
+{
+ if ((IterImage!=NULL)&&(buf!=NULL)&&(n>0))
+ memcpy(buf,IterImage,min(n,(int32_t)ima->GetEffWidth()));
+}
+/////////////////////////////////////////////////////////////////////
+inline uint8_t* CImageIterator::GetRow()
+{
+ return IterImage;
+}
+/////////////////////////////////////////////////////////////////////
+inline uint8_t* CImageIterator::GetRow(int32_t n)
+{
+ SetY(n);
+ return IterImage;
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::NextByte()
+{
+ if (++Itx < (int32_t)ima->GetEffWidth()) return 1;
+ else
+ if (++Ity < (int32_t)ima->GetHeight()){
+ IterImage += ima->GetEffWidth();
+ Itx = 0;
+ return 1;
+ } else
+ return 0;
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::PrevByte()
+{
+ if (--Itx >= 0) return 1;
+ else
+ if (--Ity >= 0){
+ IterImage -= ima->GetEffWidth();
+ Itx = 0;
+ return 1;
+ } else
+ return 0;
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::NextStep()
+{
+ Itx += Stepx;
+ if (Itx < (int32_t)ima->GetEffWidth()) return 1;
+ else {
+ Ity += Stepy;
+ if (Ity < (int32_t)ima->GetHeight()){
+ IterImage += ima->GetEffWidth();
+ Itx = 0;
+ return 1;
+ } else
+ return 0;
+ }
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::PrevStep()
+{
+ Itx -= Stepx;
+ if (Itx >= 0) return 1;
+ else {
+ Ity -= Stepy;
+ if (Ity >= 0 && Ity < (int32_t)ima->GetHeight()) {
+ IterImage -= ima->GetEffWidth();
+ Itx = 0;
+ return 1;
+ } else
+ return 0;
+ }
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::GetCol(uint8_t* pCol, uint32_t x)
+{
+ if ((pCol==0)||(ima->GetBpp()<8)||(x>=ima->GetWidth()))
+ return 0;
+ uint32_t h = ima->GetHeight();
+ //uint32_t line = ima->GetEffWidth();
+ uint8_t bytes = (uint8_t)(ima->GetBpp()>>3);
+ uint8_t* pSrc;
+ for (uint32_t y=0;y<h;y++){
+ pSrc = ima->GetBits(y) + x*bytes;
+ for (uint8_t w=0;w<bytes;w++){
+ *pCol++=*pSrc++;
+ }
+ }
+ return 1;
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::SetCol(uint8_t* pCol, uint32_t x)
+{
+ if ((pCol==0)||(ima->GetBpp()<8)||(x>=ima->GetWidth()))
+ return 0;
+ uint32_t h = ima->GetHeight();
+ //uint32_t line = ima->GetEffWidth();
+ uint8_t bytes = (uint8_t)(ima->GetBpp()>>3);
+ uint8_t* pSrc;
+ for (uint32_t y=0;y<h;y++){
+ pSrc = ima->GetBits(y) + x*bytes;
+ for (uint8_t w=0;w<bytes;w++){
+ *pSrc++=*pCol++;
+ }
+ }
+ return 1;
+}
+/////////////////////////////////////////////////////////////////////
+#endif
diff --git a/archive/hge/CxImage/ximajas.cpp b/archive/hge/CxImage/ximajas.cpp new file mode 100644 index 0000000..788e204 --- /dev/null +++ b/archive/hge/CxImage/ximajas.cpp @@ -0,0 +1,325 @@ +/*
+ * File: ximajas.cpp
+ * Purpose: Platform Independent JasPer Image Class Loader and Writer
+ * 12/Apr/2003 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximajas.h"
+
+#if CXIMAGE_SUPPORT_JASPER
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageJAS::Decode(CxFile *hFile, uint32_t imagetype)
+{
+ if (hFile == NULL) return false;
+
+ jas_image_t *image=0;
+ jas_stream_t *in=0;
+ jas_matrix_t **bufs=0;
+ int32_t i,error=0;
+ int32_t fmt;
+ //jas_setdbglevel(0);
+
+ cx_try
+ {
+ if (jas_init())
+ cx_throw("cannot initialize jasper");
+
+ in = jas_stream_fdopen(0, "rb");
+ if (!in)
+ cx_throw("error: cannot open standard input");
+
+ CxFileJas src(hFile,in);
+
+ fmt = jas_image_getfmt(in);
+ if (fmt<0)
+ cx_throw("error: unknowm format");
+
+ image = jas_image_decode(in, fmt, 0);
+ if (!image){
+ fmt = -1;
+ cx_throw("error: cannot load image data");
+ }
+
+ char szfmt[4];
+ *szfmt = '\0';
+ strncpy(szfmt,jas_image_fmttostr(fmt),3);
+ szfmt[3] = '\0';
+
+ fmt = -1;
+#if CXIMAGE_SUPPORT_JP2
+ if (strcmp(szfmt,"jp2")==0) fmt = CXIMAGE_FORMAT_JP2;
+#endif
+#if CXIMAGE_SUPPORT_JPC
+ if (strcmp(szfmt,"jpc")==0) fmt = CXIMAGE_FORMAT_JPC;
+#endif
+#if CXIMAGE_SUPPORT_RAS
+ if (strcmp(szfmt,"ras")==0) fmt = CXIMAGE_FORMAT_RAS;
+#endif
+#if CXIMAGE_SUPPORT_PNM
+ if (strcmp(szfmt,"pnm")==0) fmt = CXIMAGE_FORMAT_PNM;
+#endif
+#if CXIMAGE_SUPPORT_PGX
+ if (strcmp(szfmt,"pgx")==0) fmt = CXIMAGE_FORMAT_PGX;
+#endif
+
+ //if (fmt<0)
+ // cx_throw("error: unknowm format");
+
+ int32_t x,y,w,h,depth,cmptno;
+
+ w = jas_image_cmptwidth(image,0);
+ h = jas_image_cmptheight(image,0);
+ depth = jas_image_cmptprec(image,0);
+
+ if (info.nEscape == -1){
+ head.biWidth = w;
+ head.biHeight= h;
+ info.dwType = fmt<0 ? 0 : fmt;
+ cx_throw("output dimensions returned");
+ }
+
+ if (image->numcmpts_ > 64 || image->numcmpts_ < 0)
+ cx_throw("error: too many components");
+
+ // <LD> 01/Jan/2005: Always force conversion to sRGB. Seems to be required for many types of JPEG2000 file.
+ // if (depth!=1 && depth!=4 && depth!=8)
+ if (image->numcmpts_>=3 && depth <=8)
+ {
+ jas_image_t *newimage;
+ jas_cmprof_t *outprof;
+ //jas_eprintf("forcing conversion to sRGB\n");
+ outprof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB);
+ if (!outprof) {
+ cx_throw("cannot create sRGB profile");
+ }
+ newimage = jas_image_chclrspc(image, outprof, JAS_CMXFORM_INTENT_PER);
+ if (!newimage) {
+ jas_cmprof_destroy(outprof); // <LD> 01/Jan/2005: Destroy color profile on error.
+ cx_throw("cannot convert to sRGB");
+ }
+ jas_image_destroy(image);
+ jas_cmprof_destroy(outprof);
+ image = newimage;
+ }
+
+ bufs = (jas_matrix_t **)calloc(image->numcmpts_, sizeof(jas_matrix_t**));
+ for (i = 0; i < image->numcmpts_; ++i) {
+ bufs[i] = jas_matrix_create(1, w);
+ if (!bufs[i]) {
+ cx_throw("error: cannot allocate memory");
+ }
+ }
+
+ int32_t nshift = (depth>8) ? (depth-8) : 0;
+
+ if (image->numcmpts_==3 &&
+ image->cmpts_[0]->width_ == image->cmpts_[1]->width_ &&
+ image->cmpts_[1]->width_ == image->cmpts_[2]->width_ &&
+ image->cmpts_[0]->height_ == image->cmpts_[1]->height_ &&
+ image->cmpts_[1]->height_ == image->cmpts_[2]->height_ &&
+ image->cmpts_[0]->prec_ == image->cmpts_[1]->prec_ &&
+ image->cmpts_[1]->prec_ == image->cmpts_[2]->prec_ )
+ {
+
+ if(!Create(w,h,24,fmt))
+ cx_throw("");
+
+ RGBQUAD c;
+ for (y=0; y<h; y++) {
+ for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {
+ jas_image_readcmpt(image, cmptno, 0, y, w, 1, bufs[cmptno]);
+ }
+
+ for (x=0; x<w; x++){
+ c.rgbRed = (uint8_t)((jas_matrix_getv(bufs[0], x)>>nshift));
+ c.rgbGreen = (uint8_t)((jas_matrix_getv(bufs[1], x)>>nshift));
+ c.rgbBlue = (uint8_t)((jas_matrix_getv(bufs[2], x)>>nshift));
+ SetPixelColor(x,h-1-y,c);
+ }
+ }
+ } else {
+ info.nNumFrames = image->numcmpts_;
+ if ((info.nFrame<0)||(info.nFrame>=info.nNumFrames)){
+ cx_throw("wrong frame!");
+ }
+ for (cmptno=0; cmptno<=info.nFrame; cmptno++) {
+ w = jas_image_cmptwidth(image,cmptno);
+ h = jas_image_cmptheight(image,cmptno);
+ depth = jas_image_cmptprec(image,cmptno);
+ if (depth>8) depth=8;
+ if(!Create(w,h,depth,imagetype))
+ cx_throw("");
+ SetGrayPalette();
+ for (y=0; y<h; y++) {
+ jas_image_readcmpt(image, cmptno, 0, y, w, 1, bufs[0]);
+ for (x=0; x<w; x++){
+ SetPixelIndex(x,h-1-y,(uint8_t)((jas_matrix_getv(bufs[0], x)>>nshift)));
+ }
+ }
+ }
+ }
+
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (info.nEscape == -1 && fmt>0){
+ error = 0;
+ } else {
+ error = 1;
+ }
+ }
+
+ if (bufs) {
+ for (i = 0; i < image->numcmpts_; ++i){ if (bufs[i]) jas_matrix_destroy(bufs[i]);}
+ free(bufs);
+ }
+ jas_cleanup();
+ if (image) jas_image_destroy(image);
+ if (in) jas_stream_close(in);
+ return (error==0);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageJAS::Encode(CxFile * hFile, uint32_t imagetype)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ if (head.biClrUsed!=0 && !IsGrayScale()){
+ strcpy(info.szLastError,"JasPer can save only RGB or GrayScale images");
+ return false;
+ }
+
+ jas_image_t *image=0;
+ jas_stream_t *out=0;
+ jas_matrix_t *cmpts[3];
+ int32_t x,y,yflip,error=0;
+ uint_fast16_t cmptno, numcmpts=0;
+ jas_image_cmptparm_t cmptparms[3], *cmptparm;
+
+ cx_try {
+
+ if (jas_init())
+ cx_throw("cannot initialize jasper");
+
+ out = jas_stream_fdopen(0, "wb");
+ if (!out)
+ cx_throw("error: cannot open standard output");
+
+ CxFileJas src(hFile,out);
+
+ numcmpts = head.biClrUsed==0 ? 3 : 1;
+
+ for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno, ++cmptparm) {
+ cmptparm->tlx = 0;
+ cmptparm->tly = 0;
+ cmptparm->hstep = 1;
+ cmptparm->vstep = 1;
+ cmptparm->width = head.biWidth;
+ cmptparm->height = head.biHeight;
+ cmptparm->prec = 8;
+ cmptparm->sgnd = false;
+ }
+
+ /* Create image object. */
+ image = jas_image_create(numcmpts, cmptparms, JAS_CLRSPC_UNKNOWN);
+ if (!image)
+ cx_throw("error : jas_image_create");
+
+ if (numcmpts == 3) {
+ jas_image_setclrspc(image, JAS_CLRSPC_SRGB);
+ jas_image_setcmpttype(image, 0,
+ JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
+ jas_image_setcmpttype(image, 1,
+ JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
+ jas_image_setcmpttype(image, 2,
+ JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
+ } else {
+ jas_image_setclrspc(image, JAS_CLRSPC_SGRAY);
+ jas_image_setcmpttype(image, 0,
+ JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
+ }
+
+
+ for (x = 0; x < numcmpts; ++x) { cmpts[x] = 0; }
+ /* Create temporary matrices to hold component data. */
+ for (x = 0; x < numcmpts; ++x) {
+ cmpts[x] = jas_matrix_create(1, head.biWidth);
+ if (!cmpts[x]) {
+ cx_throw("error : can't allocate memory");
+ }
+ }
+
+ RGBQUAD c;
+ for (y = 0; y < head.biHeight; ++y) {
+ for (x = 0; x < head.biWidth; ++x) {
+ if (head.biClrUsed==0){
+ c = GetPixelColor(x,y);
+ jas_matrix_setv(cmpts[0], x, c.rgbRed);
+ jas_matrix_setv(cmpts[1], x, c.rgbGreen);
+ jas_matrix_setv(cmpts[2], x, c.rgbBlue);
+ } else {
+ jas_matrix_setv(cmpts[0], x, GetPixelIndex(x,y));
+ }
+ }
+ yflip = head.biHeight - 1 - y;
+ for (cmptno = 0; cmptno < numcmpts; ++cmptno) {
+ if (jas_image_writecmpt(image, cmptno, 0, yflip, head.biWidth, 1, cmpts[cmptno])) {
+ cx_throw("error : jas_image_writecmpt");
+ }
+ }
+ }
+
+ char szfmt[4];
+ *szfmt = '\0';
+#if CXIMAGE_SUPPORT_JP2
+ if (imagetype == CXIMAGE_FORMAT_JP2) strcpy(szfmt,"jp2");
+#endif
+#if CXIMAGE_SUPPORT_JPC
+ if (imagetype == CXIMAGE_FORMAT_JPC) strcpy(szfmt,"jpc");
+#endif
+#if CXIMAGE_SUPPORT_RAS
+ if (imagetype == CXIMAGE_FORMAT_RAS) strcpy(szfmt,"ras");
+#endif
+#if CXIMAGE_SUPPORT_PNM
+ if (imagetype == CXIMAGE_FORMAT_PNM) strcpy(szfmt,"pnm");
+#endif
+#if CXIMAGE_SUPPORT_PGX
+ if (imagetype == CXIMAGE_FORMAT_PGX){
+ strcpy(szfmt,"pgx");
+ if (head.biClrUsed==0) cx_throw("PGX can save only GrayScale images");
+ }
+#endif
+ int32_t outfmt = jas_image_strtofmt(szfmt);
+
+ char szoutopts[32];
+ sprintf(szoutopts,"rate=%.3f", info.fQuality/100.0f);
+
+ if (jas_image_encode(image, out, outfmt, szoutopts)) {
+ cx_throw("error: cannot encode image");
+ }
+ jas_stream_flush(out);
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ error = 1;
+ }
+
+ for (x = 0; x < numcmpts; ++x) { if (cmpts[x]) { jas_matrix_destroy(cmpts[x]); } }
+ jas_cleanup();
+ if (image) jas_image_destroy(image);
+ if (out) jas_stream_close(out);
+
+ return (error==0);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_JASPER
+
diff --git a/archive/hge/CxImage/ximajas.h b/archive/hge/CxImage/ximajas.h new file mode 100644 index 0000000..da76dfc --- /dev/null +++ b/archive/hge/CxImage/ximajas.h @@ -0,0 +1,88 @@ +/*
+ * File: ximajas.h
+ * Purpose: Jasper Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageJAS (c) 12/Apr/2003 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * based on JasPer Copyright (c) 2001-2003 Michael David Adams - All rights reserved.
+ * ==========================================================
+ */
+#if !defined(__ximaJAS_h)
+#define __ximaJAS_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_JASPER
+
+#ifdef _LINUX
+ #include <jasper/jasper.h>
+#else
+ #include "../jasper/include/jasper/jasper.h"
+#endif
+
+class CxImageJAS: public CxImage
+{
+public:
+ CxImageJAS(): CxImage((uint32_t)0) {} // <vho> cast to uint32_t
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,0);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,0);}
+ bool Decode(CxFile * hFile, uint32_t imagetype = 0);
+ bool Decode(FILE *hFile, uint32_t imagetype = 0) { CxIOFile file(hFile); return Decode(&file,imagetype); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile, uint32_t imagetype = 0);
+ bool Encode(FILE *hFile, uint32_t imagetype = 0) { CxIOFile file(hFile); return Encode(&file,imagetype); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+protected:
+
+ class CxFileJas
+ {
+ public:
+ CxFileJas(CxFile* pFile,jas_stream_t *stream)
+ {
+ if (stream->obj_) jas_free(stream->obj_);
+ stream->obj_ = pFile;
+
+ // <vho> - cannot set the stream->ops_->functions here,
+ // because this overwrites a static structure in the Jasper library.
+ // This structure is used by Jasper for internal operations too, e.g. tempfile.
+ // However the ops_ pointer in the stream can be overwritten.
+
+ //stream->ops_->close_ = JasClose;
+ //stream->ops_->read_ = JasRead;
+ //stream->ops_->seek_ = JasSeek;
+ //stream->ops_->write_ = JasWrite;
+
+ jas_stream_CxFile.close_ = JasClose;
+ jas_stream_CxFile.read_ = JasRead;
+ jas_stream_CxFile.seek_ = JasSeek;
+ jas_stream_CxFile.write_ = JasWrite;
+
+ stream->ops_ = &jas_stream_CxFile;
+
+ // <vho> - end
+ }
+ static int32_t JasRead(jas_stream_obj_t *obj, char *buf, int32_t cnt)
+ { return ((CxFile*)obj)->Read(buf,1,cnt); }
+ static int32_t JasWrite(jas_stream_obj_t *obj, char *buf, int32_t cnt)
+ { return ((CxFile*)obj)->Write(buf,1,cnt); }
+ static long JasSeek(jas_stream_obj_t *obj, long offset, int32_t origin)
+ { return ((CxFile*)obj)->Seek(offset,origin); }
+ static int32_t JasClose(jas_stream_obj_t * /*obj*/)
+ { return 1; }
+
+ // <vho>
+private:
+ jas_stream_ops_t jas_stream_CxFile;
+ // <vho> - end
+
+ };
+
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximajbg.cpp b/archive/hge/CxImage/ximajbg.cpp new file mode 100644 index 0000000..ee7bc10 --- /dev/null +++ b/archive/hge/CxImage/ximajbg.cpp @@ -0,0 +1,174 @@ +/*
+ * File: ximajbg.cpp
+ * Purpose: Platform Independent JBG Image Class Loader and Writer
+ * 18/Aug/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximajbg.h"
+
+#if CXIMAGE_SUPPORT_JBG
+
+#include "ximaiter.h"
+
+#define JBIG_BUFSIZE 8192
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageJBG::Decode(CxFile *hFile)
+{
+ if (hFile == NULL) return false;
+
+ struct jbg_dec_state jbig_state;
+ uint32_t xmax = 4294967295UL, ymax = 4294967295UL;
+ uint32_t len, cnt;
+ uint8_t *buffer=0,*p;
+ int32_t result;
+
+ cx_try
+ {
+ jbg_dec_init(&jbig_state);
+ jbg_dec_maxsize(&jbig_state, xmax, ymax);
+
+ buffer = (uint8_t*)malloc(JBIG_BUFSIZE);
+ if (!buffer) cx_throw("Sorry, not enough memory available!");
+
+ result = JBG_EAGAIN;
+ do {
+ len = hFile->Read(buffer, 1, JBIG_BUFSIZE);
+ if (!len) break;
+ cnt = 0;
+ p = buffer;
+ while (len > 0 && (result == JBG_EAGAIN || result == JBG_EOK)) {
+ result = jbg_dec_in(&jbig_state, p, len, &cnt);
+ p += cnt;
+ len -= cnt;
+ }
+ } while (result == JBG_EAGAIN || result == JBG_EOK);
+
+ if (hFile->Error())
+ cx_throw("Problem while reading input file");
+ if (result != JBG_EOK && result != JBG_EOK_INTR)
+ cx_throw("Problem with input file");
+
+ int32_t w, h, bpp, planes, ew;
+
+ w = jbg_dec_getwidth(&jbig_state);
+ h = jbg_dec_getheight(&jbig_state);
+ planes = jbg_dec_getplanes(&jbig_state);
+ bpp = (planes+7)>>3;
+ ew = (w + 7)>>3;
+
+ if (info.nEscape == -1){
+ head.biWidth = w;
+ head.biHeight= h;
+ info.dwType = CXIMAGE_FORMAT_JBG;
+ cx_throw("output dimensions returned");
+ }
+
+ switch (planes){
+ case 1:
+ {
+ uint8_t* binary_image = jbg_dec_getimage(&jbig_state, 0);
+
+ if (!Create(w,h,1,CXIMAGE_FORMAT_JBG))
+ cx_throw("");
+
+ SetPaletteColor(0,255,255,255);
+ SetPaletteColor(1,0,0,0);
+
+ CImageIterator iter(this);
+ iter.Upset();
+ for (int32_t i=0;i<h;i++){
+ iter.SetRow(binary_image+i*ew,ew);
+ iter.PrevRow();
+ }
+
+ break;
+ }
+ default:
+ cx_throw("cannot decode images with more than 1 plane");
+ }
+
+ jbg_dec_free(&jbig_state);
+ free(buffer);
+
+ } cx_catch {
+ jbg_dec_free(&jbig_state);
+ if (buffer) free(buffer);
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_JBG) return true;
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageJBG::Encode(CxFile * hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ if (head.biBitCount != 1){
+ strcpy(info.szLastError,"JBG can save only 1-bpp images");
+ return false;
+ }
+
+ int32_t w, h, bpp, planes, ew, i, j, x, y;
+
+ w = head.biWidth;
+ h = head.biHeight;
+ planes = 1;
+ bpp = (planes+7)>>3;
+ ew = (w + 7)>>3;
+
+ uint8_t mask;
+ RGBQUAD *rgb = GetPalette();
+ if (CompareColors(&rgb[0],&rgb[1])<0) mask=255; else mask=0;
+
+ uint8_t *buffer = (uint8_t*)malloc(ew*h*2);
+ if (!buffer) {
+ strcpy(info.szLastError,"Sorry, not enough memory available!");
+ return false;
+ }
+
+ for (y=0; y<h; y++){
+ i= y*ew;
+ j= (h-y-1)*info.dwEffWidth;
+ for (x=0; x<ew; x++){
+ buffer[i + x]=info.pImage[j + x]^mask;
+ }
+ }
+
+ struct jbg_enc_state jbig_state;
+ jbg_enc_init(&jbig_state, w, h, planes, &buffer, jbig_data_out, hFile);
+
+ //jbg_enc_layers(&jbig_state, 2);
+ //jbg_enc_lrlmax(&jbig_state, 800, 600);
+
+ // Specify a few other options (each is ignored if negative)
+ int32_t dl = -1, dh = -1, d = -1, l0 = -1, mx = -1;
+ int32_t options = JBG_TPDON | JBG_TPBON | JBG_DPON;
+ int32_t order = JBG_ILEAVE | JBG_SMID;
+ jbg_enc_lrange(&jbig_state, dl, dh);
+ jbg_enc_options(&jbig_state, order, options, l0, mx, -1);
+
+ // now encode everything and send it to data_out()
+ jbg_enc_out(&jbig_state);
+
+ // give encoder a chance to free its temporary data structures
+ jbg_enc_free(&jbig_state);
+
+ free(buffer);
+
+ if (hFile->Error()){
+ strcpy(info.szLastError,"Problem while writing JBG file");
+ return false;
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_JBG
+
diff --git a/archive/hge/CxImage/ximajbg.h b/archive/hge/CxImage/ximajbg.h new file mode 100644 index 0000000..1cf4965 --- /dev/null +++ b/archive/hge/CxImage/ximajbg.h @@ -0,0 +1,44 @@ +/*
+ * File: ximajbg.h
+ * Purpose: JBG Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageJBG (c) 18/Aug/2002 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * based on LIBJBG Copyright (c) 2002, Markus Kuhn - All rights reserved.
+ * ==========================================================
+ */
+#if !defined(__ximaJBG_h)
+#define __ximaJBG_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_JBG
+
+extern "C" {
+#include "../jbig/jbig.h"
+};
+
+class CxImageJBG: public CxImage
+{
+public:
+ CxImageJBG(): CxImage(CXIMAGE_FORMAT_JBG) {}
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_JBG);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_JBG);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+protected:
+ static void jbig_data_out(uint8_t *buffer, uint32_t len, void *file)
+ {((CxFile*)file)->Write(buffer,len,1);}
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximajpg.cpp b/archive/hge/CxImage/ximajpg.cpp new file mode 100644 index 0000000..b66bf97 --- /dev/null +++ b/archive/hge/CxImage/ximajpg.cpp @@ -0,0 +1,538 @@ +/*
+ * File: ximajpg.cpp
+ * Purpose: Platform Independent JPEG Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximajpg.h"
+
+#if CXIMAGE_SUPPORT_JPG
+
+#ifdef _LINUX
+ #include <jmorecfg.h>
+#else
+ #include "../jpeg/jmorecfg.h"
+#endif
+
+#include "ximaiter.h"
+
+#include <setjmp.h>
+
+struct jpg_error_mgr {
+ struct jpeg_error_mgr pub; /* "public" fields */
+ jmp_buf setjmp_buffer; /* for return to caller */
+ char* buffer; /* error message <CSC>*/
+};
+typedef jpg_error_mgr *jpg_error_ptr;
+
+////////////////////////////////////////////////////////////////////////////////
+// Here's the routine that will replace the standard error_exit method:
+////////////////////////////////////////////////////////////////////////////////
+static void
+ima_jpeg_error_exit (j_common_ptr cinfo)
+{
+ /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
+ jpg_error_ptr myerr = (jpg_error_ptr) cinfo->err;
+ /* Create the message */
+ myerr->pub.format_message (cinfo, myerr->buffer);
+ /* Send it to stderr, adding a newline */
+ /* Return control to the setjmp point */
+ longjmp(myerr->setjmp_buffer, 1);
+}
+////////////////////////////////////////////////////////////////////////////////
+CxImageJPG::CxImageJPG(): CxImage(CXIMAGE_FORMAT_JPG)
+{
+#if CXIMAGEJPG_SUPPORT_EXIF
+ m_exif = NULL;
+ memset(&info.ExifInfo, 0, sizeof(EXIFINFO));
+#endif
+}
+////////////////////////////////////////////////////////////////////////////////
+CxImageJPG::~CxImageJPG()
+{
+#if CXIMAGEJPG_SUPPORT_EXIF
+ if (m_exif) delete m_exif;
+#endif
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGEJPG_SUPPORT_EXIF
+bool CxImageJPG::DecodeExif(CxFile * hFile)
+{
+ m_exif = new CxExifInfo(&info.ExifInfo);
+ if (m_exif){
+ int32_t pos=hFile->Tell();
+ m_exif->DecodeExif(hFile);
+ hFile->Seek(pos,SEEK_SET);
+ return m_exif->m_exifinfo->IsExif;
+ } else {
+ return false;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageJPG::GetExifThumbnail(const TCHAR *filename, const TCHAR *outname, int32_t type)
+{
+ CxIOFile file;
+ if (!file.Open(filename, _T("rb"))) return false;
+ CxExifInfo exif(&info.ExifInfo);
+ exif.DecodeExif(&file);
+ if (info.ExifInfo.IsExif && info.ExifInfo.ThumbnailPointer && info.ExifInfo.ThumbnailSize > 0)
+ { // have a thumbnail - check whether it needs rotating or resizing
+ // TODO: Write a fast routine to read the jpeg header to get the width and height
+ CxImage image(info.ExifInfo.ThumbnailPointer, info.ExifInfo.ThumbnailSize, CXIMAGE_FORMAT_JPG);
+ if (image.IsValid())
+ {
+ if (image.GetWidth() > 256 || image.GetHeight() > 256)
+ { // resize the image
+// float amount = 256.0f / max(image.GetWidth(), image.GetHeight());
+// image.Resample((int32_t)(image.GetWidth() * amount), (int32_t)(image.GetHeight() * amount), 0);
+ }
+ if (info.ExifInfo.Orientation != 1)
+ image.RotateExif(info.ExifInfo.Orientation);
+ return image.Save(outname, CXIMAGE_FORMAT_JPG);
+ }
+ // nice and fast, but we can't resize :(
+ /*
+ FILE *hFileWrite;
+ if ((hFileWrite=fopen(outname, "wb")) != NULL)
+ {
+ fwrite(m_exifinfo.ThumbnailPointer, m_exifinfo.ThumbnailSize, 1, hFileWrite);
+ fclose(hFileWrite);
+ return true;
+ }*/
+ }
+ return false;
+}
+#endif //CXIMAGEJPG_SUPPORT_EXIF
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageJPG::Decode(CxFile * hFile)
+{
+
+ bool is_exif = false;
+#if CXIMAGEJPG_SUPPORT_EXIF
+ is_exif = DecodeExif(hFile);
+#endif
+
+ CImageIterator iter(this);
+ /* This struct contains the JPEG decompression parameters and pointers to
+ * working space (which is allocated as needed by the JPEG library).
+ */
+ struct jpeg_decompress_struct cinfo;
+ /* We use our private extension JPEG error handler. <CSC> */
+ struct jpg_error_mgr jerr;
+ jerr.buffer=info.szLastError;
+ /* More stuff */
+ JSAMPARRAY buffer; /* Output row buffer */
+ int32_t row_stride; /* physical row width in output buffer */
+
+ /* In this example we want to open the input file before doing anything else,
+ * so that the setjmp() error recovery below can assume the file is open.
+ * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
+ * requires it in order to read binary files.
+ */
+
+ /* Step 1: allocate and initialize JPEG decompression object */
+ /* We set up the normal JPEG error routines, then override error_exit. */
+ cinfo.err = jpeg_std_error(&jerr.pub);
+ jerr.pub.error_exit = ima_jpeg_error_exit;
+
+ CxFileJpg src(hFile);
+
+ /* Establish the setjmp return context for my_error_exit to use. */
+ if (setjmp(jerr.setjmp_buffer)) {
+ /* If we get here, the JPEG code has signaled an error.
+ * We need to clean up the JPEG object, close the input file, and return.
+ */
+ jpeg_destroy_decompress(&cinfo);
+ return 0;
+ }
+ /* Now we can initialize the JPEG decompression object. */
+ jpeg_create_decompress(&cinfo);
+
+ /* Step 2: specify data source (eg, a file) */
+ //jpeg_stdio_src(&cinfo, infile);
+ cinfo.src = &src;
+
+ /* Step 3: read file parameters with jpeg_read_header() */
+ (void) jpeg_read_header(&cinfo, TRUE);
+
+ /* Step 4 <chupeev> handle decoder options*/
+ uint32_t dwCodecOptions = GetCodecOption(CXIMAGE_FORMAT_JPG); //[nm_114]
+ if ((dwCodecOptions & DECODE_GRAYSCALE) != 0)
+ cinfo.out_color_space = JCS_GRAYSCALE;
+ if ((dwCodecOptions & DECODE_QUANTIZE) != 0) {
+ cinfo.quantize_colors = TRUE;
+ cinfo.desired_number_of_colors = GetJpegQuality();
+ }
+ if ((dwCodecOptions & DECODE_DITHER) != 0)
+ cinfo.dither_mode = m_nDither;
+ if ((dwCodecOptions & DECODE_ONEPASS) != 0)
+ cinfo.two_pass_quantize = FALSE;
+ if ((dwCodecOptions & DECODE_NOSMOOTH) != 0)
+ cinfo.do_fancy_upsampling = FALSE;
+
+//<DP>: Load true color images as RGB (no quantize)
+/* Step 4: set parameters for decompression */
+/* if (cinfo.jpeg_color_space!=JCS_GRAYSCALE) {
+ * cinfo.quantize_colors = TRUE;
+ * cinfo.desired_number_of_colors = 128;
+ *}
+ */ //</DP>
+
+ cinfo.scale_num = 1;
+ // Set the scale <ignacio>
+ cinfo.scale_denom = GetJpegScale();
+
+ // Borrowed the idea from GIF implementation <ignacio>
+ if (info.nEscape == -1) {
+ // Return output dimensions only
+ jpeg_calc_output_dimensions(&cinfo);
+ head.biWidth = cinfo.output_width;
+ head.biHeight = cinfo.output_height;
+ info.dwType = CXIMAGE_FORMAT_JPG;
+ jpeg_destroy_decompress(&cinfo);
+ return true;
+ }
+
+ /* Step 5: Start decompressor */
+ jpeg_start_decompress(&cinfo);
+
+ /* We may need to do some setup of our own at this point before reading
+ * the data. After jpeg_start_decompress() we have the correct scaled
+ * output image dimensions available, as well as the output colormap
+ * if we asked for color quantization.
+ */
+ //Create the image using output dimensions <ignacio>
+ //Create(cinfo.image_width, cinfo.image_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG);
+ Create(cinfo.output_width, cinfo.output_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG);
+
+ if (!pDib) longjmp(jerr.setjmp_buffer, 1); //<DP> check if the image has been created
+
+ if (is_exif){
+#if CXIMAGEJPG_SUPPORT_EXIF
+ if ((info.ExifInfo.Xresolution != 0.0) && (info.ExifInfo.ResolutionUnit != 0))
+ SetXDPI((int32_t)(info.ExifInfo.Xresolution/info.ExifInfo.ResolutionUnit));
+ if ((info.ExifInfo.Yresolution != 0.0) && (info.ExifInfo.ResolutionUnit != 0))
+ SetYDPI((int32_t)(info.ExifInfo.Yresolution/info.ExifInfo.ResolutionUnit));
+#endif
+ } else {
+ switch (cinfo.density_unit) {
+ case 0: // [andy] fix for aspect ratio...
+ if((cinfo.Y_density > 0) && (cinfo.X_density > 0)){
+ SetYDPI((int32_t)(GetXDPI()*(float(cinfo.Y_density)/float(cinfo.X_density))));
+ }
+ break;
+ case 2: // [andy] fix: cinfo.X/Y_density is pixels per centimeter
+ SetXDPI((int32_t)floor(cinfo.X_density * 2.54 + 0.5));
+ SetYDPI((int32_t)floor(cinfo.Y_density * 2.54 + 0.5));
+ break;
+ default:
+ SetXDPI(cinfo.X_density);
+ SetYDPI(cinfo.Y_density);
+ }
+ }
+
+ if (cinfo.out_color_space==JCS_GRAYSCALE){
+ SetGrayPalette();
+ head.biClrUsed =256;
+ } else {
+ if (cinfo.quantize_colors){
+ SetPalette(cinfo.actual_number_of_colors, cinfo.colormap[0], cinfo.colormap[1], cinfo.colormap[2]);
+ head.biClrUsed=cinfo.actual_number_of_colors;
+ } else {
+ head.biClrUsed=0;
+ }
+ }
+
+ /* JSAMPLEs per row in output buffer */
+ row_stride = cinfo.output_width * cinfo.output_components;
+
+ /* Make a one-row-high sample array that will go away when done with image */
+ buffer = (*cinfo.mem->alloc_sarray)
+ ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
+
+ /* Step 6: while (scan lines remain to be read) */
+ /* jpeg_read_scanlines(...); */
+ /* Here we use the library's state variable cinfo.output_scanline as the
+ * loop counter, so that we don't have to keep track ourselves.
+ */
+ iter.Upset();
+ while (cinfo.output_scanline < cinfo.output_height) {
+
+ if (info.nEscape) longjmp(jerr.setjmp_buffer, 1); // <vho> - cancel decoding
+
+ (void) jpeg_read_scanlines(&cinfo, buffer, 1);
+ // info.nProgress = (int32_t)(100*cinfo.output_scanline/cinfo.output_height);
+ //<DP> Step 6a: CMYK->RGB */
+ if ((cinfo.num_components==4)&&(cinfo.quantize_colors==FALSE)){
+ uint8_t k,*dst,*src;
+ dst=iter.GetRow();
+ src=buffer[0];
+ for(int32_t x3=0,x4=0; x3<(int32_t)info.dwEffWidth && x4<row_stride; x3+=3, x4+=4){
+ k=src[x4+3];
+ dst[x3] =(uint8_t)((k * src[x4+2])/255);
+ dst[x3+1]=(uint8_t)((k * src[x4+1])/255);
+ dst[x3+2]=(uint8_t)((k * src[x4+0])/255);
+ }
+ } else {
+ /* Assume put_scanline_someplace wants a pointer and sample count. */
+ iter.SetRow(buffer[0], row_stride);
+ }
+ iter.PrevRow();
+ }
+
+ /* Step 7: Finish decompression */
+ (void) jpeg_finish_decompress(&cinfo);
+ /* We can ignore the return value since suspension is not possible
+ * with the stdio data source.
+ */
+
+ //<DP> Step 7A: Swap red and blue components
+ // not necessary if swapped red and blue definition in jmorecfg.h;ln322 <W. Morrison>
+ if ((cinfo.num_components==3)&&(cinfo.quantize_colors==FALSE)){
+ uint8_t* r0=GetBits();
+ for(int32_t y=0;y<head.biHeight;y++){
+ if (info.nEscape) longjmp(jerr.setjmp_buffer, 1); // <vho> - cancel decoding
+ RGBtoBGR(r0,3*head.biWidth);
+ r0+=info.dwEffWidth;
+ }
+ }
+
+ /* Step 8: Release JPEG decompression object */
+ /* This is an important step since it will release a good deal of memory. */
+ jpeg_destroy_decompress(&cinfo);
+
+ /* At this point you may want to check to see whether any corrupt-data
+ * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
+ */
+
+ /* And we're done! */
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageJPG::Encode(CxFile * hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ if (head.biClrUsed!=0 && !IsGrayScale()){
+ strcpy(info.szLastError,"JPEG can save only RGB or GreyScale images");
+ return false;
+ }
+
+ // necessary for EXIF, and for roll backs
+ int32_t pos=hFile->Tell();
+
+ /* This struct contains the JPEG compression parameters and pointers to
+ * working space (which is allocated as needed by the JPEG library).
+ * It is possible to have several such structures, representing multiple
+ * compression/decompression processes, in existence at once. We refer
+ * to any one struct (and its associated working data) as a "JPEG object".
+ */
+ struct jpeg_compress_struct cinfo;
+ /* This struct represents a JPEG error handler. It is declared separately
+ * because applications often want to supply a specialized error handler
+ * (see the second half of this file for an example). But here we just
+ * take the easy way out and use the standard error handler, which will
+ * print a message on stderr and call exit() if compression fails.
+ * Note that this struct must live as int32_t as the main JPEG parameter
+ * struct, to avoid dangling-pointer problems.
+ */
+ //struct jpeg_error_mgr jerr;
+ /* We use our private extension JPEG error handler. <CSC> */
+ struct jpg_error_mgr jerr;
+ jerr.buffer=info.szLastError;
+ /* More stuff */
+ int32_t row_stride; /* physical row width in image buffer */
+ JSAMPARRAY buffer; /* Output row buffer */
+
+ /* Step 1: allocate and initialize JPEG compression object */
+ /* We have to set up the error handler first, in case the initialization
+ * step fails. (Unlikely, but it could happen if you are out of memory.)
+ * This routine fills in the contents of struct jerr, and returns jerr's
+ * address which we place into the link field in cinfo.
+ */
+ //cinfo.err = jpeg_std_error(&jerr); <CSC>
+ /* We set up the normal JPEG error routines, then override error_exit. */
+ cinfo.err = jpeg_std_error(&jerr.pub);
+ jerr.pub.error_exit = ima_jpeg_error_exit;
+
+ /* Establish the setjmp return context for my_error_exit to use. */
+ if (setjmp(jerr.setjmp_buffer)) {
+ /* If we get here, the JPEG code has signaled an error.
+ * We need to clean up the JPEG object, close the input file, and return.
+ */
+ strcpy(info.szLastError, jerr.buffer); //<CSC>
+ jpeg_destroy_compress(&cinfo);
+ return 0;
+ }
+
+ /* Now we can initialize the JPEG compression object. */
+ jpeg_create_compress(&cinfo);
+ /* Step 2: specify data destination (eg, a file) */
+ /* Note: steps 2 and 3 can be done in either order. */
+ /* Here we use the library-supplied code to send compressed data to a
+ * stdio stream. You can also write your own code to do something else.
+ * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
+ * requires it in order to write binary files.
+ */
+
+ //jpeg_stdio_dest(&cinfo, outfile);
+ CxFileJpg dest(hFile);
+ cinfo.dest = &dest;
+
+ /* Step 3: set parameters for compression */
+ /* First we supply a description of the input image.
+ * Four fields of the cinfo struct must be filled in:
+ */
+ cinfo.image_width = GetWidth(); // image width and height, in pixels
+ cinfo.image_height = GetHeight();
+
+ if (IsGrayScale()){
+ cinfo.input_components = 1; // # of color components per pixel
+ cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
+ } else {
+ cinfo.input_components = 3; // # of color components per pixel
+ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+ }
+
+ /* Now use the library's routine to set default compression parameters.
+ * (You must set at least cinfo.in_color_space before calling this,
+ * since the defaults depend on the source color space.)
+ */
+ jpeg_set_defaults(&cinfo);
+ /* Now you can set any non-default parameters you wish to.
+ * Here we just illustrate the use of quality (quantization table) scaling:
+ */
+
+ uint32_t dwCodecOptions = GetCodecOption(CXIMAGE_FORMAT_JPG); //[nm_114]
+//#ifdef C_ARITH_CODING_SUPPORTED
+ if ((dwCodecOptions & ENCODE_ARITHMETIC) != 0)
+ cinfo.arith_code = TRUE;
+//#endif
+
+//#ifdef ENTROPY_OPT_SUPPORTED
+ if ((dwCodecOptions & ENCODE_OPTIMIZE) != 0)
+ cinfo.optimize_coding = TRUE;
+//#endif
+
+ if ((dwCodecOptions & ENCODE_GRAYSCALE) != 0)
+ jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE);
+
+ if ((dwCodecOptions & ENCODE_SMOOTHING) != 0)
+ cinfo.smoothing_factor = m_nSmoothing;
+
+ jpeg_set_quality(&cinfo, GetJpegQuality(), (dwCodecOptions & ENCODE_BASELINE) != 0);
+
+//#ifdef C_PROGRESSIVE_SUPPORTED
+ if ((dwCodecOptions & ENCODE_PROGRESSIVE) != 0)
+ jpeg_simple_progression(&cinfo);
+//#endif
+
+#ifdef C_LOSSLESS_SUPPORTED
+ if ((dwCodecOptions & ENCODE_LOSSLESS) != 0)
+ jpeg_simple_lossless(&cinfo, m_nPredictor, m_nPointTransform);
+#endif
+
+ //SetCodecOption(ENCODE_SUBSAMPLE_444 | GetCodecOption(CXIMAGE_FORMAT_JPG),CXIMAGE_FORMAT_JPG);
+
+ // 2x2, 1x1, 1x1 (4:1:1) : High (default sub sampling)
+ cinfo.comp_info[0].h_samp_factor = 2;
+ cinfo.comp_info[0].v_samp_factor = 2;
+ cinfo.comp_info[1].h_samp_factor = 1;
+ cinfo.comp_info[1].v_samp_factor = 1;
+ cinfo.comp_info[2].h_samp_factor = 1;
+ cinfo.comp_info[2].v_samp_factor = 1;
+
+ if ((dwCodecOptions & ENCODE_SUBSAMPLE_422) != 0){
+ // 2x1, 1x1, 1x1 (4:2:2) : Medium
+ cinfo.comp_info[0].h_samp_factor = 2;
+ cinfo.comp_info[0].v_samp_factor = 1;
+ cinfo.comp_info[1].h_samp_factor = 1;
+ cinfo.comp_info[1].v_samp_factor = 1;
+ cinfo.comp_info[2].h_samp_factor = 1;
+ cinfo.comp_info[2].v_samp_factor = 1;
+ }
+
+ if ((dwCodecOptions & ENCODE_SUBSAMPLE_444) != 0){
+ // 1x1 1x1 1x1 (4:4:4) : None
+ cinfo.comp_info[0].h_samp_factor = 1;
+ cinfo.comp_info[0].v_samp_factor = 1;
+ cinfo.comp_info[1].h_samp_factor = 1;
+ cinfo.comp_info[1].v_samp_factor = 1;
+ cinfo.comp_info[2].h_samp_factor = 1;
+ cinfo.comp_info[2].v_samp_factor = 1;
+ }
+
+ cinfo.density_unit=1;
+ cinfo.X_density=(uint16_t)GetXDPI();
+ cinfo.Y_density=(uint16_t)GetYDPI();
+
+ /* Step 4: Start compressor */
+ /* TRUE ensures that we will write a complete interchange-JPEG file.
+ * Pass TRUE unless you are very sure of what you're doing.
+ */
+ jpeg_start_compress(&cinfo, TRUE);
+
+ /* Step 5: while (scan lines remain to be written) */
+ /* jpeg_write_scanlines(...); */
+ /* Here we use the library's state variable cinfo.next_scanline as the
+ * loop counter, so that we don't have to keep track ourselves.
+ * To keep things simple, we pass one scanline per call; you can pass
+ * more if you wish, though.
+ */
+ row_stride = info.dwEffWidth; /* JSAMPLEs per row in image_buffer */
+
+ //<DP> "8+row_stride" fix heap deallocation problem during debug???
+ buffer = (*cinfo.mem->alloc_sarray)
+ ((j_common_ptr) &cinfo, JPOOL_IMAGE, 8+row_stride, 1);
+
+ CImageIterator iter(this);
+
+ iter.Upset();
+ while (cinfo.next_scanline < cinfo.image_height) {
+ // info.nProgress = (int32_t)(100*cinfo.next_scanline/cinfo.image_height);
+ iter.GetRow(buffer[0], row_stride);
+ // not necessary if swapped red and blue definition in jmorecfg.h;ln322 <W. Morrison>
+ if (head.biClrUsed==0){ // swap R & B for RGB images
+ RGBtoBGR(buffer[0], row_stride); // Lance : 1998/09/01 : Bug ID: EXP-2.1.1-9
+ }
+ iter.PrevRow();
+ (void) jpeg_write_scanlines(&cinfo, buffer, 1);
+ }
+
+ /* Step 6: Finish compression */
+ jpeg_finish_compress(&cinfo);
+
+ /* Step 7: release JPEG compression object */
+ /* This is an important step since it will release a good deal of memory. */
+ jpeg_destroy_compress(&cinfo);
+
+
+#if CXIMAGEJPG_SUPPORT_EXIF
+ if (m_exif && m_exif->m_exifinfo->IsExif){
+ // discard useless sections (if any) read from original image
+ m_exif->DiscardAllButExif();
+ // read new created image, to split the sections
+ hFile->Seek(pos,SEEK_SET);
+ m_exif->DecodeExif(hFile,EXIF_READ_IMAGE);
+ // save back the image, adding EXIF section
+ hFile->Seek(pos,SEEK_SET);
+ m_exif->EncodeExif(hFile);
+ }
+#endif
+
+
+ /* And we're done! */
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_JPG
+
diff --git a/archive/hge/CxImage/ximajpg.h b/archive/hge/CxImage/ximajpg.h new file mode 100644 index 0000000..da21643 --- /dev/null +++ b/archive/hge/CxImage/ximajpg.h @@ -0,0 +1,283 @@ +/*
+ * File: ximajpg.h
+ * Purpose: JPG Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageJPG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes
+ *
+ * Special thanks to Chris Shearer Cooper for CxFileJpg tips & code
+ *
+ * EXIF support based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>
+ *
+ * original CImageJPG and CImageIterator implementation are:
+ * Copyright: (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>
+ *
+ * This software is based in part on the work of the Independent JPEG Group.
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * ==========================================================
+ */
+#if !defined(__ximaJPEG_h)
+#define __ximaJPEG_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_JPG
+
+#define CXIMAGEJPG_SUPPORT_EXIF CXIMAGE_SUPPORT_EXIF
+
+extern "C" {
+#ifdef _LINUX
+ #include <jpeglib.h>
+ #include <jerror.h>
+#else
+ #include "../jpeg/jpeglib.h"
+ #include "../jpeg/jerror.h"
+#endif
+}
+
+class DLL_EXP CxImageJPG: public CxImage
+{
+public:
+ CxImageJPG();
+ ~CxImageJPG();
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_JPG);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_JPG);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+/*
+ * EXIF support based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>
+ */
+
+#if CXIMAGEJPG_SUPPORT_EXIF
+
+//--------------------------------------------------------------------------
+// JPEG markers consist of one or more 0xFF bytes, followed by a marker
+// code byte (which is not an FF). Here are the marker codes of interest
+// in this program. (See jdmarker.c for a more complete list.)
+//--------------------------------------------------------------------------
+
+#define M_SOF0 0xC0 // Start Of Frame N
+#define M_SOF1 0xC1 // N indicates which compression process
+#define M_SOF2 0xC2 // Only SOF0-SOF2 are now in common use
+#define M_SOF3 0xC3
+#define M_SOF5 0xC5 // NB: codes C4 and CC are NOT SOF markers
+#define M_SOF6 0xC6
+#define M_SOF7 0xC7
+#define M_SOF9 0xC9
+#define M_SOF10 0xCA
+#define M_SOF11 0xCB
+#define M_SOF13 0xCD
+#define M_SOF14 0xCE
+#define M_SOF15 0xCF
+#define M_SOI 0xD8 // Start Of Image (beginning of datastream)
+#define M_EOI 0xD9 // End Of Image (end of datastream)
+#define M_SOS 0xDA // Start Of Scan (begins compressed data)
+#define M_JFIF 0xE0 // Jfif marker
+#define M_EXIF 0xE1 // Exif marker
+#define M_COM 0xFE // COMment
+
+#define PSEUDO_IMAGE_MARKER 0x123; // Extra value.
+
+#define EXIF_READ_EXIF 0x01
+#define EXIF_READ_IMAGE 0x02
+#define EXIF_READ_ALL 0x03
+
+class DLL_EXP CxExifInfo
+{
+
+typedef struct tag_Section_t{
+ uint8_t* Data;
+ int32_t Type;
+ unsigned Size;
+} Section_t;
+
+public:
+ EXIFINFO* m_exifinfo;
+ char m_szLastError[256];
+ CxExifInfo(EXIFINFO* info = NULL);
+ ~CxExifInfo();
+ bool DecodeExif(CxFile * hFile, int32_t nReadMode = EXIF_READ_EXIF);
+ bool EncodeExif(CxFile * hFile);
+ void DiscardAllButExif();
+protected:
+ bool process_EXIF(uint8_t * CharBuf, uint32_t length);
+ void process_COM (const uint8_t * Data, int32_t length);
+ void process_SOFn (const uint8_t * Data, int32_t marker);
+ int32_t Get16u(void * Short);
+ int32_t Get16m(void * Short);
+ int32_t Get32s(void * Long);
+ uint32_t Get32u(void * Long);
+ double ConvertAnyFormat(void * ValuePtr, int32_t Format);
+ void* FindSection(int32_t SectionType);
+ bool ProcessExifDir(uint8_t * DirStart, uint8_t * OffsetBase, unsigned ExifLength,
+ EXIFINFO * const pInfo, uint8_t ** const LastExifRefdP, int32_t NestingLevel=0);
+ int32_t ExifImageWidth;
+ int32_t MotorolaOrder;
+ Section_t Sections[MAX_SECTIONS];
+ int32_t SectionsRead;
+ bool freeinfo;
+};
+
+ CxExifInfo* m_exif;
+ bool DecodeExif(CxFile * hFile);
+ bool DecodeExif(FILE * hFile) { CxIOFile file(hFile); return DecodeExif(&file); }
+ bool GetExifThumbnail(const TCHAR *filename, const TCHAR *outname, int32_t type);
+
+#endif //CXIMAGEJPG_SUPPORT_EXIF
+
+////////////////////////////////////////////////////////////////////////////////////////
+////////////////////// C x F i l e J p g ////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////
+
+// thanks to Chris Shearer Cooper <cscooper(at)frii(dot)com>
+class CxFileJpg : public jpeg_destination_mgr, public jpeg_source_mgr
+ {
+public:
+ enum { eBufSize = 4096 };
+
+ CxFileJpg(CxFile* pFile)
+ {
+ m_pFile = pFile;
+
+ init_destination = InitDestination;
+ empty_output_buffer = EmptyOutputBuffer;
+ term_destination = TermDestination;
+
+ init_source = InitSource;
+ fill_input_buffer = FillInputBuffer;
+ skip_input_data = SkipInputData;
+ resync_to_restart = jpeg_resync_to_restart; // use default method
+ term_source = TermSource;
+ next_input_byte = NULL; //* => next byte to read from buffer
+ bytes_in_buffer = 0; //* # of bytes remaining in buffer
+
+ m_pBuffer = new uint8_t[eBufSize];
+ }
+ ~CxFileJpg()
+ {
+ delete [] m_pBuffer;
+ }
+
+ static void InitDestination(j_compress_ptr cinfo)
+ {
+ CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;
+ pDest->next_output_byte = pDest->m_pBuffer;
+ pDest->free_in_buffer = eBufSize;
+ }
+
+ static boolean EmptyOutputBuffer(j_compress_ptr cinfo)
+ {
+ CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;
+ if (pDest->m_pFile->Write(pDest->m_pBuffer,1,eBufSize)!=(size_t)eBufSize)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ pDest->next_output_byte = pDest->m_pBuffer;
+ pDest->free_in_buffer = eBufSize;
+ return TRUE;
+ }
+
+ static void TermDestination(j_compress_ptr cinfo)
+ {
+ CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;
+ size_t datacount = eBufSize - pDest->free_in_buffer;
+ /* Write any data remaining in the buffer */
+ if (datacount > 0) {
+ if (!pDest->m_pFile->Write(pDest->m_pBuffer,1,datacount))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ }
+ pDest->m_pFile->Flush();
+ /* Make sure we wrote the output file OK */
+ if (pDest->m_pFile->Error()) ERREXIT(cinfo, JERR_FILE_WRITE);
+ return;
+ }
+
+ static void InitSource(j_decompress_ptr cinfo)
+ {
+ CxFileJpg* pSource = (CxFileJpg*)cinfo->src;
+ pSource->m_bStartOfFile = TRUE;
+ }
+
+ static boolean FillInputBuffer(j_decompress_ptr cinfo)
+ {
+ size_t nbytes;
+ CxFileJpg* pSource = (CxFileJpg*)cinfo->src;
+ nbytes = pSource->m_pFile->Read(pSource->m_pBuffer,1,eBufSize);
+ if (nbytes <= 0){
+ if (pSource->m_bStartOfFile) //* Treat empty input file as fatal error
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ // Insert a fake EOI marker
+ pSource->m_pBuffer[0] = (JOCTET) 0xFF;
+ pSource->m_pBuffer[1] = (JOCTET) JPEG_EOI;
+ nbytes = 2;
+ }
+ pSource->next_input_byte = pSource->m_pBuffer;
+ pSource->bytes_in_buffer = nbytes;
+ pSource->m_bStartOfFile = FALSE;
+ return TRUE;
+ }
+
+ static void SkipInputData(j_decompress_ptr cinfo, long num_bytes)
+ {
+ CxFileJpg* pSource = (CxFileJpg*)cinfo->src;
+ if (num_bytes > 0){
+ while (num_bytes > (int32_t)pSource->bytes_in_buffer){
+ num_bytes -= (int32_t)pSource->bytes_in_buffer;
+ FillInputBuffer(cinfo);
+ // note we assume that fill_input_buffer will never return FALSE,
+ // so suspension need not be handled.
+ }
+ pSource->next_input_byte += (size_t) num_bytes;
+ pSource->bytes_in_buffer -= (size_t) num_bytes;
+ }
+ }
+
+ static void TermSource(j_decompress_ptr /*cinfo*/)
+ {
+ return;
+ }
+protected:
+ CxFile *m_pFile;
+ uint8_t *m_pBuffer;
+ bool m_bStartOfFile;
+};
+
+public:
+ enum CODEC_OPTION
+ {
+ ENCODE_BASELINE = 0x1,
+ ENCODE_ARITHMETIC = 0x2,
+ ENCODE_GRAYSCALE = 0x4,
+ ENCODE_OPTIMIZE = 0x8,
+ ENCODE_PROGRESSIVE = 0x10,
+ ENCODE_LOSSLESS = 0x20,
+ ENCODE_SMOOTHING = 0x40,
+ DECODE_GRAYSCALE = 0x80,
+ DECODE_QUANTIZE = 0x100,
+ DECODE_DITHER = 0x200,
+ DECODE_ONEPASS = 0x400,
+ DECODE_NOSMOOTH = 0x800,
+ ENCODE_SUBSAMPLE_422 = 0x1000,
+ ENCODE_SUBSAMPLE_444 = 0x2000
+ };
+
+ int32_t m_nPredictor;
+ int32_t m_nPointTransform;
+ int32_t m_nSmoothing;
+ int32_t m_nQuantize;
+ J_DITHER_MODE m_nDither;
+
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximalpha.cpp b/archive/hge/CxImage/ximalpha.cpp new file mode 100644 index 0000000..2932068 --- /dev/null +++ b/archive/hge/CxImage/ximalpha.cpp @@ -0,0 +1,367 @@ +// xImalpha.cpp : Alpha channel functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_ALPHA
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa AlphaSetMax
+ */
+uint8_t CxImage::AlphaGetMax() const
+{
+ return info.nAlphaMax;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets global Alpha (opacity) value applied to the whole image,
+ * valid only for painting functions.
+ * \param nAlphaMax: can be from 0 to 255
+ */
+void CxImage::AlphaSetMax(uint8_t nAlphaMax)
+{
+ info.nAlphaMax=nAlphaMax;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the image has a valid alpha channel.
+ */
+bool CxImage::AlphaIsValid()
+{
+ return pAlpha!=0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Enables the alpha palette, so the Draw() function changes its behavior.
+ */
+void CxImage::AlphaPaletteEnable(bool enable)
+{
+ info.bAlphaPaletteEnabled=enable;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * True if the alpha palette is enabled for painting.
+ */
+bool CxImage::AlphaPaletteIsEnabled()
+{
+ return info.bAlphaPaletteEnabled;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the alpha channel to full transparent. AlphaSet(0) has the same effect
+ */
+void CxImage::AlphaClear()
+{
+ if (pAlpha) memset(pAlpha,0,head.biWidth * head.biHeight);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the alpha level for the whole image.
+ * \param level : from 0 (transparent) to 255 (opaque)
+ */
+void CxImage::AlphaSet(uint8_t level)
+{
+ if (pAlpha) memset(pAlpha,level,head.biWidth * head.biHeight);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Allocates an empty (opaque) alpha channel.
+ */
+bool CxImage::AlphaCreate()
+{
+ if (pAlpha==NULL) {
+ pAlpha = (uint8_t*)malloc(head.biWidth * head.biHeight);
+ if (pAlpha) memset(pAlpha,255,head.biWidth * head.biHeight);
+ }
+ return (pAlpha!=0);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::AlphaDelete()
+{
+ if (pAlpha) { free(pAlpha); pAlpha=0; }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::AlphaInvert()
+{
+ if (pAlpha) {
+ uint8_t *iSrc=pAlpha;
+ int32_t n=head.biHeight*head.biWidth;
+ for(int32_t i=0; i < n; i++){
+ *iSrc=(uint8_t)~(*(iSrc));
+ iSrc++;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Imports an existing alpa channel from another image with the same width and height.
+ */
+bool CxImage::AlphaCopy(CxImage &from)
+{
+ if (from.pAlpha == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;
+ if (pAlpha==NULL) pAlpha = (uint8_t*)malloc(head.biWidth * head.biHeight);
+ if (pAlpha==NULL) return false;
+ memcpy(pAlpha,from.pAlpha,head.biWidth * head.biHeight);
+ info.nAlphaMax=from.info.nAlphaMax;
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Creates the alpha channel from a gray scale image.
+ */
+bool CxImage::AlphaSet(CxImage &from)
+{
+ if (!from.IsGrayScale() || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;
+ if (pAlpha==NULL) pAlpha = (uint8_t*)malloc(head.biWidth * head.biHeight);
+ uint8_t* src = from.info.pImage;
+ uint8_t* dst = pAlpha;
+ if (src==NULL || dst==NULL) return false;
+ for (int32_t y=0; y<head.biHeight; y++){
+ memcpy(dst,src,head.biWidth);
+ dst += head.biWidth;
+ src += from.info.dwEffWidth;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the alpha level for a single pixel
+ */
+void CxImage::AlphaSet(const int32_t x,const int32_t y,const uint8_t level)
+{
+ if (pAlpha && IsInside(x,y)) pAlpha[x+y*head.biWidth]=level;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the alpha level for a single pixel
+ */
+uint8_t CxImage::AlphaGet(const int32_t x,const int32_t y)
+{
+ if (pAlpha && IsInside(x,y)) return pAlpha[x+y*head.biWidth];
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns pointer to alpha data for pixel (x,y).
+ *
+ * \author ***bd*** 2.2004
+ */
+uint8_t* CxImage::AlphaGetPointer(const int32_t x,const int32_t y)
+{
+ if (pAlpha && IsInside(x,y)) return pAlpha+x+y*head.biWidth;
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Get alpha value without boundscheck (a bit faster). Pixel must be inside the image.
+ *
+ * \author ***bd*** 2.2004
+ */
+uint8_t CxImage::BlindAlphaGet(const int32_t x,const int32_t y)
+{
+#ifdef _DEBUG
+ if (!IsInside(x,y) || (pAlpha==0))
+ #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+ throw 0;
+ #else
+ return 0;
+ #endif
+#endif
+ return pAlpha[x+y*head.biWidth];
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Resets the alpha palette
+ */
+void CxImage::AlphaPaletteClear()
+{
+ RGBQUAD c;
+ for(uint16_t ip=0; ip<head.biClrUsed;ip++){
+ c=GetPaletteColor((uint8_t)ip);
+ c.rgbReserved=0;
+ SetPaletteColor((uint8_t)ip,c);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the image has a valid alpha palette.
+ */
+bool CxImage::AlphaPaletteIsValid()
+{
+ RGBQUAD c;
+ for(uint16_t ip=0; ip<head.biClrUsed;ip++){
+ c=GetPaletteColor((uint8_t)ip);
+ if (c.rgbReserved != 0) return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Blends the alpha channel and the alpha palette with the pixels. The result is a 24 bit image.
+ * The background color can be selected using SetTransColor().
+ */
+void CxImage::AlphaStrip()
+{
+ bool bAlphaPaletteIsValid = AlphaPaletteIsValid();
+ bool bAlphaIsValid = AlphaIsValid();
+ if (!(bAlphaIsValid || bAlphaPaletteIsValid)) return;
+ RGBQUAD c;
+ int32_t a, a1;
+ if (head.biBitCount==24){
+ for(int32_t y=0; y<head.biHeight; y++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ c = BlindGetPixelColor(x,y);
+ if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;
+ a1 = 256-a;
+ c.rgbBlue = (uint8_t)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);
+ c.rgbGreen = (uint8_t)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);
+ c.rgbRed = (uint8_t)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);
+ BlindSetPixelColor(x,y,c);
+ }
+ }
+ AlphaDelete();
+ } else {
+ CxImage tmp(head.biWidth,head.biHeight,24);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return;
+ }
+
+ for(int32_t y=0; y<head.biHeight; y++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ c = BlindGetPixelColor(x,y);
+ if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;
+ if (bAlphaPaletteIsValid) a=(c.rgbReserved*a)/255;
+ a1 = 256-a;
+ c.rgbBlue = (uint8_t)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);
+ c.rgbGreen = (uint8_t)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);
+ c.rgbRed = (uint8_t)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);
+ tmp.BlindSetPixelColor(x,y,c);
+ }
+ }
+ Transfer(tmp);
+ }
+ return;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::AlphaFlip()
+{
+ if (!pAlpha) return false;
+
+ uint8_t *buff = (uint8_t*)malloc(head.biWidth);
+ if (!buff) return false;
+
+ uint8_t *iSrc,*iDst;
+ iSrc = pAlpha + (head.biHeight-1)*head.biWidth;
+ iDst = pAlpha;
+ for (int32_t i=0; i<(head.biHeight/2); ++i)
+ {
+ memcpy(buff, iSrc, head.biWidth);
+ memcpy(iSrc, iDst, head.biWidth);
+ memcpy(iDst, buff, head.biWidth);
+ iSrc-=head.biWidth;
+ iDst+=head.biWidth;
+ }
+
+ free(buff);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::AlphaMirror()
+{
+ if (!pAlpha) return false;
+ uint8_t* pAlpha2 = (uint8_t*)malloc(head.biWidth * head.biHeight);
+ if (!pAlpha2) return false;
+ uint8_t *iSrc,*iDst;
+ int32_t wdt=head.biWidth-1;
+ iSrc=pAlpha + wdt;
+ iDst=pAlpha2;
+ for(int32_t y=0; y < head.biHeight; y++){
+ for(int32_t x=0; x <= wdt; x++)
+ *(iDst+x)=*(iSrc-x);
+ iSrc+=head.biWidth;
+ iDst+=head.biWidth;
+ }
+ free(pAlpha);
+ pAlpha=pAlpha2;
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Exports the alpha channel in a 8bpp grayscale image.
+ */
+bool CxImage::AlphaSplit(CxImage *dest)
+{
+ if (!pAlpha || !dest) return false;
+
+ CxImage tmp(head.biWidth,head.biHeight,8);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ uint8_t* src = pAlpha;
+ uint8_t* dst = tmp.info.pImage;
+ for (int32_t y=0; y<head.biHeight; y++){
+ memcpy(dst,src,head.biWidth);
+ dst += tmp.info.dwEffWidth;
+ src += head.biWidth;
+ }
+
+ tmp.SetGrayPalette();
+ dest->Transfer(tmp);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Exports the alpha palette channel in a 8bpp grayscale image.
+ */
+bool CxImage::AlphaPaletteSplit(CxImage *dest)
+{
+ if (!AlphaPaletteIsValid() || !dest) return false;
+
+ CxImage tmp(head.biWidth,head.biHeight,8);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ for(int32_t y=0; y<head.biHeight; y++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ tmp.BlindSetPixelIndex(x,y,BlindGetPixelColor(x,y).rgbReserved);
+ }
+ }
+
+ tmp.SetGrayPalette();
+ dest->Transfer(tmp);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Merge in the alpha layer the transparent color mask
+ * (previously set with SetTransColor or SetTransIndex)
+ */
+bool CxImage::AlphaFromTransparency()
+{
+ if (!IsValid() || !IsTransparent())
+ return false;
+
+ AlphaCreate();
+
+ for(int32_t y=0; y<head.biHeight; y++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ if (IsTransparent(x,y)){
+ AlphaSet(x,y,0);
+ }
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_ALPHA
diff --git a/archive/hge/CxImage/ximalyr.cpp b/archive/hge/CxImage/ximalyr.cpp new file mode 100644 index 0000000..23dc226 --- /dev/null +++ b/archive/hge/CxImage/ximalyr.cpp @@ -0,0 +1,116 @@ +// xImaLyr.cpp : Layers functions
+/* 21/04/2003 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_LAYERS
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * If the object is an internal layer, GetParent return its parent in the hierarchy.
+ */
+CxImage* CxImage::GetParent() const
+{
+ return info.pParent;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Number of layers allocated directly by the object.
+ */
+int32_t CxImage::GetNumLayers() const
+{
+ return info.nNumLayers;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Creates an empty layer. If position is less than 0, the new layer will be placed in the last position
+ */
+bool CxImage::LayerCreate(int32_t position)
+{
+ if ( position < 0 || position > info.nNumLayers ) position = info.nNumLayers;
+
+ CxImage** ptmp = new CxImage*[info.nNumLayers + 1];
+ if (ptmp==0) return false;
+
+ int32_t i=0;
+ for (int32_t n=0; n<info.nNumLayers; n++){
+ if (position == n){
+ ptmp[n] = new CxImage();
+ i=1;
+ }
+ ptmp[n+i]=ppLayers[n];
+ }
+ if (i==0) ptmp[info.nNumLayers] = new CxImage();
+
+ if (ptmp[position]){
+ ptmp[position]->info.pParent = this;
+ } else {
+ free(ptmp);
+ return false;
+ }
+
+ info.nNumLayers++;
+ delete [] ppLayers;
+ ppLayers = ptmp;
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Deletes a layer. If position is less than 0, the last layer will be deleted
+ */
+bool CxImage::LayerDelete(int32_t position)
+{
+ if ( position >= info.nNumLayers ) return false;
+ if ( position < 0) position = info.nNumLayers - 1;
+ if ( position < 0) return false;
+
+ if (info.nNumLayers>1){
+
+ CxImage** ptmp = new CxImage*[info.nNumLayers - 1];
+ if (ptmp==0) return false;
+
+ int32_t i=0;
+ for (int32_t n=0; n<info.nNumLayers; n++){
+ if (position == n){
+ delete ppLayers[n];
+ i=1;
+ }
+ ptmp[n]=ppLayers[n+i];
+ }
+
+ info.nNumLayers--;
+ delete [] ppLayers;
+ ppLayers = ptmp;
+
+ } else {
+ delete ppLayers[0];
+ delete [] ppLayers;
+ ppLayers = 0;
+ info.nNumLayers = 0;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::LayerDeleteAll()
+{
+ if (ppLayers) {
+ for(int32_t n=0; n<info.nNumLayers;n++){ delete ppLayers[n]; }
+ delete [] ppLayers; ppLayers=0; info.nNumLayers = 0;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns a pointer to a layer. If position is less than 0, the last layer will be returned
+ */
+CxImage* CxImage::GetLayer(int32_t position)
+{
+ if ( ppLayers == NULL) return NULL;
+ if ( info.nNumLayers == 0) return NULL;
+ if ( position >= info.nNumLayers ) return NULL;
+ if ( position < 0) position = info.nNumLayers - 1;
+ return ppLayers[position];
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_LAYERS
diff --git a/archive/hge/CxImage/ximamng.cpp b/archive/hge/CxImage/ximamng.cpp new file mode 100644 index 0000000..d5ea82e --- /dev/null +++ b/archive/hge/CxImage/ximamng.cpp @@ -0,0 +1,430 @@ +/*
+ * File: ximamng.cpp
+ * Purpose: Platform Independent MNG Image Class Loader and Writer
+ * Author: 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximamng.h"
+
+#if CXIMAGE_SUPPORT_MNG
+
+////////////////////////////////////////////////////////////////////////////////
+// callbacks for the mng decoder:
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+// memory allocation; data must be zeroed
+static mng_ptr
+mymngalloc( mng_size_t size )
+{
+ return (mng_ptr)calloc(1, size);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// memory deallocation
+static void mymngfree(mng_ptr p, mng_size_t size)
+{
+ free(p);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Stream open/close:
+// since the user is responsible for opening and closing the file,
+// we leave the default implementation open
+static mng_bool mymngopenstream(mng_handle mng) { return MNG_TRUE; }
+static mng_bool mymngopenstreamwrite(mng_handle mng) { return MNG_TRUE; }
+static mng_bool mymngclosestream(mng_handle mng) { return MNG_TRUE; }
+
+////////////////////////////////////////////////////////////////////////////////
+// feed data to the decoder
+static mng_bool mymngreadstream(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread)
+{
+ mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
+ // read the requested amount of data from the file
+ *bytesread = mymng->file->Read( buffer, sizeof(uint8_t), size);
+ return MNG_TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+static mng_bool mymngwritestream (mng_handle mng, mng_ptr pBuf, mng_uint32 iSize, mng_uint32 *iWritten)
+{
+ mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
+ // write it
+ *iWritten = mymng->file->Write (pBuf, 1, iSize);
+ return MNG_TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// the header's been read. set up the display stuff
+static mng_bool mymngprocessheader( mng_handle mng, mng_uint32 width, mng_uint32 height )
+{
+ // normally the image buffer is allocated here,
+ // but in this module we don't know nothing about
+ // the final environment.
+
+ mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
+
+ mymng->width = width;
+ mymng->height = height;
+ mymng->bpp = 24;
+ mymng->effwdt = ((((width * mymng->bpp) + 31) >> 5) << 2);
+
+ if (mng->bUseBKGD){
+ mymng->nBkgndIndex = 0;
+ mymng->nBkgndColor.rgbRed = mng->iBGred >> 8;
+ mymng->nBkgndColor.rgbGreen =mng->iBGgreen >> 8;
+ mymng->nBkgndColor.rgbBlue = mng->iBGblue >> 8;
+ }
+
+ mymng->image = (uint8_t*)malloc(height * mymng->effwdt);
+
+ // tell the mng decoder about our bit-depth choice
+#if CXIMAGE_SUPPORT_ALPHA
+ mng_set_canvasstyle( mng, MNG_CANVAS_RGB8_A8 );
+ mymng->alpha = (uint8_t*)malloc(height * width);
+#else
+ mng_set_canvasstyle( mng, MNG_CANVAS_BGR8);
+ mymng->alpha = NULL;
+#endif
+ return MNG_TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// return a row pointer for the decoder to fill
+static mng_ptr mymnggetcanvasline( mng_handle mng, mng_uint32 line )
+{
+ mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
+ return (mng_ptr)(mymng->image + (mymng->effwdt * (mymng->height - 1 - line)));
+}
+////////////////////////////////////////////////////////////////////////////////
+// return a row pointer for the decoder to fill for alpha channel
+static mng_ptr mymnggetalphaline( mng_handle mng, mng_uint32 line )
+{
+ mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
+ return (mng_ptr)(mymng->alpha + (mymng->width * (mymng->height - 1 - line)));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// timer
+static mng_uint32 mymnggetticks(mng_handle mng)
+{
+#ifdef WIN32
+ return (mng_uint32)GetTickCount();
+#else
+ return 0;
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Refresh: actual frame need to be updated (Invalidate)
+static mng_bool mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
+{
+// mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
+ return MNG_TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// interframe delay callback
+static mng_bool mymngsettimer(mng_handle mng, mng_uint32 msecs)
+{
+ mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
+ mymng->delay = msecs; // set the timer for when the decoder wants to be woken
+ return MNG_TRUE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+static mng_bool mymngerror(mng_handle mng, mng_int32 code, mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar text)
+{
+ return mng_cleanup(&mng); //<Arkadiy Olovyannikov>
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CxImage members
+////////////////////////////////////////////////////////////////////////////////
+CxImageMNG::CxImageMNG(): CxImage(CXIMAGE_FORMAT_MNG)
+{
+ hmng = NULL;
+ memset(&mnginfo,0,sizeof(mngstuff));
+ mnginfo.nBkgndIndex = -1;
+ mnginfo.speed = 1.0f;
+}
+////////////////////////////////////////////////////////////////////////////////
+CxImageMNG::~CxImageMNG()
+{
+ // cleanup and return
+ if (mnginfo.thread){ //close the animation thread
+ mnginfo.animation_enabled=0;
+ ResumeThread(mnginfo.thread);
+ WaitForSingleObject(mnginfo.thread,500);
+ CloseHandle(mnginfo.thread);
+ }
+ // free objects
+ if (mnginfo.image) free(mnginfo.image);
+ if (mnginfo.alpha) free(mnginfo.alpha);
+ if (hmng) mng_cleanup(&hmng); //be sure it's not needed any more. (active timers ?)
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageMNG::SetCallbacks(mng_handle mng)
+{
+ // set the callbacks
+ mng_setcb_errorproc(mng, mymngerror);
+ mng_setcb_openstream(mng, mymngopenstream);
+ mng_setcb_closestream(mng, mymngclosestream);
+ mng_setcb_readdata(mng, mymngreadstream);
+ mng_setcb_processheader(mng, mymngprocessheader);
+ mng_setcb_getcanvasline(mng, mymnggetcanvasline);
+ mng_setcb_refresh(mng, mymngrefresh);
+ mng_setcb_gettickcount(mng, mymnggetticks);
+ mng_setcb_settimer(mng, mymngsettimer);
+ mng_setcb_refresh(mng, mymngrefresh);
+ mng_setcb_getalphaline(mng, mymnggetalphaline);
+}
+////////////////////////////////////////////////////////////////////////////////
+// can't use the CxImage implementation because it looses mnginfo
+bool CxImageMNG::Load(const TCHAR * imageFileName){
+ FILE* hFile; //file handle to read the image
+#ifdef WIN32
+ if ((hFile=_tfopen(imageFileName,_T("rb")))==NULL) return false; // For UNICODE support
+#else
+ if ((hFile=fopen(imageFileName,"rb"))==NULL) return false;
+#endif
+ bool bOK = Decode(hFile);
+ fclose(hFile);
+ return bOK;
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageMNG::Decode(CxFile *hFile)
+{
+ if (hFile == NULL) return false;
+
+ cx_try
+ {
+ // set up the mng decoder for our stream
+ hmng = mng_initialize(&mnginfo, (mng_memalloc)mymngalloc, (mng_memfree)mymngfree, MNG_NULL);
+ if (hmng == NULL) cx_throw("could not initialize libmng");
+
+ // set the file we want to play
+ mnginfo.file = hFile;
+
+ // Set the colorprofile, lcms uses this:
+ mng_set_srgb(hmng, MNG_TRUE );
+ // Set white as background color:
+ uint16_t Red,Green,Blue;
+ Red = Green = Blue = (255 << 8) + 255;
+ mng_set_bgcolor(hmng, Red, Green, Blue );
+ // If PNG Background is available, use it:
+ mng_set_usebkgd(hmng, MNG_TRUE );
+
+ // No need to store chunks:
+ mng_set_storechunks(hmng, MNG_FALSE);
+ // No need to wait: straight reading
+ mng_set_suspensionmode(hmng, MNG_FALSE);
+
+ SetCallbacks(hmng);
+
+ mng_datap pData = (mng_datap)hmng;
+
+ // read in the image
+ info.nNumFrames=0;
+ int32_t retval=MNG_NOERROR;
+
+ retval = mng_readdisplay(hmng);
+
+ if (retval != MNG_NOERROR && retval != MNG_NEEDTIMERWAIT){
+ mng_store_error(hmng,retval,0,0);
+ if (hmng->zErrortext){
+ cx_throw(hmng->zErrortext);
+ } else {
+ cx_throw("Error in MNG file");
+ }
+ }
+
+ if (info.nEscape == -1) {
+ // Return output dimensions only
+ head.biWidth = hmng->iWidth;
+ head.biHeight = hmng->iHeight;
+ info.dwType = CXIMAGE_FORMAT_MNG;
+ return true;
+ }
+
+ // read all
+ while(pData->bReading){
+ retval = mng_display_resume(hmng);
+ info.nNumFrames++;
+ }
+
+ // single frame check:
+ if (retval != MNG_NEEDTIMERWAIT){
+ info.nNumFrames--;
+ } else {
+ mnginfo.animation=1;
+ }
+
+ if (info.nNumFrames<=0) info.nNumFrames=1;
+
+ if (mnginfo.animation_enabled==0){
+ // select the frame
+ if (info.nFrame>=0 && info.nFrame<info.nNumFrames){
+ for (int32_t n=0;n<info.nFrame;n++) mng_display_resume(hmng);
+ } else cx_throw("Error: frame not present in MNG file");
+ }
+
+ if (mnginfo.nBkgndIndex >= 0){
+ info.nBkgndIndex = mnginfo.nBkgndIndex;
+ info.nBkgndColor.rgbRed = mnginfo.nBkgndColor.rgbRed;
+ info.nBkgndColor.rgbGreen = mnginfo.nBkgndColor.rgbGreen;
+ info.nBkgndColor.rgbBlue = mnginfo.nBkgndColor.rgbBlue;
+ }
+
+ //store the newly created image
+ if (Create(mnginfo.width,mnginfo.height,mnginfo.bpp, CXIMAGE_FORMAT_MNG)){
+ memcpy(GetBits(), mnginfo.image, info.dwEffWidth * head.biHeight);
+#if CXIMAGE_SUPPORT_ALPHA
+ SwapRGB2BGR();
+ AlphaCreate();
+ if(AlphaIsValid() && mnginfo.alpha){
+ memcpy(AlphaGetPointer(),mnginfo.alpha,mnginfo.width * mnginfo.height);
+ }
+#endif
+ } else cx_throw("CxImageMNG::Decode cannot create image");
+
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageMNG::Encode(CxFile *hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ cx_try
+ {
+ if (head.biClrUsed != 0) cx_throw("MNG encoder can save only RGB images");
+ // set the file we want to play
+ mnginfo.file = hFile;
+ mnginfo.bpp = head.biBitCount;
+ mnginfo.effwdt = info.dwEffWidth;
+ mnginfo.height = head.biHeight;
+ mnginfo.width = head.biWidth;
+
+ mnginfo.image = (uint8_t*)malloc(head.biSizeImage);
+ if (mnginfo.image == NULL) cx_throw("could not allocate memory for MNG");
+ memcpy(mnginfo.image,info.pImage, head.biSizeImage);
+
+ // set up the mng decoder for our stream
+ hmng = mng_initialize(&mnginfo, (mng_memalloc)mymngalloc, (mng_memfree)mymngfree, MNG_NULL);
+ if (hmng == NULL) cx_throw("could not initialize libmng");
+
+ mng_setcb_openstream(hmng, mymngopenstreamwrite );
+ mng_setcb_closestream(hmng, mymngclosestream);
+ mng_setcb_writedata(hmng, mymngwritestream);
+
+ // Write File:
+ mng_create(hmng);
+ // Just a single Frame (save a normal PNG):
+ WritePNG(hmng, 0, 1 );
+ // Now write file:
+ mng_write(hmng);
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+// Writes a single PNG datastream
+void CxImageMNG::WritePNG( mng_handle hMNG, int32_t Frame, int32_t FrameCount )
+{
+ mngstuff *mymng = (mngstuff *)mng_get_userdata(hMNG);
+
+ int32_t OffsetX=0,OffsetY=0,OffsetW=mymng->width,OffsetH=mymng->height;
+
+ uint8_t *tmpbuffer = new uint8_t[ (mymng->effwdt+1) * mymng->height];
+ if( tmpbuffer == 0 ) return;
+
+ // Write DEFI chunk.
+ mng_putchunk_defi( hMNG, 0, 0, 0, MNG_TRUE, OffsetX, OffsetY, MNG_FALSE, 0, 0, 0, 0 );
+
+ // Write Header:
+ mng_putchunk_ihdr(
+ hMNG,
+ OffsetW, OffsetH,
+ MNG_BITDEPTH_8,
+ MNG_COLORTYPE_RGB,
+ MNG_COMPRESSION_DEFLATE,
+ MNG_FILTER_ADAPTIVE,
+ MNG_INTERLACE_NONE
+ );
+
+ // transfer data, add Filterbyte:
+ for( int32_t Row=0; Row<OffsetH; Row++ ){
+ // First Byte in each Scanline is Filterbyte: Currently 0 -> No Filter.
+ tmpbuffer[Row*(mymng->effwdt+1)]=0;
+ // Copy the scanline: (reverse order)
+ memcpy(tmpbuffer+Row*(mymng->effwdt+1)+1,
+ mymng->image+((OffsetH-1-(OffsetY+Row))*(mymng->effwdt))+OffsetX,mymng->effwdt);
+ // swap red and blue components
+ RGBtoBGR(tmpbuffer+Row*(mymng->effwdt+1)+1,mymng->effwdt);
+ }
+
+ // Compress data with ZLib (Deflate):
+ uint8_t *dstbuffer = new uint8_t[(mymng->effwdt+1)*OffsetH];
+ if( dstbuffer == 0 ) return;
+ uint32_t dstbufferSize=(mymng->effwdt+1)*OffsetH;
+
+ // Compress data:
+ if(Z_OK != compress2((Bytef *)dstbuffer,(ULONG *)&dstbufferSize,(const Bytef*)tmpbuffer,
+ (ULONG) (mymng->effwdt+1)*OffsetH,9 )) return;
+
+ // Write Data into MNG File:
+ mng_putchunk_idat( hMNG, dstbufferSize, (mng_ptr*)dstbuffer);
+ mng_putchunk_iend(hMNG);
+
+ // Free the stuff:
+ delete [] tmpbuffer;
+ delete [] dstbuffer;
+}
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImageMNG::Resume()
+{
+ if (MNG_NEEDTIMERWAIT == mng_display_resume(hmng)){
+ if (info.pImage==NULL){
+ Create(mnginfo.width,mnginfo.height,mnginfo.bpp, CXIMAGE_FORMAT_MNG);
+ }
+ if (IsValid()){
+ memcpy(GetBits(), mnginfo.image, info.dwEffWidth * head.biHeight);
+#if CXIMAGE_SUPPORT_ALPHA
+ SwapRGB2BGR();
+ AlphaCreate();
+ if(AlphaIsValid() && mnginfo.alpha){
+ memcpy(AlphaGetPointer(),mnginfo.alpha,mnginfo.width * mnginfo.height);
+ }
+#endif
+ }
+ } else {
+ mnginfo.animation_enabled = 0;
+ }
+ return mnginfo.animation_enabled;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageMNG::SetSpeed(float speed)
+{
+ if (speed>10.0) mnginfo.speed = 10.0f;
+ else if (speed<0.1) mnginfo.speed = 0.1f;
+ else mnginfo.speed=speed;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_MNG
diff --git a/archive/hge/CxImage/ximamng.h b/archive/hge/CxImage/ximamng.h new file mode 100644 index 0000000..9466fc2 --- /dev/null +++ b/archive/hge/CxImage/ximamng.h @@ -0,0 +1,88 @@ +/*
+ * File: ximamng.h
+ * Purpose: Declaration of the MNG Image Class
+ * Author: Davide Pizzolato - www.xdp.it
+ * Created: 2001
+ */
+/* ==========================================================
+ * CxImageMNG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Special thanks to Frank Haug <f.haug(at)jdm(dot)de> for suggestions and code.
+ *
+ * original mng.cpp code created by Nikolaus Brennig, November 14th, 2000. <virtualnik(at)nol(dot)at>
+ *
+ * LIBMNG Copyright (c) 2000,2001 Gerard Juyn (gerard@libmng.com)
+ * ==========================================================
+ */
+
+#if !defined(__ximaMNG_h)
+#define __ximaMNG_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_MNG
+
+//#define MNG_NO_CMS
+#define MNG_SUPPORT_DISPLAY
+#define MNG_SUPPORT_READ
+#define MNG_SUPPORT_WRITE
+#define MNG_ACCESS_CHUNKS
+#define MNG_STORE_CHUNKS
+
+extern "C" {
+#include "../mng/libmng.h"
+#include "../mng/libmng_data.h"
+#include "../mng/libmng_error.h"
+}
+
+//uint32_t _stdcall RunMNGThread(void *lpParam);
+
+typedef struct tagmngstuff
+{
+ CxFile *file;
+ uint8_t *image;
+ uint8_t *alpha;
+ HANDLE thread;
+ mng_uint32 delay;
+ mng_uint32 width;
+ mng_uint32 height;
+ mng_uint32 effwdt;
+ mng_int16 bpp;
+ mng_bool animation;
+ mng_bool animation_enabled;
+ float speed;
+ int32_t nBkgndIndex;
+ RGBQUAD nBkgndColor;
+} mngstuff;
+
+class CxImageMNG: public CxImage
+{
+public:
+ CxImageMNG();
+ ~CxImageMNG();
+
+ bool Load(const TCHAR * imageFileName);
+
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+ bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_MNG);}
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+ int32_t Resume();
+ void SetSpeed(float speed);
+
+ mng_handle hmng;
+ mngstuff mnginfo;
+protected:
+ void WritePNG(mng_handle hMNG, int32_t Frame, int32_t FrameCount );
+ void SetCallbacks(mng_handle mng);
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximapal.cpp b/archive/hge/CxImage/ximapal.cpp new file mode 100644 index 0000000..fe0615b --- /dev/null +++ b/archive/hge/CxImage/ximapal.cpp @@ -0,0 +1,834 @@ +// xImaPal.cpp : Palette and Pixel functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * returns the palette dimension in byte
+ */
+uint32_t CxImage::GetPaletteSize()
+{
+ return (head.biClrUsed * sizeof(RGBQUAD));
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPaletteColor(uint8_t idx, uint8_t r, uint8_t g, uint8_t b, uint8_t alpha)
+{
+ if ((pDib)&&(head.biClrUsed)){
+ uint8_t* iDst = (uint8_t*)(pDib) + sizeof(BITMAPINFOHEADER);
+ if (idx<head.biClrUsed){
+ int32_t ldx=idx*sizeof(RGBQUAD);
+ iDst[ldx++] = (uint8_t) b;
+ iDst[ldx++] = (uint8_t) g;
+ iDst[ldx++] = (uint8_t) r;
+ iDst[ldx] = (uint8_t) alpha;
+ info.last_c_isvalid = false;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPaletteColor(uint8_t idx, RGBQUAD c)
+{
+ if ((pDib)&&(head.biClrUsed)){
+ uint8_t* iDst = (uint8_t*)(pDib) + sizeof(BITMAPINFOHEADER);
+ if (idx<head.biClrUsed){
+ int32_t ldx=idx*sizeof(RGBQUAD);
+ iDst[ldx++] = (uint8_t) c.rgbBlue;
+ iDst[ldx++] = (uint8_t) c.rgbGreen;
+ iDst[ldx++] = (uint8_t) c.rgbRed;
+ iDst[ldx] = (uint8_t) c.rgbReserved;
+ info.last_c_isvalid = false;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPaletteColor(uint8_t idx, COLORREF cr)
+{
+ if ((pDib)&&(head.biClrUsed)){
+ uint8_t* iDst = (uint8_t*)(pDib) + sizeof(BITMAPINFOHEADER);
+ if (idx<head.biClrUsed){
+ int32_t ldx=idx*sizeof(RGBQUAD);
+ iDst[ldx++] = (uint8_t) GetBValue(cr);
+ iDst[ldx++] = (uint8_t) GetGValue(cr);
+ iDst[ldx++] = (uint8_t) GetRValue(cr);
+ iDst[ldx] = (uint8_t) 0;
+ info.last_c_isvalid = false;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * returns the pointer to the first palette index
+ */
+RGBQUAD* CxImage::GetPalette() const
+{
+ if ((pDib)&&(head.biClrUsed))
+ return (RGBQUAD*)((uint8_t*)pDib + sizeof(BITMAPINFOHEADER));
+ return NULL;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the color of the specified index.
+ */
+RGBQUAD CxImage::GetPaletteColor(uint8_t idx)
+{
+ RGBQUAD rgb = {0,0,0,0};
+ if ((pDib)&&(head.biClrUsed)){
+ uint8_t* iDst = (uint8_t*)(pDib) + sizeof(BITMAPINFOHEADER);
+ if (idx<head.biClrUsed){
+ int32_t ldx=idx*sizeof(RGBQUAD);
+ rgb.rgbBlue = iDst[ldx++];
+ rgb.rgbGreen=iDst[ldx++];
+ rgb.rgbRed =iDst[ldx++];
+ rgb.rgbReserved = iDst[ldx];
+ }
+ }
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the palette index of the specified pixel.
+ */
+uint8_t CxImage::GetPixelIndex(int32_t x,int32_t y)
+{
+ if ((pDib==NULL)||(head.biClrUsed==0)) return 0;
+
+ if ((x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) {
+ if (info.nBkgndIndex >= 0) return (uint8_t)info.nBkgndIndex;
+ else return *info.pImage;
+ }
+ if (head.biBitCount==8){
+ return info.pImage[y*info.dwEffWidth + x];
+ } else {
+ uint8_t pos;
+ uint8_t iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];
+ if (head.biBitCount==4){
+ pos = (uint8_t)(4*(1-x%2));
+ iDst &= (0x0F<<pos);
+ return (uint8_t)(iDst >> pos);
+ } else if (head.biBitCount==1){
+ pos = (uint8_t)(7-x%8);
+ iDst &= (0x01<<pos);
+ return (uint8_t)(iDst >> pos);
+ }
+ }
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint8_t CxImage::BlindGetPixelIndex(const int32_t x,const int32_t y)
+{
+#ifdef _DEBUG
+ if ((pDib==NULL) || (head.biClrUsed==0) || !IsInside(x,y))
+ #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+ throw 0;
+ #else
+ return 0;
+ #endif
+#endif
+
+ if (head.biBitCount==8){
+ return info.pImage[y*info.dwEffWidth + x];
+ } else {
+ uint8_t pos;
+ uint8_t iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];
+ if (head.biBitCount==4){
+ pos = (uint8_t)(4*(1-x%2));
+ iDst &= (0x0F<<pos);
+ return (uint8_t)(iDst >> pos);
+ } else if (head.biBitCount==1){
+ pos = (uint8_t)(7-x%8);
+ iDst &= (0x01<<pos);
+ return (uint8_t)(iDst >> pos);
+ }
+ }
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::GetPixelColor(int32_t x,int32_t y, bool bGetAlpha)
+{
+// RGBQUAD rgb={0,0,0,0};
+ RGBQUAD rgb=info.nBkgndColor; //<mpwolski>
+ if ((pDib==NULL)||(x<0)||(y<0)||
+ (x>=head.biWidth)||(y>=head.biHeight)){
+ if (info.nBkgndIndex >= 0){
+ if (head.biBitCount<24) return GetPaletteColor((uint8_t)info.nBkgndIndex);
+ else return info.nBkgndColor;
+ } else if (pDib) return GetPixelColor(0,0);
+ return rgb;
+ }
+
+ if (head.biClrUsed){
+ rgb = GetPaletteColor(BlindGetPixelIndex(x,y));
+ } else {
+ uint8_t* iDst = info.pImage + y*info.dwEffWidth + x*3;
+ rgb.rgbBlue = *iDst++;
+ rgb.rgbGreen= *iDst++;
+ rgb.rgbRed = *iDst;
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);
+#else
+ rgb.rgbReserved = 0;
+#endif //CXIMAGE_SUPPORT_ALPHA
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * This is (a bit) faster version of GetPixelColor.
+ * It tests bounds only in debug mode (_DEBUG defined).
+ *
+ * It is an error to request out-of-borders pixel with this method.
+ * In DEBUG mode an exception will be thrown, and data will be violated in non-DEBUG mode.
+ * \author ***bd*** 2.2004
+ */
+RGBQUAD CxImage::BlindGetPixelColor(const int32_t x,const int32_t y, bool bGetAlpha)
+{
+ RGBQUAD rgb;
+#ifdef _DEBUG
+ if ((pDib==NULL) || !IsInside(x,y))
+ #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+ throw 0;
+ #else
+ {rgb.rgbReserved = 0; return rgb;}
+ #endif
+#endif
+
+ if (head.biClrUsed){
+ rgb = GetPaletteColor(BlindGetPixelIndex(x,y));
+ } else {
+ uint8_t* iDst = info.pImage + y*info.dwEffWidth + x*3;
+ rgb.rgbBlue = *iDst++;
+ rgb.rgbGreen= *iDst++;
+ rgb.rgbRed = *iDst;
+ rgb.rgbReserved = 0; //needed for images without alpha layer
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);
+#else
+ rgb.rgbReserved = 0;
+#endif //CXIMAGE_SUPPORT_ALPHA
+ return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+uint8_t CxImage::GetPixelGray(int32_t x, int32_t y)
+{
+ RGBQUAD color = GetPixelColor(x,y);
+ return (uint8_t)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::BlindSetPixelIndex(int32_t x,int32_t y,uint8_t i)
+{
+#ifdef _DEBUG
+ if ((pDib==NULL)||(head.biClrUsed==0)||
+ (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight))
+ #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+ throw 0;
+ #else
+ return;
+ #endif
+#endif
+
+ if (head.biBitCount==8){
+ info.pImage[y*info.dwEffWidth + x]=i;
+ return;
+ } else {
+ uint8_t pos;
+ uint8_t* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);
+ if (head.biBitCount==4){
+ pos = (uint8_t)(4*(1-x%2));
+ *iDst &= ~(0x0F<<pos);
+ *iDst |= ((i & 0x0F)<<pos);
+ return;
+ } else if (head.biBitCount==1){
+ pos = (uint8_t)(7-x%8);
+ *iDst &= ~(0x01<<pos);
+ *iDst |= ((i & 0x01)<<pos);
+ return;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPixelIndex(int32_t x,int32_t y,uint8_t i)
+{
+ if ((pDib==NULL)||(head.biClrUsed==0)||
+ (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) return ;
+
+ if (head.biBitCount==8){
+ info.pImage[y*info.dwEffWidth + x]=i;
+ return;
+ } else {
+ uint8_t pos;
+ uint8_t* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);
+ if (head.biBitCount==4){
+ pos = (uint8_t)(4*(1-x%2));
+ *iDst &= ~(0x0F<<pos);
+ *iDst |= ((i & 0x0F)<<pos);
+ return;
+ } else if (head.biBitCount==1){
+ pos = (uint8_t)(7-x%8);
+ *iDst &= ~(0x01<<pos);
+ *iDst |= ((i & 0x01)<<pos);
+ return;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPixelColor(int32_t x,int32_t y,COLORREF cr)
+{
+ SetPixelColor(x,y,RGBtoRGBQUAD(cr));
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::BlindSetPixelColor(int32_t x,int32_t y,RGBQUAD c, bool bSetAlpha)
+{
+#ifdef _DEBUG
+ if ((pDib==NULL)||(x<0)||(y<0)||
+ (x>=head.biWidth)||(y>=head.biHeight))
+ #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+ throw 0;
+ #else
+ return;
+ #endif
+#endif
+ if (head.biClrUsed)
+ BlindSetPixelIndex(x,y,GetNearestIndex(c));
+ else {
+ uint8_t* iDst = info.pImage + y*info.dwEffWidth + x*3;
+ *iDst++ = c.rgbBlue;
+ *iDst++ = c.rgbGreen;
+ *iDst = c.rgbRed;
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);
+#endif //CXIMAGE_SUPPORT_ALPHA
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPixelColor(int32_t x,int32_t y,RGBQUAD c, bool bSetAlpha)
+{
+ if ((pDib==NULL)||(x<0)||(y<0)||
+ (x>=head.biWidth)||(y>=head.biHeight)) return;
+ if (head.biClrUsed)
+ BlindSetPixelIndex(x,y,GetNearestIndex(c));
+ else {
+ uint8_t* iDst = info.pImage + y*info.dwEffWidth + x*3;
+ *iDst++ = c.rgbBlue;
+ *iDst++ = c.rgbGreen;
+ *iDst = c.rgbRed;
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);
+#endif //CXIMAGE_SUPPORT_ALPHA
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Blends the current pixel color with a new color.
+ * \param x,y = pixel
+ * \param c = new color
+ * \param blend = can be from 0 (no effect) to 1 (full effect).
+ * \param bSetAlpha = if true, blends also the alpha component stored in c.rgbReserved
+ */
+void CxImage::BlendPixelColor(int32_t x,int32_t y,RGBQUAD c, float blend, bool bSetAlpha)
+{
+ if ((pDib==NULL)||(x<0)||(y<0)||
+ (x>=head.biWidth)||(y>=head.biHeight)) return;
+
+ int32_t a0 = (int32_t)(256*blend);
+ int32_t a1 = 256 - a0;
+
+ RGBQUAD c0 = BlindGetPixelColor(x,y);
+ c.rgbRed = (uint8_t)((c.rgbRed * a0 + c0.rgbRed * a1)>>8);
+ c.rgbBlue = (uint8_t)((c.rgbBlue * a0 + c0.rgbBlue * a1)>>8);
+ c.rgbGreen = (uint8_t)((c.rgbGreen * a0 + c0.rgbGreen * a1)>>8);
+
+ if (head.biClrUsed)
+ BlindSetPixelIndex(x,y,GetNearestIndex(c));
+ else {
+ uint8_t* iDst = info.pImage + y*info.dwEffWidth + x*3;
+ *iDst++ = c.rgbBlue;
+ *iDst++ = c.rgbGreen;
+ *iDst = c.rgbRed;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the best palette index that matches a specified color.
+ */
+uint8_t CxImage::GetNearestIndex(RGBQUAD c)
+{
+ if ((pDib==NULL)||(head.biClrUsed==0)) return 0;
+
+ // <RJ> check matching with the previous result
+ if (info.last_c_isvalid && (*(int32_t*)&info.last_c == *(int32_t*)&c)) return info.last_c_index;
+ info.last_c = c;
+ info.last_c_isvalid = true;
+
+ uint8_t* iDst = (uint8_t*)(pDib) + sizeof(BITMAPINFOHEADER);
+ int32_t distance=200000;
+ int32_t i,j = 0;
+ int32_t k,l;
+ int32_t m = (int32_t)(head.biClrImportant==0 ? head.biClrUsed : head.biClrImportant);
+ for(i=0,l=0;i<m;i++,l+=sizeof(RGBQUAD)){
+ k = (iDst[l]-c.rgbBlue)*(iDst[l]-c.rgbBlue)+
+ (iDst[l+1]-c.rgbGreen)*(iDst[l+1]-c.rgbGreen)+
+ (iDst[l+2]-c.rgbRed)*(iDst[l+2]-c.rgbRed);
+// k = abs(iDst[l]-c.rgbBlue)+abs(iDst[l+1]-c.rgbGreen)+abs(iDst[l+2]-c.rgbRed);
+ if (k==0){
+ j=i;
+ break;
+ }
+ if (k<distance){
+ distance=k;
+ j=i;
+ }
+ }
+ info.last_c_index = (uint8_t)j;
+ return (uint8_t)j;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * swaps the blue and red components (for RGB images)
+ * \param buffer : pointer to the pixels
+ * \param length : number of bytes to swap. lenght may not exceed the scan line.
+ */
+void CxImage::RGBtoBGR(uint8_t *buffer, int32_t length)
+{
+ if (buffer && (head.biClrUsed==0)){
+ uint8_t temp;
+ length = min(length,(int32_t)info.dwEffWidth);
+ length = min(length,(int32_t)(3*head.biWidth));
+ for (int32_t i=0;i<length;i+=3){
+ temp = buffer[i]; buffer[i] = buffer[i+2]; buffer[i+2] = temp;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoRGBQUAD(COLORREF cr)
+{
+ RGBQUAD c;
+ c.rgbRed = GetRValue(cr); /* get R, G, and B out of uint32_t */
+ c.rgbGreen = GetGValue(cr);
+ c.rgbBlue = GetBValue(cr);
+ c.rgbReserved=0;
+ return c;
+}
+////////////////////////////////////////////////////////////////////////////////
+COLORREF CxImage::RGBQUADtoRGB (RGBQUAD c)
+{
+ return RGB(c.rgbRed,c.rgbGreen,c.rgbBlue);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the color of the specified index.
+ * \param i = palette index
+ * \param r, g, b = output color channels
+ */
+bool CxImage::GetPaletteColor(uint8_t i, uint8_t* r, uint8_t* g, uint8_t* b)
+{
+ RGBQUAD* ppal=GetPalette();
+ if (ppal) {
+ *r = ppal[i].rgbRed;
+ *g = ppal[i].rgbGreen;
+ *b = ppal[i].rgbBlue;
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPalette(uint32_t n, uint8_t *r, uint8_t *g, uint8_t *b)
+{
+ if ((!r)||(pDib==NULL)||(head.biClrUsed==0)) return;
+ if (!g) g = r;
+ if (!b) b = g;
+ RGBQUAD* ppal=GetPalette();
+ uint32_t m=min(n,head.biClrUsed);
+ for (uint32_t i=0; i<m;i++){
+ ppal[i].rgbRed=r[i];
+ ppal[i].rgbGreen=g[i];
+ ppal[i].rgbBlue=b[i];
+ }
+ info.last_c_isvalid = false;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPalette(rgb_color *rgb,uint32_t nColors)
+{
+ if ((!rgb)||(pDib==NULL)||(head.biClrUsed==0)) return;
+ RGBQUAD* ppal=GetPalette();
+ uint32_t m=min(nColors,head.biClrUsed);
+ for (uint32_t i=0; i<m;i++){
+ ppal[i].rgbRed=rgb[i].r;
+ ppal[i].rgbGreen=rgb[i].g;
+ ppal[i].rgbBlue=rgb[i].b;
+ }
+ info.last_c_isvalid = false;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPalette(RGBQUAD* pPal,uint32_t nColors)
+{
+ if ((pPal==NULL)||(pDib==NULL)||(head.biClrUsed==0)) return;
+ memcpy(GetPalette(),pPal,min(GetPaletteSize(),nColors*sizeof(RGBQUAD)));
+ info.last_c_isvalid = false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets (or replaces) the palette to gray scale palette.
+ * The function doesn't change the pixels; for standard
+ * gray scale conversion use GrayScale().
+ */
+void CxImage::SetGrayPalette()
+{
+ if ((pDib==NULL)||(head.biClrUsed==0)) return;
+ RGBQUAD* pal=GetPalette();
+ for (uint32_t ni=0;ni<head.biClrUsed;ni++)
+ pal[ni].rgbBlue=pal[ni].rgbGreen = pal[ni].rgbRed = (uint8_t)(ni*(255/(head.biClrUsed-1)));
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Colorize the palette.
+ * \sa Colorize
+ */
+void CxImage::BlendPalette(COLORREF cr,int32_t perc)
+{
+ if ((pDib==NULL)||(head.biClrUsed==0)) return;
+ uint8_t* iDst = (uint8_t*)(pDib) + sizeof(BITMAPINFOHEADER);
+ uint32_t i,r,g,b;
+ RGBQUAD* pPal=(RGBQUAD*)iDst;
+ r = GetRValue(cr);
+ g = GetGValue(cr);
+ b = GetBValue(cr);
+ if (perc>100) perc=100;
+ for(i=0;i<head.biClrUsed;i++){
+ pPal[i].rgbBlue=(uint8_t)((pPal[i].rgbBlue*(100-perc)+b*perc)/100);
+ pPal[i].rgbGreen =(uint8_t)((pPal[i].rgbGreen*(100-perc)+g*perc)/100);
+ pPal[i].rgbRed =(uint8_t)((pPal[i].rgbRed*(100-perc)+r*perc)/100);
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns true if the image has 256 colors and a linear grey scale palette.
+ */
+bool CxImage::IsGrayScale()
+{
+ RGBQUAD* ppal=GetPalette();
+ if(!(pDib && ppal && head.biClrUsed)) return false;
+ for(uint32_t i=0;i<head.biClrUsed;i++){
+ if (ppal[i].rgbBlue!=i || ppal[i].rgbGreen!=i || ppal[i].rgbRed!=i) return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * swap two indexes in the image and their colors in the palette
+ */
+void CxImage::SwapIndex(uint8_t idx1, uint8_t idx2)
+{
+ RGBQUAD* ppal=GetPalette();
+ if(!(pDib && ppal)) return;
+ //swap the colors
+ RGBQUAD tempRGB=GetPaletteColor(idx1);
+ SetPaletteColor(idx1,GetPaletteColor(idx2));
+ SetPaletteColor(idx2,tempRGB);
+ //swap the pixels
+ uint8_t idx;
+ for(int32_t y=0; y < head.biHeight; y++){
+ for(int32_t x=0; x < head.biWidth; x++){
+ idx=BlindGetPixelIndex(x,y);
+ if (idx==idx1) BlindSetPixelIndex(x,y,idx2);
+ if (idx==idx2) BlindSetPixelIndex(x,y,idx1);
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * swap Red and Blue colors
+ */
+void CxImage::SwapRGB2BGR()
+{
+ if (!pDib) return;
+
+ if (head.biClrUsed){
+ RGBQUAD* ppal=GetPalette();
+ uint8_t b;
+ if(!ppal) return;
+ for(uint16_t a=0;a<head.biClrUsed;a++){
+ b=ppal[a].rgbBlue; ppal[a].rgbBlue=ppal[a].rgbRed; ppal[a].rgbRed=b;
+ }
+ } else {
+ for(int32_t y=0;y<head.biHeight;y++){
+ RGBtoBGR(GetBits(y),3*head.biWidth);
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::IsTransparent(int32_t x, int32_t y)
+{
+ if (!pDib) return false;
+
+ if (info.nBkgndIndex>=0){
+ if (head.biClrUsed){
+ if (GetPixelIndex(x,y) == info.nBkgndIndex) return true;
+ } else {
+ RGBQUAD ct = info.nBkgndColor;
+ RGBQUAD c = GetPixelColor(x,y,false);
+ if (*(int32_t*)&c==*(int32_t*)&ct) return true;
+ }
+ }
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pAlpha) return AlphaGet(x,y)==0;
+#endif
+
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::GetTransparentMask(CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ CxImage tmp;
+ tmp.Create(head.biWidth, head.biHeight, 1, GetType());
+ tmp.SetStdPalette();
+ tmp.Clear(0);
+
+ for(int32_t y=0; y<head.biHeight; y++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ if (IsTransparent(x,y)){
+ tmp.BlindSetPixelIndex(x,y,1);
+ }
+ }
+ }
+
+ if (iDst) iDst->Transfer(tmp);
+ else Transfer(tmp);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if image has the same palette, if any.
+ * \param img = image to compare.
+ * \param bCheckAlpha = check also the rgbReserved field.
+ */
+bool CxImage::IsSamePalette(CxImage &img, bool bCheckAlpha)
+{
+ if (head.biClrUsed != img.head.biClrUsed)
+ return false;
+ if (head.biClrUsed == 0)
+ return false;
+
+ RGBQUAD c1,c2;
+ for (uint32_t n=0; n<head.biClrUsed; n++){
+ c1 = GetPaletteColor((uint8_t)n);
+ c2 = img.GetPaletteColor((uint8_t)n);
+ if (c1.rgbRed != c2.rgbRed) return false;
+ if (c1.rgbBlue != c2.rgbBlue) return false;
+ if (c1.rgbGreen != c2.rgbGreen) return false;
+ if (bCheckAlpha && (c1.rgbReserved != c2.rgbReserved)) return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetClrImportant
+ */
+uint32_t CxImage::GetClrImportant() const
+{
+ return head.biClrImportant;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * sets the maximum number of colors that some functions like
+ * DecreaseBpp() or GetNearestIndex() will use on indexed images
+ * \param ncolors should be less than 2^bpp,
+ * or 0 if all the colors are important.
+ */
+void CxImage::SetClrImportant(uint32_t ncolors)
+{
+ if (ncolors==0 || ncolors>256) {
+ head.biClrImportant = 0;
+ return;
+ }
+
+ switch(head.biBitCount){
+ case 1:
+ head.biClrImportant = min(ncolors,2);
+ break;
+ case 4:
+ head.biClrImportant = min(ncolors,16);
+ break;
+ case 8:
+ head.biClrImportant = ncolors;
+ break;
+ }
+ return;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns pointer to pixel. Currently implemented only for truecolor images.
+ *
+ * \param x,y - coordinates
+ *
+ * \return pointer to first byte of pixel data
+ *
+ * \author ***bd*** 2.2004
+ */
+void* CxImage::BlindGetPixelPointer(const int32_t x, const int32_t y)
+{
+#ifdef _DEBUG
+ if ((pDib==NULL) || !IsInside(x,y))
+ #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+ throw 0;
+ #else
+ return 0;
+ #endif
+#endif
+ if (!IsIndexed())
+ return info.pImage + y*info.dwEffWidth + x*3;
+ else
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::DrawLine(int32_t StartX, int32_t EndX, int32_t StartY, int32_t EndY, COLORREF cr)
+{
+ DrawLine(StartX, EndX, StartY, EndY, RGBtoRGBQUAD(cr));
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::DrawLine(int32_t StartX, int32_t EndX, int32_t StartY, int32_t EndY, RGBQUAD color, bool bSetAlpha)
+{
+ if (!pDib) return;
+ //////////////////////////////////////////////////////
+ // Draws a line using the Bresenham line algorithm
+ // Thanks to Jordan DeLozier <JDL>
+ //////////////////////////////////////////////////////
+ int32_t x1 = StartX;
+ int32_t y1 = StartY;
+ int32_t x = x1; // Start x off at the first pixel
+ int32_t y = y1; // Start y off at the first pixel
+ int32_t x2 = EndX;
+ int32_t y2 = EndY;
+
+ int32_t xinc1,xinc2,yinc1,yinc2; // Increasing values
+ int32_t den, num, numadd,numpixels;
+ int32_t deltax = abs(x2 - x1); // The difference between the x's
+ int32_t deltay = abs(y2 - y1); // The difference between the y's
+
+ // Get Increasing Values
+ if (x2 >= x1) { // The x-values are increasing
+ xinc1 = 1;
+ xinc2 = 1;
+ } else { // The x-values are decreasing
+ xinc1 = -1;
+ xinc2 = -1;
+ }
+
+ if (y2 >= y1) { // The y-values are increasing
+ yinc1 = 1;
+ yinc2 = 1;
+ } else { // The y-values are decreasing
+ yinc1 = -1;
+ yinc2 = -1;
+ }
+
+ // Actually draw the line
+ if (deltax >= deltay) // There is at least one x-value for every y-value
+ {
+ xinc1 = 0; // Don't change the x when numerator >= denominator
+ yinc2 = 0; // Don't change the y for every iteration
+ den = deltax;
+ num = deltax / 2;
+ numadd = deltay;
+ numpixels = deltax; // There are more x-values than y-values
+ }
+ else // There is at least one y-value for every x-value
+ {
+ xinc2 = 0; // Don't change the x for every iteration
+ yinc1 = 0; // Don't change the y when numerator >= denominator
+ den = deltay;
+ num = deltay / 2;
+ numadd = deltax;
+ numpixels = deltay; // There are more y-values than x-values
+ }
+
+ for (int32_t curpixel = 0; curpixel <= numpixels; curpixel++)
+ {
+ // Draw the current pixel
+ SetPixelColor(x,y,color,bSetAlpha);
+
+ num += numadd; // Increase the numerator by the top of the fraction
+ if (num >= den) // Check if numerator >= denominator
+ {
+ num -= den; // Calculate the new numerator value
+ x += xinc1; // Change the x as appropriate
+ y += yinc1; // Change the y as appropriate
+ }
+ x += xinc2; // Change the x as appropriate
+ y += yinc2; // Change the y as appropriate
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets a palette with standard colors for 1, 4 and 8 bpp images.
+ */
+void CxImage::SetStdPalette()
+{
+ if (!pDib) return;
+ switch (head.biBitCount){
+ case 8:
+ {
+ const uint8_t pal256[1024] = {0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0,
+ 192,220,192,0,240,202,166,0,212,240,255,0,177,226,255,0,142,212,255,0,107,198,255,0,
+ 72,184,255,0,37,170,255,0,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,
+ 50,80,0,212,227,255,0,177,199,255,0,142,171,255,0,107,143,255,0,72,115,255,0,37,87,255,0,0,
+ 85,255,0,0,73,220,0,0,61,185,0,0,49,150,0,0,37,115,0,0,25,80,0,212,212,255,0,177,177,255,0,
+ 142,142,255,0,107,107,255,0,72,72,255,0,37,37,255,0,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,
+ 0,0,115,0,0,0,80,0,227,212,255,0,199,177,255,0,171,142,255,0,143,107,255,0,115,72,255,0,
+ 87,37,255,0,85,0,255,0,73,0,220,0,61,0,185,0,49,0,150,0,37,0,115,0,25,0,80,0,240,212,255,0,
+ 226,177,255,0,212,142,255,0,198,107,255,0,184,72,255,0,170,37,255,0,170,0,255,0,146,0,220,0,
+ 122,0,185,0,98,0,150,0,74,0,115,0,50,0,80,0,255,212,255,0,255,177,255,0,255,142,255,0,255,107,255,0,
+ 255,72,255,0,255,37,255,0,254,0,254,0,220,0,220,0,185,0,185,0,150,0,150,0,115,0,115,0,80,0,80,0,
+ 255,212,240,0,255,177,226,0,255,142,212,0,255,107,198,0,255,72,184,0,255,37,170,0,255,0,170,0,
+ 220,0,146,0,185,0,122,0,150,0,98,0,115,0,74,0,80,0,50,0,255,212,227,0,255,177,199,0,255,142,171,0,
+ 255,107,143,0,255,72,115,0,255,37,87,0,255,0,85,0,220,0,73,0,185,0,61,0,150,0,49,0,115,0,37,0,
+ 80,0,25,0,255,212,212,0,255,177,177,0,255,142,142,0,255,107,107,0,255,72,72,0,255,37,37,0,254,0,
+ 0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,0,255,227,212,0,255,199,177,0,255,171,142,0,
+ 255,143,107,0,255,115,72,0,255,87,37,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,115,37,0,
+ 0,80,25,0,0,255,240,212,0,255,226,177,0,255,212,142,0,255,198,107,0,255,184,72,0,255,170,37,0,
+ 255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,0,255,255,212,0,255,255,177,0,
+ 255,255,142,0,255,255,107,0,255,255,72,0,255,255,37,0,254,254,0,0,220,220,0,0,185,185,0,0,150,150,0,
+ 0,115,115,0,0,80,80,0,0,240,255,212,0,226,255,177,0,212,255,142,0,198,255,107,0,184,255,72,0,
+ 170,255,37,0,170,255,0,0,146,220,0,0,122,185,0,0,98,150,0,0,74,115,0,0,50,80,0,0,227,255,212,0,
+ 199,255,177,0,171,255,142,0,143,255,107,0,115,255,72,0,87,255,37,0,85,255,0,0,73,220,0,0,61,185,0,
+ 0,49,150,0,0,37,115,0,0,25,80,0,0,212,255,212,0,177,255,177,0,142,255,142,0,107,255,107,0,72,255,72,0,
+ 37,255,37,0,0,254,0,0,0,220,0,0,0,185,0,0,0,150,0,0,0,115,0,0,0,80,0,0,212,255,227,0,177,255,199,0,
+ 142,255,171,0,107,255,143,0,72,255,115,0,37,255,87,0,0,255,85,0,0,220,73,0,0,185,61,0,0,150,49,0,0,
+ 115,37,0,0,80,25,0,212,255,240,0,177,255,226,0,142,255,212,0,107,255,198,0,72,255,184,0,37,255,170,0,
+ 0,255,170,0,0,220,146,0,0,185,122,0,0,150,98,0,0,115,74,0,0,80,50,0,212,255,255,0,177,255,255,0,
+ 142,255,255,0,107,255,255,0,72,255,255,0,37,255,255,0,0,254,254,0,0,220,220,0,0,185,185,0,0,
+ 150,150,0,0,115,115,0,0,80,80,0,242,242,242,0,230,230,230,0,218,218,218,0,206,206,206,0,194,194,194,0,
+ 182,182,182,0,170,170,170,0,158,158,158,0,146,146,146,0,134,134,134,0,122,122,122,0,110,110,110,0,
+ 98,98,98,0,86,86,86,0,74,74,74,0,62,62,62,0,50,50,50,0,38,38,38,0,26,26,26,0,14,14,14,0,240,251,255,0,
+ 164,160,160,0,128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0};
+ memcpy(GetPalette(),pal256,1024);
+ break;
+ }
+ case 4:
+ {
+ const uint8_t pal16[64]={0,0,0,0,0,0,128,0,0,128,0,0,0,128,128,0,128,0,0,0,128,0,128,0,128,128,0,0,192,192,192,0,
+ 128,128,128,0,0,0,255,0,0,255,0,0,0,255,255,0,255,0,0,0,255,0,255,0,255,255,0,0,255,255,255,0};
+ memcpy(GetPalette(),pal16,64);
+ break;
+ }
+ case 1:
+ {
+ const uint8_t pal2[8]={0,0,0,0,255,255,255,0};
+ memcpy(GetPalette(),pal2,8);
+ break;
+ }
+ }
+ info.last_c_isvalid = false;
+ return;
+}
+////////////////////////////////////////////////////////////////////////////////
diff --git a/archive/hge/CxImage/ximapcx.cpp b/archive/hge/CxImage/ximapcx.cpp new file mode 100644 index 0000000..2fa2f5d --- /dev/null +++ b/archive/hge/CxImage/ximapcx.cpp @@ -0,0 +1,479 @@ +/*
+ * File: ximapcx.cpp
+ * Purpose: Platform Independent PCX Image Class Loader and Writer
+ * 05/Jan/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ *
+ * based on ppmtopcx.c - convert a portable pixmap to PCX
+ * Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
+ * based on ppmtopcx.c by Michael Davidson
+ */
+
+#include "ximapcx.h"
+
+#if CXIMAGE_SUPPORT_PCX
+
+#include "xmemfile.h"
+
+#define PCX_MAGIC 0X0A // PCX magic number
+#define PCX_256_COLORS 0X0C // magic number for 256 colors
+#define PCX_HDR_SIZE 128 // size of PCX header
+#define PCX_MAXCOLORS 256
+#define PCX_MAXPLANES 4
+#define PCX_MAXVAL 255
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImagePCX::Decode(CxFile *hFile)
+{
+ if (hFile == NULL) return false;
+
+ PCXHEADER pcxHeader;
+ int32_t i, x, y, y2, nbytes, count, Height, Width;
+ uint8_t c, ColorMap[PCX_MAXCOLORS][3];
+ uint8_t *pcximage = NULL, *lpHead1 = NULL, *lpHead2 = NULL;
+ uint8_t *pcxplanes, *pcxpixels;
+
+ cx_try
+ {
+ if (hFile->Read(&pcxHeader,sizeof(PCXHEADER),1)==0) cx_throw("Can't read PCX image");
+
+ PCX_toh(&pcxHeader);
+
+ if (pcxHeader.Manufacturer != PCX_MAGIC) cx_throw("Error: Not a PCX file");
+ // Check for PCX run length encoding
+ if (pcxHeader.Encoding != 1) cx_throw("PCX file has unknown encoding scheme");
+
+ Width = (pcxHeader.Xmax - pcxHeader.Xmin) + 1;
+ Height = (pcxHeader.Ymax - pcxHeader.Ymin) + 1;
+ info.xDPI = pcxHeader.Hres;
+ info.yDPI = pcxHeader.Vres;
+
+ if (info.nEscape == -1){
+ head.biWidth = Width;
+ head.biHeight= Height;
+ info.dwType = CXIMAGE_FORMAT_PCX;
+ return true;
+ }
+
+ // Check that we can handle this image format
+ if (pcxHeader.ColorPlanes > 4)
+ cx_throw("Can't handle image with more than 4 planes");
+
+ // Create the image
+ if (pcxHeader.ColorPlanes >= 3 && pcxHeader.BitsPerPixel == 8){
+ Create (Width, Height, 24, CXIMAGE_FORMAT_PCX);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pcxHeader.ColorPlanes==4) AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+ } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 1)
+ Create (Width, Height, 4, CXIMAGE_FORMAT_PCX);
+ else
+ Create (Width, Height, pcxHeader.BitsPerPixel, CXIMAGE_FORMAT_PCX);
+
+ if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+ //Read the image and check if it's ok
+ nbytes = pcxHeader.BytesPerLine * pcxHeader.ColorPlanes * Height;
+ lpHead1 = pcximage = (uint8_t*)malloc(nbytes);
+ while (nbytes > 0){
+ if (hFile == NULL || hFile->Eof()) cx_throw("corrupted PCX");
+
+ hFile->Read(&c,1,1);
+ if ((c & 0XC0) != 0XC0){ // Repeated group
+ *pcximage++ = c;
+ --nbytes;
+ continue;
+ }
+ count = c & 0X3F; // extract count
+ hFile->Read(&c,1,1);
+ if (count > nbytes) cx_throw("repeat count spans end of image");
+
+ nbytes -= count;
+ while (--count >=0) *pcximage++ = c;
+ }
+ pcximage = lpHead1;
+
+ //store the palette
+ for (i = 0; i < 16; i++){
+ ColorMap[i][0] = pcxHeader.ColorMap[i][0];
+ ColorMap[i][1] = pcxHeader.ColorMap[i][1];
+ ColorMap[i][2] = pcxHeader.ColorMap[i][2];
+ }
+ if (pcxHeader.BitsPerPixel == 8 && pcxHeader.ColorPlanes == 1){
+ hFile->Read(&c,1,1);
+ if (c != PCX_256_COLORS) cx_throw("bad color map signature");
+
+ for (i = 0; i < PCX_MAXCOLORS; i++){
+ hFile->Read(&ColorMap[i][0],1,1);
+ hFile->Read(&ColorMap[i][1],1,1);
+ hFile->Read(&ColorMap[i][2],1,1);
+ }
+ }
+ if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){
+ ColorMap[0][0] = ColorMap[0][1] = ColorMap[0][2] = 0;
+ ColorMap[1][0] = ColorMap[1][1] = ColorMap[1][2] = 255;
+ }
+
+ for (uint32_t idx=0; idx<head.biClrUsed; idx++) SetPaletteColor((uint8_t)idx,ColorMap[idx][0],ColorMap[idx][1],ColorMap[idx][2]);
+
+ lpHead2 = pcxpixels = (uint8_t *)malloc(Width + pcxHeader.BytesPerLine * 8);
+ // Convert the image
+ for (y = 0; y < Height; y++){
+
+ if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+ y2=Height-1-y;
+ pcxpixels = lpHead2;
+ pcxplanes = pcximage + (y * pcxHeader.BytesPerLine * pcxHeader.ColorPlanes);
+
+ if (pcxHeader.ColorPlanes == 3 && pcxHeader.BitsPerPixel == 8){
+ // Deal with 24 bit color image
+ for (x = 0; x < Width; x++){
+ SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x]));
+ }
+ continue;
+#if CXIMAGE_SUPPORT_ALPHA
+ } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 8){
+ for (x = 0; x < Width; x++){
+ SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x]));
+ AlphaSet(x,y2,pcxplanes[3*pcxHeader.BytesPerLine + x]);
+ }
+ continue;
+#endif //CXIMAGE_SUPPORT_ALPHA
+ } else if (pcxHeader.ColorPlanes == 1) {
+ if (!PCX_UnpackPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel)){
+ cx_throw("PCX_UnpackPixels: Can't handle packed pixels with more than 1 plane");
+ }
+ } else {
+ if (!PCX_PlanesToPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel)){
+ cx_throw("PCX_PlanesToPixels: more than 4 planes or more than 1 bit per pixel");
+ }
+ }
+ for (x = 0; x < Width; x++) SetPixelIndex(x,y2,pcxpixels[x]);
+ }
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (lpHead1){ free(lpHead1); lpHead1 = NULL; }
+ if (lpHead2){ free(lpHead2); lpHead2 = NULL; }
+ return false;
+ }
+ if (lpHead1){ free(lpHead1); lpHead1 = NULL; }
+ if (lpHead2){ free(lpHead2); lpHead2 = NULL; }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImagePCX::Encode(CxFile * hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ cx_try
+ {
+ PCXHEADER pcxHeader;
+ memset(&pcxHeader,0,sizeof(pcxHeader));
+ pcxHeader.Manufacturer = PCX_MAGIC;
+ pcxHeader.Version = 5;
+ pcxHeader.Encoding = 1;
+ pcxHeader.Xmin = 0;
+ pcxHeader.Ymin = 0;
+ pcxHeader.Xmax = (uint16_t)head.biWidth-1;
+ pcxHeader.Ymax = (uint16_t)head.biHeight-1;
+ pcxHeader.Hres = (uint16_t)info.xDPI;
+ pcxHeader.Vres = (uint16_t)info.yDPI;
+ pcxHeader.Reserved = 0;
+ pcxHeader.PaletteType = head.biClrUsed==0;
+
+ switch(head.biBitCount){
+ case 24:
+ case 8:
+ {
+ pcxHeader.BitsPerPixel = 8;
+ pcxHeader.ColorPlanes = head.biClrUsed==0 ? 3 : 1;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid() && head.biClrUsed==0) pcxHeader.ColorPlanes =4;
+#endif //CXIMAGE_SUPPORT_ALPHA
+ pcxHeader.BytesPerLine = (uint16_t)head.biWidth;
+ break;
+ }
+ default: //(4 1)
+ pcxHeader.BitsPerPixel = 1;
+ pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1;
+ pcxHeader.BytesPerLine = (uint16_t)((head.biWidth * pcxHeader.BitsPerPixel + 7)>>3);
+ }
+
+ if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){
+ pcxHeader.ColorMap[0][0] = pcxHeader.ColorMap[0][1] = pcxHeader.ColorMap[0][2] = 0;
+ pcxHeader.ColorMap[1][0] = pcxHeader.ColorMap[1][1] = pcxHeader.ColorMap[1][2] = 255;
+ }
+ if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 4){
+ RGBQUAD c;
+ for (int32_t i = 0; i < 16; i++){
+ c=GetPaletteColor(i);
+ pcxHeader.ColorMap[i][0] = c.rgbRed;
+ pcxHeader.ColorMap[i][1] = c.rgbGreen;
+ pcxHeader.ColorMap[i][2] = c.rgbBlue;
+ }
+ }
+
+ pcxHeader.BytesPerLine = (pcxHeader.BytesPerLine + 1)&(~1);
+
+ PCX_toh(&pcxHeader);
+ if (hFile->Write(&pcxHeader, sizeof(pcxHeader), 1) == 0 )
+ cx_throw("cannot write PCX header");
+ PCX_toh(&pcxHeader);
+
+ CxMemFile buffer;
+ buffer.Open();
+
+ uint8_t c,n;
+ int32_t x,y;
+ if (head.biClrUsed==0){
+ for (y = head.biHeight-1; y >=0 ; y--){
+ for (int32_t p=0; p<pcxHeader.ColorPlanes; p++){
+ c=n=0;
+ for (x = 0; x<head.biWidth; x++){
+ if (p==0)
+ PCX_PackPixels(BlindGetPixelColor(x,y).rgbRed,c,n,buffer);
+ else if (p==1)
+ PCX_PackPixels(BlindGetPixelColor(x,y).rgbGreen,c,n,buffer);
+ else if (p==2)
+ PCX_PackPixels(BlindGetPixelColor(x,y).rgbBlue,c,n,buffer);
+#if CXIMAGE_SUPPORT_ALPHA
+ else if (p==3)
+ PCX_PackPixels(BlindAlphaGet(x,y),c,n,buffer);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer);
+ }
+ }
+
+ hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1);
+
+ } else if (head.biBitCount==8) {
+
+ for (y = head.biHeight-1; y >=0 ; y--){
+ c=n=0;
+ for (x = 0; x<head.biWidth; x++){
+ PCX_PackPixels(GetPixelIndex(x,y),c,n,buffer);
+ }
+ PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer);
+ }
+
+ hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1);
+
+ if (head.biBitCount == 8){
+ hFile->PutC(0x0C);
+ uint8_t* pal = (uint8_t*)malloc(768);
+ RGBQUAD c;
+ for (int32_t i=0;i<256;i++){
+ c=GetPaletteColor(i);
+ pal[3*i+0] = c.rgbRed;
+ pal[3*i+1] = c.rgbGreen;
+ pal[3*i+2] = c.rgbBlue;
+ }
+ hFile->Write(pal,768,1);
+ free(pal);
+ }
+ } else { //(head.biBitCount==4) || (head.biBitCount==1)
+
+ RGBQUAD *rgb = GetPalette();
+ bool binvert = false;
+ if (CompareColors(&rgb[0],&rgb[1])>0) binvert=(head.biBitCount==1);
+
+ uint8_t* plane = (uint8_t*)malloc(pcxHeader.BytesPerLine);
+ uint8_t* raw = (uint8_t*)malloc(head.biWidth);
+
+ for(y = head.biHeight-1; y >=0 ; y--) {
+
+ for( x = 0; x < head.biWidth; x++) raw[x] = (uint8_t)GetPixelIndex(x,y);
+
+ if (binvert) for( x = 0; x < head.biWidth; x++) raw[x] = 1-raw[x];
+
+ for( x = 0; x < pcxHeader.ColorPlanes; x++ ) {
+ PCX_PixelsToPlanes(raw, head.biWidth, plane, x);
+ PCX_PackPlanes(plane, pcxHeader.BytesPerLine, buffer);
+ }
+ }
+
+ free(plane);
+ free(raw);
+
+ hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1);
+
+ }
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+// Convert multi-plane format into 1 pixel per byte
+// from unpacked file data bitplanes[] into pixel row pixels[]
+// image Height rows, with each row having planes image planes each
+// bytesperline bytes
+bool CxImagePCX::PCX_PlanesToPixels(uint8_t * pixels, uint8_t * bitplanes, int16_t bytesperline, int16_t planes, int16_t bitsperpixel)
+{
+ int32_t i, j, npixels;
+ uint8_t * p;
+ if (planes > 4) return false;
+ if (bitsperpixel != 1) return false;
+
+ // Clear the pixel buffer
+ npixels = (bytesperline * 8) / bitsperpixel;
+ p = pixels;
+ while (--npixels >= 0) *p++ = 0;
+
+ // Do the format conversion
+ for (i = 0; i < planes; i++){
+ int32_t pixbit, bits, mask;
+ p = pixels;
+ pixbit = (1 << i); // pixel bit for this plane
+ for (j = 0; j < bytesperline; j++){
+ bits = *bitplanes++;
+ for (mask = 0X80; mask != 0; mask >>= 1, p++)
+ if (bits & mask) *p |= pixbit;
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+// convert packed pixel format into 1 pixel per byte
+// from unpacked file data bitplanes[] into pixel row pixels[]
+// image Height rows, with each row having planes image planes each
+// bytesperline bytes
+bool CxImagePCX::PCX_UnpackPixels(uint8_t * pixels, uint8_t * bitplanes, int16_t bytesperline, int16_t planes, int16_t bitsperpixel)
+{
+ register int32_t bits;
+ if (planes != 1) return false;
+
+ if (bitsperpixel == 8){ // 8 bits/pixels, no unpacking needed
+ while (bytesperline-- > 0) *pixels++ = *bitplanes++;
+ } else if (bitsperpixel == 4){ // 4 bits/pixel, two pixels per byte
+ while (bytesperline-- > 0){
+ bits = *bitplanes++;
+ *pixels++ = (uint8_t)((bits >> 4) & 0X0F);
+ *pixels++ = (uint8_t)((bits) & 0X0F);
+ }
+ } else if (bitsperpixel == 2){ // 2 bits/pixel, four pixels per byte
+ while (bytesperline-- > 0){
+ bits = *bitplanes++;
+ *pixels++ = (uint8_t)((bits >> 6) & 0X03);
+ *pixels++ = (uint8_t)((bits >> 4) & 0X03);
+ *pixels++ = (uint8_t)((bits >> 2) & 0X03);
+ *pixels++ = (uint8_t)((bits) & 0X03);
+ }
+ } else if (bitsperpixel == 1){ // 1 bits/pixel, 8 pixels per byte
+ while (bytesperline-- > 0){
+ bits = *bitplanes++;
+ *pixels++ = ((bits & 0X80) != 0);
+ *pixels++ = ((bits & 0X40) != 0);
+ *pixels++ = ((bits & 0X20) != 0);
+ *pixels++ = ((bits & 0X10) != 0);
+ *pixels++ = ((bits & 0X08) != 0);
+ *pixels++ = ((bits & 0X04) != 0);
+ *pixels++ = ((bits & 0X02) != 0);
+ *pixels++ = ((bits & 0X01) != 0);
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/* PCX_PackPixels(const int32_t p,uint8_t &c, uint8_t &n, int32_t &l, CxFile &f)
+ * p = current pixel (-1 ends the line -2 ends odd line)
+ * c = previous pixel
+ * n = number of consecutive pixels
+ */
+void CxImagePCX::PCX_PackPixels(const int32_t p,uint8_t &c, uint8_t &n, CxFile &f)
+{
+ if (p!=c && n){
+ if (n==1 && c<0xC0){
+ f.PutC(c);
+ } else {
+ f.PutC(0xC0|n);
+ f.PutC(c);
+ }
+ n=0;
+ }
+ if (n==0x3F) {
+ f.PutC(0xFF);
+ f.PutC(c);
+ n=0;
+ }
+ if (p==-2) f.PutC(0);
+ c=(uint8_t)p;
+ n++;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImagePCX::PCX_PackPlanes(uint8_t* buff, const int32_t size, CxFile &f)
+{
+ uint8_t *start,*end;
+ uint8_t c, previous, count;
+
+ start = buff;
+ end = buff + size;
+ previous = *start++;
+ count = 1;
+
+ while (start < end) {
+ c = *start++;
+ if (c == previous && count < 63) {
+ ++count;
+ continue;
+ }
+
+ if (count > 1 || (previous & 0xc0) == 0xc0) {
+ f.PutC( count | 0xc0 );
+ }
+ f.PutC(previous);
+ previous = c;
+ count = 1;
+ }
+
+ if (count > 1 || (previous & 0xc0) == 0xc0) {
+ count |= 0xc0;
+ f.PutC(count);
+ }
+ f.PutC(previous);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImagePCX::PCX_PixelsToPlanes(uint8_t* raw, int32_t width, uint8_t* buf, int32_t plane)
+{
+ int32_t cbit, x, mask;
+ uint8_t *cp = buf-1;
+
+ mask = 1 << plane;
+ cbit = -1;
+ for( x = 0; x < width; x++ ) {
+ if( cbit < 0 ) {
+ cbit = 7;
+ *++cp = 0;
+ }
+ if( raw[x] & mask )
+ *cp |= (1<<cbit);
+ --cbit;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImagePCX::PCX_toh(PCXHEADER* p)
+{
+ p->Xmin = m_ntohs(p->Xmin);
+ p->Ymin = m_ntohs(p->Ymin);
+ p->Xmax = m_ntohs(p->Xmax);
+ p->Ymax = m_ntohs(p->Ymax);
+ p->Hres = m_ntohs(p->Hres);
+ p->Vres = m_ntohs(p->Vres);
+ p->BytesPerLine = m_ntohs(p->BytesPerLine);
+ p->PaletteType = m_ntohs(p->PaletteType);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_PCX
diff --git a/archive/hge/CxImage/ximapcx.h b/archive/hge/CxImage/ximapcx.h new file mode 100644 index 0000000..05c5ad0 --- /dev/null +++ b/archive/hge/CxImage/ximapcx.h @@ -0,0 +1,64 @@ +/*
+ * File: ximapcx.h
+ * Purpose: PCX Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImagePCX (c) 05/Jan/2002 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Parts of the code come from Paintlib: Copyright (c) 1996-1998 Ulrich von Zadow
+ * ==========================================================
+ */
+#if !defined(__ximaPCX_h)
+#define __ximaPCX_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_PCX
+
+class CxImagePCX: public CxImage
+{
+// PCX Image File
+#pragma pack(1)
+typedef struct tagPCXHEADER
+{
+ char Manufacturer; // always 0X0A
+ char Version; // version number
+ char Encoding; // always 1
+ char BitsPerPixel; // color bits
+ uint16_t Xmin, Ymin; // image origin
+ uint16_t Xmax, Ymax; // image dimensions
+ uint16_t Hres, Vres; // resolution values
+ uint8_t ColorMap[16][3]; // color palette
+ char Reserved;
+ char ColorPlanes; // color planes
+ uint16_t BytesPerLine; // line buffer size
+ uint16_t PaletteType; // grey or color palette
+ char Filter[58];
+} PCXHEADER;
+#pragma pack()
+
+public:
+ CxImagePCX(): CxImage(CXIMAGE_FORMAT_PCX) {}
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_PCX);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_PCX);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+protected:
+ bool PCX_PlanesToPixels(uint8_t * pixels, uint8_t * bitplanes, int16_t bytesperline, int16_t planes, int16_t bitsperpixel);
+ bool PCX_UnpackPixels(uint8_t * pixels, uint8_t * bitplanes, int16_t bytesperline, int16_t planes, int16_t bitsperpixel);
+ void PCX_PackPixels(const int32_t p,uint8_t &c, uint8_t &n, CxFile &f);
+ void PCX_PackPlanes(uint8_t* buff, const int32_t size, CxFile &f);
+ void PCX_PixelsToPlanes(uint8_t* raw, int32_t width, uint8_t* buf, int32_t plane);
+ void PCX_toh(PCXHEADER* p);
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximapng.cpp b/archive/hge/CxImage/ximapng.cpp new file mode 100644 index 0000000..db2f636 --- /dev/null +++ b/archive/hge/CxImage/ximapng.cpp @@ -0,0 +1,644 @@ +/*
+ * File: ximapng.cpp
+ * Purpose: Platform Independent PNG Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximapng.h"
+
+#if CXIMAGE_SUPPORT_PNG
+
+#include "ximaiter.h"
+
+////////////////////////////////////////////////////////////////////////////////
+void CxImagePNG::ima_png_error(png_struct *png_ptr, char *message)
+{
+ strcpy(info.szLastError,message);
+#if PNG_LIBPNG_VER > 10399
+ longjmp(png_jmpbuf(png_ptr), 1);
+#else
+ longjmp(png_ptr->jmpbuf, 1);
+#endif
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+void CxImagePNG::expand2to4bpp(uint8_t* prow)
+{
+ uint8_t *psrc,*pdst;
+ uint8_t pos,idx;
+ for(int32_t x=head.biWidth-1;x>=0;x--){
+ psrc = prow + ((2*x)>>3);
+ pdst = prow + ((4*x)>>3);
+ pos = (uint8_t)(2*(3-x%4));
+ idx = (uint8_t)((*psrc & (0x03<<pos))>>pos);
+ pos = (uint8_t)(4*(1-x%2));
+ *pdst &= ~(0x0F<<pos);
+ *pdst |= (idx & 0x0F)<<pos;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImagePNG::Decode(CxFile *hFile)
+{
+ png_struct *png_ptr;
+ png_info *info_ptr;
+ uint8_t *row_pointers=NULL;
+ CImageIterator iter(this);
+
+ cx_try
+ {
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also supply the
+ * the compiler header file version, so that we know if the application
+ * was compiled with a compatible version of the library. REQUIRED */
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,(void *)NULL,NULL,NULL);
+ if (png_ptr == NULL) cx_throw("Failed to create PNG structure");
+
+ /* Allocate/initialize the memory for image information. REQUIRED. */
+ info_ptr = png_create_info_struct(png_ptr);
+ if (info_ptr == NULL) {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ cx_throw("Failed to initialize PNG info structure");
+ }
+
+ /* Set error handling if you are using the setjmp/longjmp method (this is
+ * the normal method of doing things with libpng). REQUIRED unless you
+ * set up your own error handlers in the png_create_read_struct() earlier. */
+#if PNG_LIBPNG_VER > 10399
+ if (setjmp(png_jmpbuf(png_ptr))) {
+#else
+ if (setjmp(png_ptr->jmpbuf)) {
+#endif
+ /* Free all of the memory associated with the png_ptr and info_ptr */
+ delete [] row_pointers;
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ cx_throw("");
+ }
+
+ // use custom I/O functions
+ png_set_read_fn(png_ptr, hFile, /*(png_rw_ptr)*/user_read_data);
+ png_set_error_fn(png_ptr,info.szLastError,/*(png_error_ptr)*/user_error_fn,NULL);
+
+ /* read the file information */
+ png_read_info(png_ptr, info_ptr);
+
+ png_uint_32 _width,_height;
+ int _bit_depth,_color_type,_interlace_type,_compression_type,_filter_type;
+#if PNG_LIBPNG_VER > 10399
+ png_get_IHDR(png_ptr,info_ptr,&_width,&_height,&_bit_depth,&_color_type,
+ &_interlace_type,&_compression_type,&_filter_type);
+#else
+ _width=info_ptr->width;
+ _height=info_ptr->height;
+ _bit_depth=info_ptr->bit_depth;
+ _color_type=info_ptr->color_type;
+ _interlace_type=info_ptr->interlace_type;
+ //_compression_type=info_ptr->compression_type;
+ //_filter_type=info_ptr->filter_type;
+#endif
+
+ if (info.nEscape == -1){
+ head.biWidth = _width;
+ head.biHeight= _height;
+ info.dwType = CXIMAGE_FORMAT_PNG;
+#if PNG_LIBPNG_VER > 10399
+ longjmp(png_jmpbuf(png_ptr), 1);
+#else
+ longjmp(png_ptr->jmpbuf, 1);
+#endif
+ }
+
+ /* calculate new number of channels */
+ int32_t channels=0;
+ switch(_color_type){
+ case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_PALETTE:
+ channels = 1;
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ channels = 2;
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ channels = 3;
+ break;
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ channels = 4;
+ break;
+ default:
+ strcpy(info.szLastError,"unknown PNG color type");
+#if PNG_LIBPNG_VER > 10399
+ longjmp(png_jmpbuf(png_ptr), 1);
+#else
+ longjmp(png_ptr->jmpbuf, 1);
+#endif
+ }
+
+ //find the right pixel depth used for cximage
+#if PNG_LIBPNG_VER > 10399
+ int pixel_depth = _bit_depth * png_get_channels(png_ptr,info_ptr);
+#else
+ int pixel_depth = info_ptr->pixel_depth;
+#endif
+ if (channels == 1 && pixel_depth>8) pixel_depth=8;
+ if (channels == 2) pixel_depth=8;
+ if (channels >= 3) pixel_depth=24;
+
+ if (!Create(_width, _height, pixel_depth, CXIMAGE_FORMAT_PNG)){
+#if PNG_LIBPNG_VER > 10399
+ longjmp(png_jmpbuf(png_ptr), 1);
+#else
+ longjmp(png_ptr->jmpbuf, 1);
+#endif
+ }
+
+ /* get metrics */
+ png_uint_32 _x_pixels_per_unit,_y_pixels_per_unit;
+ int _phys_unit_type;
+#if PNG_LIBPNG_VER > 10399
+ png_get_pHYs(png_ptr,info_ptr,&_x_pixels_per_unit,&_y_pixels_per_unit,&_phys_unit_type);
+#else
+ _x_pixels_per_unit=info_ptr->x_pixels_per_unit;
+ _y_pixels_per_unit=info_ptr->y_pixels_per_unit;
+ _phys_unit_type=info_ptr->phys_unit_type;
+#endif
+ switch (_phys_unit_type)
+ {
+ case PNG_RESOLUTION_UNKNOWN:
+ SetXDPI(_x_pixels_per_unit);
+ SetYDPI(_y_pixels_per_unit);
+ break;
+ case PNG_RESOLUTION_METER:
+ SetXDPI((long)floor(_x_pixels_per_unit * 254.0 / 10000.0 + 0.5));
+ SetYDPI((long)floor(_y_pixels_per_unit * 254.0 / 10000.0 + 0.5));
+ break;
+ }
+
+ int _num_palette;
+ png_colorp _palette;
+#if PNG_LIBPNG_VER > 10399
+ png_get_PLTE(png_ptr,info_ptr,&_palette,&_num_palette);
+#else
+ _num_palette=info_ptr->num_palette;
+ _palette=info_ptr->palette;
+#endif
+ if (_num_palette>0){
+ SetPalette((rgb_color*)_palette,_num_palette);
+ SetClrImportant(_num_palette);
+ } else if (_bit_depth ==2) { //<DP> needed for 2 bpp grayscale PNGs
+ SetPaletteColor(0,0,0,0);
+ SetPaletteColor(1,85,85,85);
+ SetPaletteColor(2,170,170,170);
+ SetPaletteColor(3,255,255,255);
+ } else SetGrayPalette(); //<DP> needed for grayscale PNGs
+
+ int nshift = max(0,(_bit_depth>>3)-1)<<3;
+
+ png_bytep _trans_alpha;
+ int _num_trans;
+ png_color_16p _trans_color;
+#if PNG_LIBPNG_VER > 10399
+ png_get_tRNS(png_ptr,info_ptr,&_trans_alpha,&_num_trans,&_trans_color);
+#else
+ _num_trans=info_ptr->num_trans;
+#endif
+ if (_num_trans!=0){ //palette transparency
+ if (_num_trans==1){
+ if (_color_type == PNG_COLOR_TYPE_PALETTE){
+ info.nBkgndIndex = _trans_color->index;
+ } else{
+ info.nBkgndIndex = _trans_color->gray>>nshift;
+ }
+ }
+ if (_num_trans>1){
+ RGBQUAD* pal=GetPalette();
+ if (pal){
+ uint32_t ip;
+ if(_trans_alpha != 0) {
+ for (ip=0;ip<min(head.biClrUsed,(unsigned long)_num_trans);ip++)
+ pal[ip].rgbReserved=_trans_alpha[ip];
+ }
+ for (ip=_num_trans;ip<head.biClrUsed;ip++){
+ pal[ip].rgbReserved=255;
+ }
+ info.bAlphaPaletteEnabled=true;
+ }
+ }
+ }
+
+ if (channels == 3){ //check RGB binary transparency
+ /* seems unnecessary to call again, but the conditional must be important so... */
+ if (png_get_tRNS(png_ptr,info_ptr,&_trans_alpha,&_num_trans,&_trans_color)){
+ info.nBkgndColor.rgbRed = (uint8_t)(_trans_color->red>>nshift);
+ info.nBkgndColor.rgbGreen = (uint8_t)(_trans_color->green>>nshift);
+ info.nBkgndColor.rgbBlue = (uint8_t)(_trans_color->blue>>nshift);
+ info.nBkgndColor.rgbReserved = 0;
+ info.nBkgndIndex = 0;
+ }
+ }
+
+ int32_t alpha_present = (channels - 1) % 2;
+ if (alpha_present){
+#if CXIMAGE_SUPPORT_ALPHA // <vho>
+ AlphaCreate();
+#else
+ png_set_strip_alpha(png_ptr);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+
+ // <vho> - flip the RGB pixels to BGR (or RGBA to BGRA)
+ if (_color_type & PNG_COLOR_MASK_COLOR){
+ png_set_bgr(png_ptr);
+ }
+
+ // <vho> - handle cancel
+ if (info.nEscape)
+#if PNG_LIBPNG_VER > 10399
+ longjmp(png_jmpbuf(png_ptr), 1);
+#else
+ longjmp(png_ptr->jmpbuf, 1);
+#endif
+
+ // row_bytes is the width x number of channels x (bit-depth / 8)
+#if PNG_LIBPNG_VER > 10399
+ row_pointers = new uint8_t[png_get_rowbytes(png_ptr,info_ptr) + 8];
+#else
+ row_pointers = new uint8_t[info_ptr->rowbytes + 8];
+#endif
+
+
+ // turn on interlace handling
+ int32_t number_passes = png_set_interlace_handling(png_ptr);
+
+ if (number_passes>1){
+ SetCodecOption( (ENCODE_INTERLACE) | GetCodecOption(CXIMAGE_FORMAT_PNG));
+ } else {
+ SetCodecOption(~(ENCODE_INTERLACE) & GetCodecOption(CXIMAGE_FORMAT_PNG));
+ }
+
+ int chan_offset = _bit_depth >> 3;
+#if PNG_LIBPNG_VER > 10399
+ int pixel_offset = (_bit_depth * png_get_channels(png_ptr,info_ptr)) >> 3;
+#else
+ int pixel_offset = info_ptr->pixel_depth >> 3;
+#endif
+
+ for (int32_t pass=0; pass < number_passes; pass++) {
+ iter.Upset();
+ int32_t y=0;
+ do {
+
+ // <vho> - handle cancel
+ if (info.nEscape)
+#if PNG_LIBPNG_VER > 10399
+ longjmp(png_jmpbuf(png_ptr), 1);
+#else
+ longjmp(png_ptr->jmpbuf, 1);
+#endif
+
+#if CXIMAGE_SUPPORT_ALPHA // <vho>
+ if (AlphaIsValid()) {
+
+ //compute the correct position of the line
+ int32_t ax,ay;
+ ay = head.biHeight-1-y;
+ uint8_t* prow= iter.GetRow(ay);
+
+ //recover data from previous scan
+ if (_interlace_type && pass>0 && pass!=7){
+ for(ax=0;ax<head.biWidth;ax++){
+ int32_t px = ax * pixel_offset;
+ if (channels == 2){
+ row_pointers[px] = prow[ax];
+ row_pointers[px+chan_offset]=AlphaGet(ax,ay);
+ } else {
+ int32_t qx = ax * 3;
+ row_pointers[px] =prow[qx];
+ row_pointers[px+chan_offset] =prow[qx+1];
+ row_pointers[px+chan_offset*2]=prow[qx+2];
+ row_pointers[px+chan_offset*3]=AlphaGet(ax,ay);
+ }
+ }
+ }
+
+ //read next row
+ png_read_row(png_ptr, row_pointers, NULL);
+
+ //RGBA -> RGB + A
+ for(ax=0;ax<head.biWidth;ax++){
+ int32_t px = ax * pixel_offset;
+ if (channels == 2){
+ prow[ax] = row_pointers[px];
+ AlphaSet(ax,ay,row_pointers[px+chan_offset]);
+ } else {
+ int32_t qx = ax * 3;
+ prow[qx] =row_pointers[px];
+ prow[qx+1]=row_pointers[px+chan_offset];
+ prow[qx+2]=row_pointers[px+chan_offset*2];
+ AlphaSet(ax,ay,row_pointers[px+chan_offset*3]);
+ }
+ }
+ } else
+#endif // CXIMAGE_SUPPORT_ALPHA // vho
+ {
+ //recover data from previous scan
+ if (_interlace_type && pass>0){
+#if PNG_LIBPNG_VER > 10399
+ iter.GetRow(row_pointers, png_get_rowbytes(png_ptr,info_ptr));
+#else
+ iter.GetRow(row_pointers, info_ptr->rowbytes);
+#endif
+ //re-expand buffer for images with bit depth > 8
+ if (_bit_depth > 8){
+ for(int32_t ax=(head.biWidth*channels-1);ax>=0;ax--)
+ row_pointers[ax*chan_offset] = row_pointers[ax];
+ }
+ }
+
+ //read next row
+ png_read_row(png_ptr, row_pointers, NULL);
+
+ //shrink 16 bit depth images down to 8 bits
+ if (_bit_depth > 8){
+ for(int32_t ax=0;ax<(head.biWidth*channels);ax++)
+ row_pointers[ax] = row_pointers[ax*chan_offset];
+ }
+
+ //copy the pixels
+#if PNG_LIBPNG_VER > 10399
+ iter.SetRow(row_pointers, png_get_rowbytes(png_ptr,info_ptr));
+#else
+ iter.SetRow(row_pointers, info_ptr->rowbytes);
+#endif
+ //<DP> expand 2 bpp images only in the last pass
+ if (_bit_depth==2 && pass==(number_passes-1))
+ expand2to4bpp(iter.GetRow());
+
+ //go on
+ iter.PrevRow();
+ }
+
+ y++;
+ } while(y<head.biHeight);
+ }
+
+ delete [] row_pointers;
+ row_pointers = NULL;
+
+ /* read the rest of the file, getting any additional chunks in info_ptr - REQUIRED */
+ png_read_end(png_ptr, info_ptr);
+
+ /* clean up after the read, and free any memory allocated - REQUIRED */
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_PNG) return true;
+ return false;
+ }
+ /* that's it */
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImagePNG::Encode(CxFile *hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ CImageIterator iter(this);
+ uint8_t trans[256]; //for transparency (don't move)
+ png_struct *png_ptr;
+ png_info *info_ptr;
+
+ cx_try
+ {
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also check that
+ * the library version is compatible with the one used at compile time,
+ * in case we are using dynamically linked libraries. REQUIRED.
+ */
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,(void *)NULL,NULL,NULL);
+ if (png_ptr == NULL) cx_throw("Failed to create PNG structure");
+
+ /* Allocate/initialize the image information data. REQUIRED */
+ info_ptr = png_create_info_struct(png_ptr);
+ if (info_ptr == NULL){
+ png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+ cx_throw("Failed to initialize PNG info structure");
+ }
+
+ /* Set error handling. REQUIRED if you aren't supplying your own
+ * error hadnling functions in the png_create_write_struct() call.
+ */
+ if (setjmp(png_ptr->jmpbuf)){
+ /* If we get here, we had a problem reading the file */
+ if (info_ptr->palette) free(info_ptr->palette);
+ png_destroy_write_struct(&png_ptr, (png_infopp)&info_ptr);
+ cx_throw("Error saving PNG file");
+ }
+
+ /* set up the output control */
+ //png_init_io(png_ptr, hFile);
+
+ // use custom I/O functions
+ png_set_write_fn(png_ptr,hFile,/*(png_rw_ptr)*/user_write_data,/*(png_flush_ptr)*/user_flush_data);
+
+ /* set the file information here */
+ info_ptr->width = GetWidth();
+ info_ptr->height = GetHeight();
+ info_ptr->pixel_depth = (uint8_t)GetBpp();
+ info_ptr->channels = (GetBpp()>8) ? (uint8_t)3: (uint8_t)1;
+ info_ptr->bit_depth = (uint8_t)(GetBpp()/info_ptr->channels);
+ info_ptr->compression_type = info_ptr->filter_type = 0;
+ info_ptr->valid = 0;
+
+ // set interlace type
+ DWORD codec_opt = GetCodecOption(CXIMAGE_FORMAT_PNG);
+ if (codec_opt & CxImagePNG::ENCODE_INTERLACE)
+ info_ptr->interlace_type = PNG_INTERLACE_ADAM7;
+ else
+ info_ptr->interlace_type = PNG_INTERLACE_NONE;
+
+ /* set compression level */
+ int32_t compress_level;
+ switch (codec_opt & CxImagePNG::ENCODE_COMPRESSION_MASK)
+ {
+ case ENCODE_NO_COMPRESSION:
+ compress_level = Z_NO_COMPRESSION;
+ break;
+ case ENCODE_BEST_SPEED:
+ compress_level = Z_BEST_SPEED;
+ break;
+ case ENCODE_BEST_COMPRESSION:
+ compress_level = Z_BEST_COMPRESSION;
+ break;
+ default:
+ compress_level = Z_DEFAULT_COMPRESSION;
+ break;
+ }
+ png_set_compression_level(png_ptr, compress_level);
+
+ bool bGrayScale = IsGrayScale();
+
+ if (GetNumColors()){
+ if (bGrayScale){
+ info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
+ } else {
+ info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
+ }
+ } else {
+ info_ptr->color_type = PNG_COLOR_TYPE_RGB;
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()){
+ info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
+ info_ptr->channels++;
+ info_ptr->bit_depth = 8;
+ info_ptr->pixel_depth += 8;
+ }
+#endif
+
+ /* set background */
+ png_color_16 image_background={ 0, 255, 255, 255, 0 };
+ RGBQUAD tc = GetTransColor();
+ if (info.nBkgndIndex>=0) {
+ image_background.blue = tc.rgbBlue;
+ image_background.green = tc.rgbGreen;
+ image_background.red = tc.rgbRed;
+ }
+ png_set_bKGD(png_ptr, info_ptr, &image_background);
+
+ /* set metrics */
+ png_set_pHYs(png_ptr, info_ptr, head.biXPelsPerMeter, head.biYPelsPerMeter, PNG_RESOLUTION_METER);
+
+ png_set_IHDR(png_ptr, info_ptr, info_ptr->width, info_ptr->height, info_ptr->bit_depth,
+ info_ptr->color_type, info_ptr->interlace_type,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ //<DP> simple transparency
+ if (info.nBkgndIndex >= 0){
+ info_ptr->num_trans = 1;
+ info_ptr->valid |= PNG_INFO_tRNS;
+ info_ptr->trans_alpha = trans;
+ info_ptr->trans_color.index = (uint8_t)info.nBkgndIndex;
+ info_ptr->trans_color.red = tc.rgbRed;
+ info_ptr->trans_color.green = tc.rgbGreen;
+ info_ptr->trans_color.blue = tc.rgbBlue;
+ info_ptr->trans_color.gray = info_ptr->trans_color.index;
+
+ // the transparency indexes start from 0 for non grayscale palette
+ if (!bGrayScale && head.biClrUsed && info.nBkgndIndex)
+ SwapIndex(0,(uint8_t)info.nBkgndIndex);
+ }
+
+ /* set the palette if there is one */
+ if (GetPalette()){
+ if (!bGrayScale){
+ info_ptr->valid |= PNG_INFO_PLTE;
+ }
+
+ int32_t nc = GetClrImportant();
+ if (nc==0) nc = GetNumColors();
+
+ if (info.bAlphaPaletteEnabled){
+ for(uint16_t ip=0; ip<nc;ip++)
+ trans[ip]=GetPaletteColor((uint8_t)ip).rgbReserved;
+ info_ptr->num_trans = (uint16_t)nc;
+ info_ptr->valid |= PNG_INFO_tRNS;
+ info_ptr->trans_alpha = trans;
+ }
+
+ // copy the palette colors
+ info_ptr->palette = new png_color[nc];
+ info_ptr->num_palette = (png_uint_16) nc;
+ for (int32_t i=0; i<nc; i++)
+ GetPaletteColor(i, &info_ptr->palette[i].red, &info_ptr->palette[i].green, &info_ptr->palette[i].blue);
+ }
+
+#if CXIMAGE_SUPPORT_ALPHA // <vho>
+ //Merge the transparent color with the alpha channel
+ if (AlphaIsValid() && head.biBitCount==24 && info.nBkgndIndex>=0){
+ for(int32_t y=0; y < head.biHeight; y++){
+ for(int32_t x=0; x < head.biWidth ; x++){
+ RGBQUAD c=GetPixelColor(x,y,false);
+ if (*(int32_t*)&c==*(int32_t*)&tc)
+ AlphaSet(x,y,0);
+ } } }
+#endif // CXIMAGE_SUPPORT_ALPHA // <vho>
+
+ int32_t row_size = max(info.dwEffWidth, info_ptr->width*info_ptr->channels*(info_ptr->bit_depth/8));
+ info_ptr->rowbytes = row_size;
+ uint8_t *row_pointers = new uint8_t[row_size];
+
+ /* write the file information */
+ png_write_info(png_ptr, info_ptr);
+
+ //interlace handling
+ int32_t num_pass = png_set_interlace_handling(png_ptr);
+ for (int32_t pass = 0; pass < num_pass; pass++){
+ //write image
+ iter.Upset();
+ int32_t ay=head.biHeight-1;
+ RGBQUAD c;
+ do {
+#if CXIMAGE_SUPPORT_ALPHA // <vho>
+ if (AlphaIsValid()){
+ for (int32_t ax=head.biWidth-1; ax>=0;ax--){
+ c = BlindGetPixelColor(ax,ay);
+ int32_t px = ax * info_ptr->channels;
+ if (!bGrayScale){
+ row_pointers[px++]=c.rgbRed;
+ row_pointers[px++]=c.rgbGreen;
+ }
+ row_pointers[px++]=c.rgbBlue;
+ row_pointers[px] = AlphaGet(ax,ay);
+ }
+ png_write_row(png_ptr, row_pointers);
+ ay--;
+ }
+ else
+#endif //CXIMAGE_SUPPORT_ALPHA // <vho>
+ {
+ iter.GetRow(row_pointers, row_size);
+ if (info_ptr->color_type == PNG_COLOR_TYPE_RGB) //HACK BY OP
+ RGBtoBGR(row_pointers, row_size);
+ png_write_row(png_ptr, row_pointers);
+ }
+ } while(iter.PrevRow());
+ }
+
+ delete [] row_pointers;
+ row_pointers = NULL;
+
+ //if necessary, restore the original palette
+ if (!bGrayScale && head.biClrUsed && info.nBkgndIndex>0)
+ SwapIndex((uint8_t)info.nBkgndIndex,0);
+
+ /* It is REQUIRED to call this to finish writing the rest of the file */
+ png_write_end(png_ptr, info_ptr);
+
+ /* if you malloced the palette, free it here */
+ if (info_ptr->palette){
+ delete [] (info_ptr->palette);
+ info_ptr->palette = NULL;
+ }
+
+ /* clean up after the write, and free any memory allocated */
+ png_destroy_write_struct(&png_ptr, (png_infopp)&info_ptr);
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ return FALSE;
+ }
+ /* that's it */
+ return TRUE;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_PNG
diff --git a/archive/hge/CxImage/ximapng.h b/archive/hge/CxImage/ximapng.h new file mode 100644 index 0000000..262ea02 --- /dev/null +++ b/archive/hge/CxImage/ximapng.h @@ -0,0 +1,95 @@ +/*
+ * File: ximapng.h
+ * Purpose: PNG Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImagePNG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes
+ *
+ * original CImagePNG and CImageIterator implementation are:
+ * Copyright: (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>
+ *
+ * libpng Copyright (c) 1998-2003 Glenn Randers-Pehrson
+ * ==========================================================
+ */
+#if !defined(__ximaPNG_h)
+#define __ximaPNG_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_PNG
+
+extern "C" {
+#ifdef _LINUX
+ #undef _DLL
+ #include <png.h>
+#else
+ #include "../png/png.h"
+#endif
+}
+
+class CxImagePNG: public CxImage
+{
+public:
+ CxImagePNG(): CxImage(CXIMAGE_FORMAT_PNG) {}
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_PNG);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_PNG);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+ enum CODEC_OPTION
+ {
+ ENCODE_INTERLACE = 0x01,
+ // Exclusive compression types : 3 bit wide field
+ ENCODE_COMPRESSION_MASK = 0x0E,
+ ENCODE_NO_COMPRESSION = 1 << 1,
+ ENCODE_BEST_SPEED = 2 << 1,
+ ENCODE_BEST_COMPRESSION = 3 << 1,
+ ENCODE_DEFAULT_COMPRESSION = 4 << 1
+ };
+
+protected:
+ void ima_png_error(png_struct *png_ptr, char *message);
+ void expand2to4bpp(uint8_t* prow);
+
+ static void PNGAPI user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+ {
+ CxFile* hFile = (CxFile*)png_get_io_ptr(png_ptr);
+ if (hFile == NULL || hFile->Read(data,1,length) != length) png_error(png_ptr, "Read Error");
+ }
+
+ static void PNGAPI user_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+ {
+ CxFile* hFile = (CxFile*)png_get_io_ptr(png_ptr);
+ if (hFile == NULL || hFile->Write(data,1,length) != length) png_error(png_ptr, "Write Error");
+ }
+
+ static void PNGAPI user_flush_data(png_structp png_ptr)
+ {
+ CxFile* hFile = (CxFile*)png_get_io_ptr(png_ptr);
+ if (hFile == NULL || !hFile->Flush()) png_error(png_ptr, "Flush Error");
+ }
+
+ static void PNGAPI user_error_fn(png_structp png_ptr,png_const_charp error_msg)
+ {
+#if PNG_LIBPNG_VER > 10399
+ strncpy((char*)png_get_error_ptr(png_ptr),error_msg,255);
+ longjmp(png_jmpbuf(png_ptr), 1);
+#else
+ strncpy((char*)png_ptr->error_ptr,error_msg,255);
+ longjmp(png_ptr->jmpbuf, 1);
+#endif
+ }
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximapsd.cpp b/archive/hge/CxImage/ximapsd.cpp new file mode 100644 index 0000000..2d8417b --- /dev/null +++ b/archive/hge/CxImage/ximapsd.cpp @@ -0,0 +1,1307 @@ +/*
+ * File: ximapsd.cpp
+ * Purpose: Platform Independent PSD Image Class Loader
+ * Dec/2010 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ *
+ * libpsd (c) 2004-2007 Graphest Software
+ *
+ * Based on MyPSD class by Iosif Hamlatzis
+ * Details: http://www.codeproject.com/KB/graphics/MyPSD.aspx
+ * Cleaned up a bit and ported to CxImage by Vitaly Ovchinnikov
+ * Send feedback to vitaly(dot)ovchinnikov(at)gmail.com
+ */
+
+#include "ximapsd.h"
+
+#if CXIMAGE_SUPPORT_PSD
+
+enum {
+ PSD_FILE_HEADER,
+ PSD_COLOR_MODE_DATA,
+ PSD_IMAGE_RESOURCE,
+ PSD_LAYER_AND_MASK_INFORMATION,
+ PSD_IMAGE_DATA,
+ PSD_DONE
+};
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_USE_LIBPSD == 0
+// MyPSD.h /////////////////////////////////////////////////////////////////////
+
+#ifndef __MyPSD_H__
+#define __MyPSD_H__
+
+namespace MyPSD
+{
+
+ class CPSD
+ {
+ struct HEADER_INFO
+ {
+ //Table 2-12: HeaderInfo Color spaces
+ // Color-ID Name Description
+ //-------------------------------------------
+ // 0 Bitmap // Probably means black & white
+ // 1 Grayscale The first value in the color data is the gray value, from 0...10000.
+ // 2 Indexed
+ // 3 RGB The first three values in the color data are red, green, and blue.
+ // They are full unsigned 16–bit values as in Apple’s RGBColor data
+ // structure. Pure red=65535,0,0.
+ // 4 CMYK The four values in the color data are cyan, magenta, yellow, and
+ // black. They are full unsigned 16–bit values. 0=100% ink. Pure
+ // cyan=0,65535,65535,65535.
+ // 7 Multichannel // Have no idea
+ // 8 Duotone
+ // 9 Lab The first three values in the color data are lightness, a chrominance,
+ // and b chrominance.
+ // Lightness is a 16–bit value from 0...100. The chromanance components
+ // are each 16–bit values from –128...127. Gray values
+ // are represented by chrominance components of 0. Pure
+ // white=100,0,0.
+ short nChannels;
+ int nHeight;
+ int nWidth;
+ short nBitsPerPixel;
+ short nColourMode;
+ HEADER_INFO();
+ };
+
+ struct COLOUR_MODE_DATA
+ {
+ int nLength;
+ unsigned char* ColourData;
+ COLOUR_MODE_DATA();
+ };
+
+
+ struct IMAGE_RESOURCE
+ {
+ // Table 2–1: Image resource block
+ // Type Name Description
+ //-------------------------------------------
+ // OSType Type Photoshop always uses its signature, 8BIM
+ // int16 ID Unique identifier
+ // PString Name A pascal string, padded to make size even (a null name consists of two bytes of 0)
+ // Pascal style string where the first byte gives the length of the
+ // string and the content bytes follow.
+ // int32 Size Actual size of resource data. This does not include the
+ // Type, ID, Name, or Size fields.
+ // Variable Data Resource data, padded to make size even
+ int nLength;
+ char OSType[4];
+ short nID;
+ unsigned char* Name;
+ int nSize;
+ IMAGE_RESOURCE();
+ void Reset();
+ };
+
+ struct RESOLUTION_INFO
+ {
+ // Table A-6: ResolutionInfo structure
+ // Type Name Description
+ //-------------------------------------------
+ // Fixed hRes Horizontal resolution in pixels per inch.
+ // int hResUnit 1=display horizontal resolution in pixels per inch;
+ // 2=display horizontal resolution in pixels per cm.
+ // short widthUnit Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
+ // Fixed vRes Vertical resolution in pixels per inch.
+ // int vResUnit 1=display vertical resolution in pixels per inch;
+ // 2=display vertical resolution in pixels per cm.
+ // short heightUnit Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
+ short hRes;
+ int hResUnit;
+ short widthUnit;
+
+ short vRes;
+ int vResUnit;
+ short heightUnit;
+ RESOLUTION_INFO();
+ };
+
+ struct RESOLUTION_INFO_v2 // Obsolete - Photoshop 2.0
+ {
+ short nChannels;
+ short nRows;
+ short nColumns;
+ short nDepth;
+ short nMode;
+ RESOLUTION_INFO_v2();
+ };
+
+ struct DISPLAY_INFO
+ {
+ // This structure contains display information about each channel.
+ //Table A-7: DisplayInfo Color spaces
+ // Color-ID Name Description
+ //-------------------------------------------
+ // 0 RGB The first three values in the color data are red, green, and blue.
+ // They are full unsigned 16–bit values as in Apple’s RGBColor data
+ // structure. Pure red=65535,0,0.
+ // 1 HSB The first three values in the color data are hue, saturation, and
+ // brightness. They are full unsigned 16–bit values as in Apple’s
+ // HSVColor data structure. Pure red=0,65535, 65535.
+ // 2 CMYK The four values in the color data are cyan, magenta, yellow, and
+ // black. They are full unsigned 16–bit values. 0=100% ink. Pure
+ // cyan=0,65535,65535,65535.
+ // 7 Lab The first three values in the color data are lightness, a chrominance,
+ // and b chrominance.
+ // Lightness is a 16–bit value from 0...10000. The chromanance components
+ // are each 16–bit values from –12800...12700. Gray values
+ // are represented by chrominance components of 0. Pure
+ // white=10000,0,0.
+ // 8 grayscale The first value in the color data is the gray value, from 0...10000.
+ short ColourSpace;
+ short Colour[4];
+ short Opacity; // 0..100
+ bool kind; // selected = 0, protected = 1
+ unsigned char padding; // should be zero
+ DISPLAY_INFO();
+ };
+ struct THUMBNAIL
+ {
+ // Adobe Photoshop 5.0 and later stores thumbnail information for preview
+ // display in an image resource block. These resource blocks consist of an
+ // 28 byte header, followed by a JFIF thumbnail in RGB (red, green, blue)
+ // for both Macintosh and Windows. Adobe Photoshop 4.0 stored the
+ // thumbnail information in the same format except the data section is
+ // (blue, green, red). The Adobe Photoshop 4.0 format is at resource ID
+ // and the Adobe Photoshop 5.0 format is at resource ID 1036.
+ // Table 2–5: Thumnail resource header
+ // Type Name Description
+ //-------------------------------------------
+ // 4 bytes format = 1 (kJpegRGB). Also supports kRawRGB (0).
+ // 4 bytes width Width of thumbnail in pixels.
+ // 4 bytes height Height of thumbnail in pixels.
+ // 4 bytes widthbytes Padded row bytes as (width * bitspixel + 31) / 32 * 4.
+ // 4 bytes size Total size as widthbytes * height * planes
+ // 4 bytes compressedsize Size after compression. Used for consistentcy check.
+ // 2 bytes bitspixel = 24. Bits per pixel.
+ // 2 bytes planes = 1. Number of planes.
+ // Variable Data JFIF data in RGB format.
+ // Note: For resource ID 1033 the data is in BGR format.
+ int nFormat;
+ int nWidth;
+ int nHeight;
+ int nWidthBytes;
+ int nSize;
+ int nCompressedSize;
+ short nBitPerPixel;
+ short nPlanes;
+ unsigned char* Data;
+ THUMBNAIL();
+ };
+
+
+ CxImage &m_image;
+
+ HEADER_INFO header_info;
+
+ COLOUR_MODE_DATA colour_mode_data;
+ short mnColourCount;
+ short mnTransparentIndex;
+
+ IMAGE_RESOURCE image_resource;
+
+ int mnGlobalAngle;
+
+ RESOLUTION_INFO resolution_info;
+ bool mbResolutionInfoFilled;
+
+ RESOLUTION_INFO_v2 resolution_info_v2;
+ bool mbResolutionInfoFilled_v2;
+
+ DISPLAY_INFO display_info;
+ bool mbDisplayInfoFilled;
+
+ THUMBNAIL thumbnail;
+ bool mbThumbNailFilled;
+
+ bool mbCopyright;
+
+ int Calculate(unsigned char* c, int nDigits);
+ void XYZToRGB(const double X, const double Y, const double Z, int &R, int &G, int &B);
+ void LabToRGB(const int L, const int a, const int b, int &R, int &G, int &B );
+ void CMYKToRGB(const double C, const double M, const double Y, const double K, int &R, int &G, int &B);
+
+ bool ReadHeader(CxFile &f, HEADER_INFO& header_info);
+ bool ReadColourModeData(CxFile &f, COLOUR_MODE_DATA& colour_mode_data);
+ bool ReadImageResource(CxFile &f, IMAGE_RESOURCE& image_resource);
+ bool ReadLayerAndMaskInfoSection(CxFile &f); // Actually ignore it
+ int ReadImageData(CxFile &f);
+
+ int DecodeRawData(CxFile &pFile);
+ int DecodeRLEData(CxFile &pFile);
+
+ void ProccessBuffer(unsigned char* pData = 0);
+
+ public:
+ CPSD(CxImage &image);
+ ~CPSD();
+
+ int Load(LPCTSTR szPathName);
+ int Load(CxFile &file);
+
+ bool ThumbNailIncluded() const { return mbThumbNailFilled; }
+ void DPI(int &x, int &y) const { x = resolution_info.hRes; y = resolution_info.vRes; }
+ void Dimensions(int &cx, int &cy) const { cx = header_info.nWidth; cy = header_info.nHeight; }
+ int BitsPerPixel() const { return header_info.nBitsPerPixel; }
+ int GlobalAngle() const { return mnGlobalAngle; }
+ bool IsCopyright() const { return mbCopyright; }
+ HBITMAP Detach();
+ };
+}
+
+#endif // __MyPSD_H__
+
+// MyPSD.cpp ///////////////////////////////////////////////////////////////////
+
+
+inline int dti(double value) { return (int)floor(value+.5f); }
+
+#define assert(a)
+
+#define mypsd_fread(a, b, c, d) d.Read(a, b, c)
+#define mypsd_fseek(a, b, c) a.Seek(b, c)
+#define mypsd_feof(a) a.Eof()
+
+namespace MyPSD
+{
+ CPSD::CPSD(CxImage &image) : m_image(image)
+ {
+ mbThumbNailFilled = false;
+ mbDisplayInfoFilled = false;
+ mbResolutionInfoFilled = false;
+ mbResolutionInfoFilled_v2 = false;
+ mnGlobalAngle = 30;
+ mbCopyright = false;
+ mnColourCount = -1;
+ mnTransparentIndex = -1;
+ }
+ CPSD::~CPSD()
+ {
+ // free memory
+ if ( 0 < colour_mode_data.nLength )
+ delete[] colour_mode_data.ColourData;
+ colour_mode_data.ColourData = 0;
+
+ if ( image_resource.Name )
+ delete[] image_resource.Name;
+ image_resource.Name = 0;
+ }
+
+ int CPSD::Calculate(unsigned char* c, int nDigits)
+ {
+ int nValue = 0;
+
+ for(int n = 0; n < nDigits; ++n)
+ nValue = ( nValue << 8 ) | *(c+n);
+
+ return nValue;
+ };
+
+ void CPSD::XYZToRGB(const double X, const double Y, const double Z, int &R, int &G, int &B)
+ {
+ // Standards used Observer = 2, Illuminant = D65
+ // ref_X = 95.047, ref_Y = 100.000, ref_Z = 108.883
+ const double ref_X = 95.047;
+ const double ref_Y = 100.000;
+ const double ref_Z = 108.883;
+
+ double var_X = X / 100.0;
+ double var_Y = Y / 100.0;
+ double var_Z = Z / 100.0;
+
+ double var_R = var_X * 3.2406 + var_Y * (-1.5372) + var_Z * (-0.4986);
+ double var_G = var_X * (-0.9689) + var_Y * 1.8758 + var_Z * 0.0415;
+ double var_B = var_X * 0.0557 + var_Y * (-0.2040) + var_Z * 1.0570;
+
+ if ( var_R > 0.0031308 )
+ var_R = 1.055 * ( pow(var_R, 1/2.4) ) - 0.055;
+ else
+ var_R = 12.92 * var_R;
+
+ if ( var_G > 0.0031308 )
+ var_G = 1.055 * ( pow(var_G, 1/2.4) ) - 0.055;
+ else
+ var_G = 12.92 * var_G;
+
+ if ( var_B > 0.0031308 )
+ var_B = 1.055 * ( pow(var_B, 1/2.4) )- 0.055;
+ else
+ var_B = 12.92 * var_B;
+
+ R = (int)(var_R * 256.0);
+ G = (int)(var_G * 256.0);
+ B = (int)(var_B * 256.0);
+ };
+
+ void CPSD::LabToRGB(const int L, const int a, const int b, int &R, int &G, int &B )
+ {
+ // For the conversion we first convert values to XYZ and then to RGB
+ // Standards used Observer = 2, Illuminant = D65
+ // ref_X = 95.047, ref_Y = 100.000, ref_Z = 108.883
+ const double ref_X = 95.047;
+ const double ref_Y = 100.000;
+ const double ref_Z = 108.883;
+
+ double var_Y = ( (double)L + 16.0 ) / 116.0;
+ double var_X = (double)a / 500.0 + var_Y;
+ double var_Z = var_Y - (double)b / 200.0;
+
+ if ( pow(var_Y, 3) > 0.008856 )
+ var_Y = pow(var_Y, 3);
+ else
+ var_Y = ( var_Y - 16 / 116 ) / 7.787;
+
+ if ( pow(var_X, 3) > 0.008856 )
+ var_X = pow(var_X, 3);
+ else
+ var_X = ( var_X - 16 / 116 ) / 7.787;
+
+ if ( pow(var_Z, 3) > 0.008856 )
+ var_Z = pow(var_Z, 3);
+ else
+ var_Z = ( var_Z - 16 / 116 ) / 7.787;
+
+ double X = ref_X * var_X;
+ double Y = ref_Y * var_Y;
+ double Z = ref_Z * var_Z;
+
+ XYZToRGB(X, Y, Z, R, G, B);
+ };
+
+ void CPSD::CMYKToRGB(const double C, const double M, const double Y, const double K, int &R, int &G, int &B )
+ {
+ R = dti( ( 1.0f - ( C *( 1.0f - K ) + K ) ) * 255.0f );
+ G = dti( ( 1.0f - ( M *( 1.0f - K ) + K ) ) * 255.0f );
+ B = dti( ( 1.0f - ( Y *( 1.0f - K ) + K ) ) * 255.0f );
+ };
+
+ bool CPSD::ReadLayerAndMaskInfoSection(CxFile &pFile) // Actually ignore it
+ {
+ bool bSuccess = false;
+
+ unsigned char DataLength[4];
+ int nBytesRead = 0;
+ int nItemsRead = (int)(int)mypsd_fread(&DataLength, sizeof(DataLength), 1, pFile);
+
+ int nTotalBytes = Calculate( DataLength, sizeof(DataLength) );
+
+ unsigned char data[1];
+ while( !mypsd_feof( pFile ) && ( nBytesRead < nTotalBytes ) )
+ {
+ data[0] = '\0';
+ nItemsRead = (int)(int)mypsd_fread(&data, sizeof(data), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(data);
+ }
+
+ assert ( nBytesRead == nTotalBytes );
+ if ( nBytesRead == nTotalBytes )
+ bSuccess = true;
+
+ return bSuccess;
+ }
+ bool CPSD::ReadImageResource(CxFile &pFile, IMAGE_RESOURCE& image_resource)
+ {
+ bool bSuccess = false;
+
+ unsigned char Length[4];
+ int nItemsRead = (int)(int)mypsd_fread(&Length, sizeof(Length), 1, pFile);
+
+ image_resource.nLength = Calculate( Length, sizeof(image_resource.nLength) );
+
+ int nBytesRead = 0;
+ int nTotalBytes = image_resource.nLength;
+
+ while( !mypsd_feof( pFile ) && ( nBytesRead < nTotalBytes ) )
+ {
+ nItemsRead = 0;
+ image_resource.Reset();
+
+ nItemsRead = (int)(int)mypsd_fread(&image_resource.OSType, sizeof(image_resource.OSType), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(image_resource.OSType);
+
+ assert ( 0 == (nBytesRead % 2) );
+ if (::memcmp(image_resource.OSType, "8BIM", 4) == 0)
+ {
+ unsigned char ID[2];
+ nItemsRead = (int)(int)mypsd_fread(&ID, sizeof(ID), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ID);
+
+ image_resource.nID = (short)Calculate( ID, sizeof(ID) );
+
+ unsigned char SizeOfName;
+ nItemsRead = (int)(int)mypsd_fread(&SizeOfName, sizeof(SizeOfName), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(SizeOfName);
+
+ int nSizeOfName = Calculate( &SizeOfName, sizeof(SizeOfName) );
+ if ( 0 < nSizeOfName )
+ {
+ image_resource.Name = new unsigned char[nSizeOfName];
+ nItemsRead = (int)(int)mypsd_fread(image_resource.Name, nSizeOfName, 1, pFile);
+ nBytesRead += nItemsRead * nSizeOfName;
+ }
+
+ if ( 0 == (nSizeOfName % 2) )
+ {
+ nItemsRead = (int)(int)mypsd_fread(&SizeOfName, sizeof(SizeOfName), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(SizeOfName);
+ }
+
+ unsigned char Size[4];
+ nItemsRead = (int)(int)mypsd_fread(&Size, sizeof(Size), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(Size);
+
+ image_resource.nSize = Calculate( Size, sizeof(image_resource.nSize) );
+
+ if ( 0 != (image_resource.nSize % 2) ) // resource data must be even
+ image_resource.nSize++;
+ if ( 0 < image_resource.nSize )
+ {
+ unsigned char IntValue[4];
+ unsigned char ShortValue[2];
+
+ switch( image_resource.nID )
+ {
+ case 1000:
+ {
+ // Obsolete - Photoshop 2.0
+ mbResolutionInfoFilled_v2 = true;
+
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nChannels = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nChannels) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nRows = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nRows) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nColumns = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nColumns) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nDepth = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nDepth) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info_v2.nMode = (short)Calculate(ShortValue, sizeof(resolution_info_v2.nMode) );
+ }
+ break;
+ case 1005:
+ {
+ mbResolutionInfoFilled = true;
+
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info.hRes = (short)Calculate(ShortValue, sizeof(resolution_info.hRes) );
+ nItemsRead = (int)(int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ resolution_info.hResUnit = Calculate(IntValue, sizeof(resolution_info.hResUnit) );
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info.widthUnit = (short)Calculate(ShortValue, sizeof(resolution_info.widthUnit) );
+
+ nItemsRead = (int)(int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info.vRes = (short)Calculate(ShortValue, sizeof(resolution_info.vRes) );
+ nItemsRead = (int)(int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ resolution_info.vResUnit = Calculate(IntValue, sizeof(resolution_info.vResUnit) );
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ resolution_info.heightUnit = (short)Calculate(ShortValue, sizeof(resolution_info.heightUnit) );
+ }
+ break;
+ case 1007:
+ {
+ mbDisplayInfoFilled = true;
+
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ display_info.ColourSpace = (short)Calculate(ShortValue, sizeof(display_info.ColourSpace) );
+
+ for ( unsigned int n = 0; n < 4; ++n )
+ {
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ display_info.Colour[n] = (short)Calculate(ShortValue, sizeof(display_info.Colour[n]) );
+ }
+
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ display_info.Opacity = (short)Calculate(ShortValue, sizeof(display_info.Opacity) );
+ assert ( 0 <= display_info.Opacity );
+ assert ( 100 >= display_info.Opacity );
+
+ unsigned char c[1];
+ nItemsRead = (int)mypsd_fread(&c, sizeof(c), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(c);
+ ( 1 == Calculate(c, sizeof(c) ) ) ? display_info.kind = true : display_info.kind = false;
+
+ nItemsRead = (int)mypsd_fread(&c, sizeof(c), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(c);
+ display_info.padding = (unsigned int)Calculate(c, sizeof(c) );
+ assert ( 0 == display_info.padding );
+ }
+ break;
+ case 1034:
+ {
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ ( 1 == Calculate(ShortValue, sizeof(ShortValue) ) ) ? mbCopyright = true : mbCopyright = false;
+ }
+ break;
+ case 1033:
+ case 1036:
+ {
+ mbThumbNailFilled = true;
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nFormat = Calculate(IntValue, sizeof(thumbnail.nFormat) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nWidth = Calculate(IntValue, sizeof(thumbnail.nWidth) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nHeight = Calculate(IntValue, sizeof(thumbnail.nHeight) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nWidthBytes = Calculate(IntValue, sizeof(thumbnail.nWidthBytes) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nSize = Calculate(IntValue, sizeof(thumbnail.nSize) );
+
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ thumbnail.nCompressedSize = Calculate(IntValue, sizeof(thumbnail.nCompressedSize) );
+
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ thumbnail.nBitPerPixel = (short)Calculate(ShortValue, sizeof(thumbnail.nBitPerPixel) );
+
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ thumbnail.nPlanes = (short)Calculate(ShortValue, sizeof(thumbnail.nPlanes) );
+
+ int nTotalData = image_resource.nSize - 28; // header
+ unsigned char* buffer = new unsigned char[nTotalData];
+ unsigned char c[1];
+ if ( 1033 == image_resource.nID )
+ {
+ // In BGR format
+ for (int n = 0; n < nTotalData; n = n +3 )
+ {
+ nItemsRead = (int)mypsd_fread(&c, sizeof(unsigned char), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(unsigned char);
+ buffer[n+2] = (unsigned char)Calculate(c, sizeof(unsigned char) );
+ nItemsRead = (int)mypsd_fread(&c, sizeof(unsigned char), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(unsigned char);
+ buffer[n+1] = (unsigned char)Calculate(c, sizeof(BYTE) );
+ nItemsRead = (int)mypsd_fread(&c, sizeof(unsigned char), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(unsigned char);
+ buffer[n] = (unsigned char)Calculate(c, sizeof(unsigned char) );
+ }
+ }
+ else if ( 1036 == image_resource.nID )
+ {
+ // In RGB format
+ for (int n = 0; n < nTotalData; ++n )
+ {
+ nItemsRead = (int)mypsd_fread(&c, sizeof(BYTE), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(BYTE);
+ buffer[n] = (BYTE)Calculate(c, sizeof(BYTE) );
+ }
+ }
+
+ delete[] buffer;
+ buffer = 0;
+ }
+ break;
+ case 1037:
+ {
+ nItemsRead = (int)mypsd_fread(&IntValue, sizeof(IntValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(IntValue);
+ mnGlobalAngle = Calculate(IntValue, sizeof(mnGlobalAngle) );
+ }
+ break;
+ case 1046:
+ {
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ mnColourCount = (short)Calculate(ShortValue, sizeof(ShortValue) );
+ }
+ break;
+ case 1047:
+ {
+ nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ nBytesRead += nItemsRead * sizeof(ShortValue);
+ mnTransparentIndex = (short)Calculate(ShortValue, sizeof(ShortValue) );
+ }
+ break;
+
+ default:
+ pFile.Seek(image_resource.nSize, SEEK_CUR);
+ nBytesRead += image_resource.nSize;
+ break;
+ }
+ }
+ }
+ }
+
+ assert ( nBytesRead == nTotalBytes );
+ if ( nBytesRead == nTotalBytes )
+ bSuccess = true;
+
+ return bSuccess;
+ }
+ bool CPSD::ReadColourModeData(CxFile &pFile, COLOUR_MODE_DATA& colour_mode_data)
+ {
+ // Only indexed colour and duotone have colour mode data,
+ // for all other modes this section is 4 bytes length, the length field is set to zero
+
+ // For indexed color images, the length will be equal to 768, and the color
+ // will contain the color table for the image, in non–interleaved order.
+
+ // For duotone images, the color data will contain the duotone specification,
+ // the format of which is not documented. Other applications that read
+ // Photoshop files can treat a duotone image as a grayscale image, and just
+ // preserve the contents of the duotone information when reading and writing
+ // the file.
+
+ // free memory
+ if ( 0 < colour_mode_data.nLength )
+ delete[] colour_mode_data.ColourData;
+ colour_mode_data.ColourData = 0;
+
+ unsigned char Length[4];
+ int nItemsRead = (int)mypsd_fread(&Length, sizeof(Length), 1, pFile);
+
+ colour_mode_data.nLength = Calculate( Length, sizeof(colour_mode_data.nLength) );
+ if ( 0 < colour_mode_data.nLength )
+ {
+ colour_mode_data.ColourData = new unsigned char[colour_mode_data.nLength];
+ nItemsRead = 0;
+ memset(colour_mode_data.ColourData, 254, colour_mode_data.nLength);
+
+ nItemsRead += (int)mypsd_fread( colour_mode_data.ColourData, colour_mode_data.nLength, 1, pFile);
+
+ }
+
+ return true;
+ }
+
+ bool CPSD::ReadHeader(CxFile &pFile, HEADER_INFO& header_info)
+ {
+ bool bSuccess = false;
+
+ struct HEADER
+ {
+ char Signature[4]; // always equal 8BPS, do not read file if not
+ unsigned char Version[2]; // always equal 1, do not read file if not
+ char Reserved[6]; // must be zero
+ unsigned char Channels[2]; // numer of channels including any alpha channels, supported range 1 to 24
+ unsigned char Rows[4]; // height in PIXELS, supported range 1 to 30000
+ unsigned char Columns[4]; // width in PIXELS, supported range 1 to 30000
+ unsigned char Depth[2]; // number of bpp
+ unsigned char Mode[2]; // colour mode of the file,
+ // Btmap=0, Grayscale=1, Indexed=2, RGB=3,
+ // CMYK=4, Multichannel=7, Duotone=8, Lab=9
+ };
+
+ HEADER header;
+ int nItemsRead = (int)mypsd_fread(&header, sizeof(HEADER), 1, pFile);
+ if ( nItemsRead )
+ {
+ if ( 0 == ::memcmp(header.Signature, "8BPS", 4))
+ {
+ int nVersion = Calculate( header.Version, sizeof(header.Version) );
+
+ if ( 1 == nVersion )
+ {
+ unsigned int n = 0;
+ bool bOK = true;
+ while ( (n < 6) && bOK )
+ {
+ if ( '\0' != header.Reserved[n] )
+ bOK = false;
+ n++;
+ }
+ bSuccess = bOK;
+
+ if ( bSuccess )
+ {
+ header_info.nChannels = (short)Calculate( header.Channels, sizeof(header.Channels) );
+ header_info.nHeight = Calculate( header.Rows, sizeof(header.Rows) );
+ header_info.nWidth = Calculate( header.Columns, sizeof(header.Columns) );
+ header_info.nBitsPerPixel = (short)Calculate( header.Depth, sizeof(header.Depth) );
+ header_info.nColourMode = (short)Calculate( header.Mode, sizeof(header.Mode) );
+ }
+ }
+ }
+ }
+
+ return bSuccess;
+ }
+
+
+ void CPSD::ProccessBuffer(unsigned char* pData )
+ {
+ if (!pData) return;
+
+ switch ( header_info.nColourMode )
+ {
+ case 1: // Grayscale
+ case 8: // Duotone
+ {
+ bool bAlpha = header_info.nChannels > 1;
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGBA = new byte[nPixels * (bAlpha ? 4 : 3)];
+ byte *pSrc = pData, *pDst = pRGBA;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += bAlpha ? 4 : 3)
+ {
+ pDst[0] = pDst[1] = pDst[2] = pSrc[0];
+ if (bAlpha) pDst[3] = pSrc[1];
+ }
+
+ m_image.CreateFromArray(pRGBA, header_info.nWidth, header_info.nHeight, bAlpha ? 32 : 24, header_info.nWidth * (bAlpha ? 4 : 3), true);
+
+ delete [] pRGBA;
+ }
+ break;
+ case 2: // Indexed
+ {
+ if (!colour_mode_data.ColourData) break;
+ if (colour_mode_data.nLength != 768) break;
+ if (mnColourCount == 0) break;
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGB = new byte[nPixels * 3];
+ ::memset(pRGB, 0, nPixels * 3);
+ byte *pSrc = pData, *pDst = pRGB;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += 3)
+ {
+ int nIndex = *pSrc;
+ pDst[2] = colour_mode_data.ColourData[nIndex + 0 * 256];
+ pDst[1] = colour_mode_data.ColourData[nIndex + 1 * 256];
+ pDst[0] = colour_mode_data.ColourData[nIndex + 2 * 256];
+ }
+
+ m_image.CreateFromArray(pRGB, header_info.nWidth, header_info.nHeight, 24, header_info.nWidth * 3, true);
+ delete [] pRGB;
+ }
+ break;
+ case 3: // RGB
+ {
+ m_image.CreateFromArray(pData, header_info.nWidth, header_info.nHeight, header_info.nChannels == 3 ? 24 : 32, header_info.nWidth * header_info.nChannels, true);
+ m_image.SwapRGB2BGR();
+ }
+ break;
+ case 4: // CMYK
+ {
+ bool bAlpha = header_info.nChannels > 4;
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGBA = new byte[nPixels * (bAlpha ? 4 : 3)];
+ byte *pSrc = pData, *pDst = pRGBA;
+ double C, M, Y, K;
+ int nRed, nGreen, nBlue;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += bAlpha ? 4 : 3)
+ {
+ C = (1.0 - (double)pSrc[0] / 256);
+ M = (1.0 - (double)pSrc[1] / 256);
+ Y = (1.0 - (double)pSrc[2] / 256);
+ K = (1.0 - (double)pSrc[3] / 256);
+
+ CMYKToRGB(C, M, Y, K, nRed, nGreen, nBlue);
+
+ if (0 > nRed) nRed = 0; else if (255 < nRed) nRed = 255;
+ if (0 > nGreen) nGreen = 0; else if (255 < nGreen) nGreen = 255;
+ if (0 > nBlue) nBlue = 0; else if (255 < nBlue) nBlue = 255;
+
+ pDst[0] = nBlue; pDst[1] = nGreen; pDst[2] = nRed;
+ if (bAlpha) pDst[3] = pSrc[4];
+ }
+
+ m_image.CreateFromArray(pRGBA, header_info.nWidth, header_info.nHeight, bAlpha ? 32 : 24, header_info.nWidth * (bAlpha ? 4 : 3), true);
+
+ delete [] pRGBA;
+ }
+ break;
+ case 7: // Multichannel
+ {
+ if (header_info.nChannels == 0 || header_info.nChannels > 4) break; // ???
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGB = new byte[nPixels * 3];
+ byte *pSrc = pData, *pDst = pRGB;
+ double C, M, Y, K;
+ int nRed, nGreen, nBlue;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += 3)
+ {
+ C = M = Y = K = 0;
+ C = (1.0 - (double)pSrc[0] / 256);
+ if (header_info.nChannels > 1) M = (1.0 - (double)pSrc[1] / 256);
+ if (header_info.nChannels > 2) Y = (1.0 - (double)pSrc[2] / 256);
+ if (header_info.nChannels > 3) K = (1.0 - (double)pSrc[3] / 256);
+
+ CMYKToRGB(C, M, Y, K, nRed, nGreen, nBlue);
+
+ if (0 > nRed) nRed = 0; else if (255 < nRed) nRed = 255;
+ if (0 > nGreen) nGreen = 0; else if (255 < nGreen) nGreen = 255;
+ if (0 > nBlue) nBlue = 0; else if (255 < nBlue) nBlue = 255;
+
+ pDst[0] = nBlue; pDst[1] = nGreen; pDst[2] = nRed;
+ }
+
+ m_image.CreateFromArray(pRGB, header_info.nWidth, header_info.nHeight, 24, header_info.nWidth * 3, true);
+
+ delete [] pRGB;
+ }
+ break;
+ case 9: // Lab
+ {
+ bool bAlpha = header_info.nChannels > 3;
+
+ int nPixels = header_info.nWidth * header_info.nHeight;
+ byte *pRGBA = new byte[nPixels * (bAlpha ? 4 : 3)];
+ byte *pSrc = pData, *pDst = pRGBA;
+
+ double L_coef = 256.f / 100.f, a_coef = 256.f / 256.f, b_coef = 256.f / 256.f;
+ int L, a, b;
+ int nRed, nGreen, nBlue;
+ for (int i = 0; i < nPixels; i++, pSrc += header_info.nChannels, pDst += bAlpha ? 4 : 3)
+ {
+ L = (int)((float)pSrc[0] / L_coef);
+ a = (int)((float)pSrc[1] / a_coef - 128.0);
+ b = (int)((float)pSrc[2] / b_coef - 128.0);
+
+ LabToRGB(L, a, b, nRed, nGreen, nBlue );
+
+ if (0 > nRed) nRed = 0; else if (255 < nRed) nRed = 255;
+ if (0 > nGreen) nGreen = 0; else if (255 < nGreen) nGreen = 255;
+ if (0 > nBlue) nBlue = 0; else if (255 < nBlue) nBlue = 255;
+
+ pDst[0] = nBlue; pDst[1] = nGreen; pDst[2] = nRed;
+ if (bAlpha) pDst[3] = pSrc[3];
+ }
+
+ m_image.CreateFromArray(pRGBA, header_info.nWidth, header_info.nHeight, bAlpha ? 32 : 24, header_info.nWidth * (bAlpha ? 4 : 3), true);
+
+ delete [] pRGBA;
+ }
+ break;
+ }
+ }
+
+ int CPSD::Load(LPCTSTR szPathName)
+ {
+ CxIOFile f;
+ if (!f.Open(szPathName, _T("rb"))) return -1;
+ return Load(f);
+ }
+
+ int CPSD::Load(CxFile &f)
+ {
+ if (!ReadHeader(f, header_info)) return -2; // Error in header
+ if (!ReadColourModeData(f, colour_mode_data)) return -3; // Error in ColourMode Data
+ if (!ReadImageResource(f, image_resource)) return -4; // Error in Image Resource
+ if (!ReadLayerAndMaskInfoSection(f)) return -5; // Error in Mask Info
+ if (ReadImageData(f) != 0) return -6; // Error in Image Data
+ return 0; // all right
+ }
+
+ int CPSD::DecodeRawData( CxFile &pFile)
+ {
+ if (header_info.nBitsPerPixel != 8 && header_info.nBitsPerPixel != 16) return -7; // can't read this
+
+ int nWidth = header_info.nWidth;
+ int nHeight = header_info.nHeight;
+ int bytesPerPixelPerChannel = header_info.nBitsPerPixel / 8;
+
+ int nPixels = nWidth * nHeight;
+ int nTotalBytes = 0;
+
+ byte* pData = NULL;
+
+ switch ( header_info.nColourMode )
+ {
+ case 1: // Grayscale
+ case 2: // Indexed
+ case 3: // RGB
+ case 4: // CMYK
+ case 8: // Duotone
+ case 9: // Lab
+ {
+ // read RRRRRRRGGGGGGGBBBBBBAAAAAA data
+ int nAllDataSize = nPixels * bytesPerPixelPerChannel * header_info.nChannels;
+ byte *pFileData = new byte[nAllDataSize];
+ ::memset(pFileData, 0, nAllDataSize);
+ if (pFile.Read(pFileData, nAllDataSize, 1) != 1)
+ {
+ delete [] pFileData;
+ return -1; // bad data
+ }
+
+ // and convert them to RGBARGBARGBA data (depends on number of channels)
+ nTotalBytes = nPixels * header_info.nChannels;
+ pData = new byte[nTotalBytes];
+ byte *pSource = pFileData;
+ for (int nChannel = 0; nChannel < header_info.nChannels; nChannel++)
+ {
+ byte *pDest = pData + nChannel;
+ for (int pos = 0; pos < nPixels; pos++, pDest += header_info.nChannels, pSource += bytesPerPixelPerChannel) *pDest = *pSource;
+ }
+ delete [] pFileData;
+ }
+ break;
+ default:
+ return -1; // unsupported format
+ }
+
+ ProccessBuffer(pData);
+ delete [] pData;
+
+ // dpi related things
+ int ppm_x = 3780; // 96 dpi
+ int ppm_y = 3780; // 96 dpi
+ if (mbResolutionInfoFilled)
+ {
+ int nHorResolution = (int)resolution_info.hRes;
+ int nVertResolution = (int)resolution_info.vRes;
+ ppm_x = (nHorResolution * 10000) / 254;
+ ppm_y = (nVertResolution * 10000) / 254;
+ }
+ m_image.SetXDPI(ppm_x);
+ m_image.SetYDPI(ppm_y);
+
+ return 0;
+ }
+
+
+ int CPSD::DecodeRLEData(CxFile & pFile)
+ {
+ if (header_info.nBitsPerPixel != 8) return -7; // can't read this
+
+ int nWidth = header_info.nWidth;
+ int nHeight = header_info.nHeight;
+ int nPixels = nWidth * nHeight;
+
+ // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data
+ // read them and compute size of RLE data
+ int nLengthDataSize = nHeight * header_info.nChannels * 2;
+ byte *pLengthData = new byte[nLengthDataSize];
+ if (pFile.Read(pLengthData, nLengthDataSize, 1) != 1)
+ {
+ delete [] pLengthData;
+ return -1; // error while reading
+ }
+ int nRLEDataSize = 0;
+ for (int i = 0; i < nHeight * header_info.nChannels * 2; i += 2)
+ nRLEDataSize += Calculate(pLengthData + i, 2);
+ delete [] pLengthData;
+
+ // now read RLE data to the buffer for fast access
+ byte *pRLEData = new byte[nRLEDataSize];
+ if (pFile.Read(pRLEData, nRLEDataSize, 1) != 1)
+ {
+ delete [] pRLEData;
+ return -1;
+ }
+
+ // allocate buffer for raw data (RRRRRRR...RRRGGGGG...GGGGGGBBBBB...BBBBBAAAAA....AAAAA) it has the same size as the final buffer
+ // and the perform RLE-decoding
+ int nTotalBytes = nPixels * header_info.nChannels;
+ byte* pRawData = new byte[nTotalBytes];
+ byte *pRLESource = pRLEData, *pRLEDest = pRawData;
+ for (int channel = 0; channel < header_info.nChannels; channel++)
+ {
+ int nCount = 0;
+ while (nCount < nPixels)
+ {
+ int len = *pRLESource++;
+ if ( 128 > len )
+ { // copy next (len + 1) bytes as is
+ len++;
+ nCount += len;
+ ::memcpy(pRLEDest, pRLESource, len);
+ pRLEDest += len; pRLESource += len;
+ }
+ else if ( 128 < len )
+ {
+ // Next -len+1 bytes in the dest are replicated from next source byte.
+ // (Interpret len as a negative 8-bit int.)
+ len ^= 0x0FF;
+ len += 2;
+ nCount += len;
+ ::memset(pRLEDest, *pRLESource++, len);
+ pRLEDest += len;
+ }
+ else if ( 128 == len ) { /* Do nothing */ }
+ }
+ }
+ delete [] pRLEData;
+
+ // transform raw data to the good one (RGBARGBARGBA...RGBA)
+ byte *pRawSource = pRawData;
+ byte *pData = new byte[nTotalBytes];
+ int nPixelCounter = 0;
+ for( int nColour = 0; nColour < header_info.nChannels; ++nColour )
+ {
+ nPixelCounter = nColour;
+ for (int nPos = 0; nPos < nPixels; nPos++, pRawSource++)
+ {
+ pData[nPixelCounter] = *pRawSource;
+ nPixelCounter += header_info.nChannels;
+ }
+ }
+ delete[] pRawData;
+
+ // create image
+ ProccessBuffer(pData);
+ delete [] pData;
+
+ // dpi related things
+ int ppm_x = 3780; // 96 dpi
+ int ppm_y = 3780; // 96 dpi
+ if (mbResolutionInfoFilled)
+ {
+ int nHorResolution = (int)resolution_info.hRes;
+ int nVertResolution = (int)resolution_info.vRes;
+ ppm_x = (nHorResolution * 10000) / 254;
+ ppm_y = (nVertResolution * 10000) / 254;
+ }
+ m_image.SetXDPI(ppm_x);
+ m_image.SetYDPI(ppm_y);
+
+ return 0;
+ }
+
+ int CPSD::ReadImageData(CxFile &pFile)
+ {
+ int nErrorCode = 0; // No Errors
+
+ if ( !mypsd_feof(pFile) )
+ {
+ unsigned char ShortValue[2];
+ int nBytesRead = 0;
+ int nItemsRead = (int)mypsd_fread(&ShortValue, sizeof(ShortValue), 1, pFile);
+ short nCompression = (short)Calculate( ShortValue, sizeof(ShortValue) );
+
+ switch ( nCompression )
+ {
+ case 0: // raw data
+ nErrorCode = DecodeRawData(pFile);
+ break;
+ case 1: // RLE compression
+ nErrorCode = DecodeRLEData(pFile);
+ break;
+ case 2: // ZIP without prediction
+ nErrorCode = -10; // ZIP without prediction, no specification
+ break;
+ case 3: // ZIP with prediction
+ nErrorCode = -11; // ZIP with prediction, no specification
+ break;
+ default:
+ nErrorCode = -12; // Unknown format
+ }
+ }
+ return nErrorCode;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
+ CPSD::HEADER_INFO::HEADER_INFO()
+ {
+ nChannels = -1;
+ nHeight = -1;
+ nWidth = -1;
+ nBitsPerPixel = -1;
+ nColourMode = -1;
+ }
+
+ CPSD::COLOUR_MODE_DATA::COLOUR_MODE_DATA()
+ {
+ nLength = -1;
+ ColourData = 0;
+ }
+
+ CPSD::IMAGE_RESOURCE::IMAGE_RESOURCE()
+ {
+ Name = 0;
+ Reset();
+ }
+
+ void CPSD::IMAGE_RESOURCE::Reset()
+ {
+ nLength = -1;
+ memset( OSType, '\0', sizeof(OSType) );
+ nID = -1;
+ if ( Name )
+ delete[] Name;
+ Name = 0;
+ nSize = -1;
+ }
+
+ CPSD::RESOLUTION_INFO::RESOLUTION_INFO()
+ {
+ hRes = -1;
+ hResUnit = -1;
+ widthUnit = -1;
+ vRes = -1;
+ vResUnit = -1;
+ heightUnit = -1;
+ }
+
+ CPSD::RESOLUTION_INFO_v2::RESOLUTION_INFO_v2()
+ {
+ nChannels = -1;
+ nRows = -1;
+ nColumns = -1;
+ nDepth = -1;
+ nMode = -1;
+ }
+
+ CPSD::DISPLAY_INFO::DISPLAY_INFO()
+ {
+ ColourSpace = -1;
+ for ( unsigned int n = 0; n < 4; ++n)
+ Colour[n] = 0;
+ Opacity = -1;
+ kind = false;
+ padding = '0';
+ }
+
+ CPSD::THUMBNAIL::THUMBNAIL()
+ {
+ nFormat = -1;
+ nWidth = -1;
+ nHeight = -1;
+ nWidthBytes = -1;
+ nSize = -1;
+ nCompressedSize = -1;
+ nBitPerPixel = -1;
+ nPlanes = -1;
+ Data = 0;
+ }
+} // MyPSD
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_USE_LIBPSD
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImagePSD::Decode(CxFile *hFile)
+{
+ if (hFile==NULL)
+ return false;
+
+#if CXIMAGE_USE_LIBPSD
+ psd_context* context = NULL;
+#endif
+
+ cx_try
+ {
+#if CXIMAGE_USE_LIBPSD
+
+ psd_status status;
+
+ context = (psd_context *)malloc(sizeof(psd_context));
+ if(context == NULL){
+ cx_throw("CxImagePSD: psd_status_malloc_failed");
+ }
+ memset(context, 0, sizeof(psd_context));
+
+ // install file manager
+ CxFilePsd src(hFile,context);
+
+ context->state = PSD_FILE_HEADER;
+ context->stream.file_length = hFile->Size();
+ context->load_tag = psd_load_tag_all;
+ status = psd_main_loop(context);
+
+ if(status != psd_status_done){
+ cx_throw("CxImagePSD: psd_main_loop failed");
+ }
+
+ Create(context->width,context->height,24,CXIMAGE_FORMAT_PSD);
+
+ uint8_t* rgba = (uint8_t*)context->merged_image_data;
+ uint8_t* alpha = NULL;
+ if (context->alpha_channel_info)
+ alpha = (uint8_t*)context->alpha_channel_info->channel_data;
+ if (alpha)
+ AlphaCreate();
+
+ int32_t x,y;
+ RGBQUAD c;
+ c.rgbReserved = 0;
+ if (rgba){
+ for(y =context->height-1; y--;){
+ for (x=0; x<context->width; x++){
+ c.rgbBlue = *rgba++;
+ c.rgbGreen = *rgba++;
+ c.rgbRed = *rgba++;
+ rgba++;
+ SetPixelColor(x,y,c);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (alpha) AlphaSet(x,y,*alpha++);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+ }
+
+ psd_image_free(context);
+ free(context);
+
+#else //CXIMAGE_USE_LIBPSD == 0
+
+ MyPSD::CPSD psd(*this);
+ int nErrorCode = psd.Load(*hFile);
+ if (nErrorCode != 0) cx_throw("error loading PSD file");
+
+#endif //CXIMAGE_USE_LIBPSD
+
+ } cx_catch {
+
+#if CXIMAGE_USE_LIBPSD
+ psd_image_free(context);
+ if (context) free(context);
+#endif //CXIMAGE_USE_LIBPSD
+
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_PSD) return true;
+ return false;
+ }
+ /* that's it */
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImagePSD::Encode(CxFile * hFile)
+{
+ if (hFile == NULL) return false;
+ strcpy(info.szLastError, "Save PSD not supported");
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_PSD
+
diff --git a/archive/hge/CxImage/ximapsd.h b/archive/hge/CxImage/ximapsd.h new file mode 100644 index 0000000..92be8f1 --- /dev/null +++ b/archive/hge/CxImage/ximapsd.h @@ -0,0 +1,110 @@ +/*
+ * File: ximapsd.h
+ * Purpose: PSD Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImagePSD (c) Dec/2010
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * libpsd (c) 2004-2007 Graphest Software
+ *
+ * ==========================================================
+ */
+#if !defined(__ximaPSD_h)
+#define __ximaPSD_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_PSD
+
+#define CXIMAGE_USE_LIBPSD 1
+
+#if CXIMAGE_USE_LIBPSD
+ extern "C" {
+ #include "../libpsd/libpsd.h"
+ }
+#endif
+
+class CxImagePSD: public CxImage
+{
+
+public:
+ CxImagePSD(): CxImage(CXIMAGE_FORMAT_PSD) {}
+
+// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_PSD);}
+// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_PSD);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+//#if CXIMAGE_SUPPORT_EXIF
+// bool GetExifThumbnail(const TCHAR *filename, const TCHAR *outname, int32_t type);
+//#endif //CXIMAGE_SUPPORT_EXIF
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+#if CXIMAGE_USE_LIBPSD
+protected:
+ class CxFilePsd
+ {
+ public:
+ CxFilePsd(CxFile* pFile,psd_context *context)
+ {
+ context->file = pFile;
+
+ psd_CxFile_ops.size_ = psd_file_size;
+ psd_CxFile_ops.seek_ = psd_file_seek;
+ psd_CxFile_ops.read_ = psd_file_read;
+// psd_CxFile_ops.write_ = psd_file_write;
+// psd_CxFile_ops.close_ = psd_file_close;
+// psd_CxFile_ops.gets_ = psd_file_gets;
+// psd_CxFile_ops.eof_ = psd_file_eof;
+// psd_CxFile_ops.tell_ = psd_file_tell;
+// psd_CxFile_ops.getc_ = psd_file_getc;
+// psd_CxFile_ops.scanf_ = psd_file_scanf;
+
+ context->ops_ = &psd_CxFile_ops;
+
+ }
+
+ static int32_t psd_file_size(psd_file_obj *obj)
+ { return ((CxFile*)obj)->Size(); }
+
+ static int32_t psd_file_seek(psd_file_obj *obj, int32_t offset, int32_t origin)
+ { return ((CxFile*)obj)->Seek(offset,origin); }
+
+ static int32_t psd_file_read(psd_file_obj *obj, void *buf, int32_t size, int32_t cnt)
+ { return ((CxFile*)obj)->Read(buf,size,cnt); }
+
+// static int32_t psd_file_write(psd_file_obj *obj, void *buf, int32_t size, int32_t cnt)
+// { return ((CxFile*)obj)->Write(buf,size,cnt); }
+
+// static int32_t psd_file_close(psd_file_obj *obj)
+// { return 1; /*((CxFile*)obj)->Close();*/ }
+
+// static char* psd_file_gets(psd_file_obj *obj, char *string, int32_t n)
+// { return ((CxFile*)obj)->GetS(string,n); }
+
+// static int32_t psd_file_eof(psd_file_obj *obj)
+// { return ((CxFile*)obj)->Eof(); }
+
+// static long psd_file_tell(psd_file_obj *obj)
+// { return ((CxFile*)obj)->Tell(); }
+
+// static int32_t psd_file_getc(psd_file_obj *obj)
+// { return ((CxFile*)obj)->GetC(); }
+
+// static int32_t psd_file_scanf(psd_file_obj *obj,const char *format, void* output)
+// { return ((CxFile*)obj)->Scanf(format, output); }
+
+ private:
+ psd_file_ops psd_CxFile_ops;
+ };
+#endif //CXIMAGE_USE_LIBPSD
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximaraw.cpp b/archive/hge/CxImage/ximaraw.cpp new file mode 100644 index 0000000..aedc50a --- /dev/null +++ b/archive/hge/CxImage/ximaraw.cpp @@ -0,0 +1,331 @@ +/*
+ * File: ximaraw.cpp
+ * Purpose: Platform Independent RAW Image Class Loader
+ * 16/Dec/2007 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ *
+ * CxImageRAW (c) May/2006 pdw63
+ *
+ * based on dcraw.c -- Dave Coffin's raw photo decoder
+ * Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net
+ */
+
+#include "ximaraw.h"
+
+#if CXIMAGE_SUPPORT_RAW
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageRAW::Decode(CxFile *hFile)
+{
+ if (hFile==NULL)
+ return false;
+
+ DCRAW dcr;
+
+ cx_try
+ {
+ // initialization
+ dcr_init_dcraw(&dcr);
+
+ dcr.opt.user_qual = GetCodecOption(CXIMAGE_FORMAT_RAW) & 0x03;
+
+ // setup variables for debugging
+ char szClass[] = "CxImageRAW";
+ dcr.ifname = szClass;
+ dcr.sz_error = info.szLastError;
+
+ // setup library options, see dcr_print_manual for the available switches
+ // call dcr_parse_command_line_options(&dcr,0,0,0) to set default options
+ // if (dcr_parse_command_line_options(&dcr,argc,argv,&arg))
+ if (dcr_parse_command_line_options(&dcr,0,0,0)){
+ cx_throw("CxImageRAW: unknown option");
+ }
+
+ // set return point for error handling
+ if (setjmp (dcr.failure)) {
+ cx_throw("");
+ }
+
+ // install file manager
+ CxFileRaw src(hFile,&dcr);
+
+ // check file header
+ dcr_identify(&dcr);
+
+ if(!dcr.is_raw){
+ cx_throw("CxImageRAW: not a raw image");
+ }
+
+ if (dcr.load_raw == NULL) {
+ cx_throw("CxImageRAW: missing raw decoder");
+ }
+
+ // verify special case
+ if (dcr.load_raw == dcr_kodak_ycbcr_load_raw) {
+ dcr.height += dcr.height & 1;
+ dcr.width += dcr.width & 1;
+ }
+
+ if (info.nEscape == -1){
+ head.biWidth = dcr.width;
+ head.biHeight= dcr.height;
+ info.dwType = CXIMAGE_FORMAT_RAW;
+ cx_throw("output dimensions returned");
+ }
+
+ // shrinked decoding available and requested?
+ dcr.shrink = dcr.filters && (dcr.opt.half_size || dcr.opt.threshold || dcr.opt.aber[0] != 1 || dcr.opt.aber[2] != 1);
+ dcr.iheight = (dcr.height + dcr.shrink) >> dcr.shrink;
+ dcr.iwidth = (dcr.width + dcr.shrink) >> dcr.shrink;
+
+ // install custom camera matrix
+ if (dcr.opt.use_camera_matrix && dcr.cmatrix[0][0] > 0.25) {
+ memcpy (dcr.rgb_cam, dcr.cmatrix, sizeof dcr.cmatrix);
+ dcr.raw_color = 0;
+ } else {
+ dcr.opt.use_camera_wb = 1;
+ }
+
+ // allocate memory for the image
+ dcr.image = (ushort (*)[4]) calloc (dcr.iheight*dcr.iwidth, sizeof *dcr.image);
+ dcr_merror (&dcr, dcr.image, szClass);
+
+ if (dcr.meta_length) {
+ dcr.meta_data = (char *) malloc (dcr.meta_length);
+ dcr_merror (&dcr, dcr.meta_data, szClass);
+ }
+
+ // start image decoder
+ hFile->Seek(dcr.data_offset, SEEK_SET);
+ (*dcr.load_raw)(&dcr);
+
+ // post processing
+ if (dcr.zero_is_bad) dcr_remove_zeroes(&dcr);
+
+ dcr_bad_pixels(&dcr,dcr.opt.bpfile);
+
+ if (dcr.opt.dark_frame) dcr_subtract (&dcr,dcr.opt.dark_frame);
+
+ dcr.quality = 2 + !dcr.fuji_width;
+
+ if (dcr.opt.user_qual >= 0) dcr.quality = dcr.opt.user_qual;
+
+ if (dcr.opt.user_black >= 0) dcr.black = dcr.opt.user_black;
+
+ if (dcr.opt.user_sat >= 0) dcr.maximum = dcr.opt.user_sat;
+
+#ifdef COLORCHECK
+ dcr_colorcheck(&dcr);
+#endif
+
+#if RESTRICTED
+ if (dcr.is_foveon && !dcr.opt.document_mode) dcr_foveon_interpolate(&dcr);
+#endif
+
+ if (!dcr.is_foveon && dcr.opt.document_mode < 2) dcr_scale_colors(&dcr);
+
+ // pixel interpolation and filters
+ dcr_pre_interpolate(&dcr);
+
+ if (dcr.filters && !dcr.opt.document_mode) {
+ if (dcr.quality == 0)
+ dcr_lin_interpolate(&dcr);
+ else if (dcr.quality == 1 || dcr.colors > 3)
+ dcr_vng_interpolate(&dcr);
+ else if (dcr.quality == 2)
+ dcr_ppg_interpolate(&dcr);
+ else
+ dcr_ahd_interpolate(&dcr);
+ }
+
+ if (dcr.mix_green) {
+ int32_t i;
+ for (dcr.colors=3, i=0; i < dcr.height*dcr.width; i++) {
+ dcr.image[i][1] = (dcr.image[i][1] + dcr.image[i][3]) >> 1;
+ }
+ }
+
+ if (!dcr.is_foveon && dcr.colors == 3) dcr_median_filter(&dcr);
+
+ if (!dcr.is_foveon && dcr.opt.highlight == 2) dcr_blend_highlights(&dcr);
+
+ if (!dcr.is_foveon && dcr.opt.highlight > 2) dcr_recover_highlights(&dcr);
+
+ if (dcr.opt.use_fuji_rotate) dcr_fuji_rotate(&dcr);
+
+#ifndef NO_LCMS
+ if (dcr.opt.cam_profile) dcr_apply_profile (dcr.opt.cam_profile, dcr.opt.out_profile);
+#endif
+
+ // final conversion
+ dcr_convert_to_rgb(&dcr);
+
+ if (dcr.opt.use_fuji_rotate) dcr_stretch(&dcr);
+
+ dcr.iheight = dcr.height;
+ dcr.iwidth = dcr.width;
+ if (dcr.flip & 4) SWAP(dcr.height,dcr.width);
+
+ // ready to transfer data from dcr.image
+ if (!Create(dcr.width,dcr.height,24,CXIMAGE_FORMAT_RAW)){
+ cx_throw("");
+ }
+
+ uchar *ppm = (uchar *) calloc (dcr.width, dcr.colors*dcr.opt.output_bps/8);
+ ushort *ppm2 = (ushort *) ppm;
+ dcr_merror (&dcr, ppm, szClass);
+
+ uchar lut[0x10000];
+ if (dcr.opt.output_bps == 8) dcr_gamma_lut (&dcr, lut);
+
+ int32_t c, row, col, soff, rstep, cstep;
+ soff = dcr_flip_index (&dcr, 0, 0);
+ cstep = dcr_flip_index (&dcr, 0, 1) - soff;
+ rstep = dcr_flip_index (&dcr, 1, 0) - dcr_flip_index (&dcr, 0, dcr.width);
+ for (row=0; row < dcr.height; row++, soff += rstep) {
+ for (col=0; col < dcr.width; col++, soff += cstep) {
+ if (dcr.opt.output_bps == 8)
+ for (c=0; c < dcr.colors; c++) ppm [col*dcr.colors+c] = lut[dcr.image[soff][c]];
+ else
+ for (c=0; c < dcr.colors; c++) ppm2[col*dcr.colors+c] = dcr.image[soff][c];
+ }
+ if (dcr.opt.output_bps == 16 && !dcr.opt.output_tiff && htons(0x55aa) != 0x55aa)
+#if defined(_LINUX) || defined(__APPLE__)
+ swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2);
+#else
+ _swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2);
+#endif
+
+ uint32_t size = dcr.width * (dcr.colors*dcr.opt.output_bps/8);
+ RGBtoBGR(ppm,size);
+ memcpy(GetBits(dcr.height - 1 - row), ppm, min(size,GetEffWidth()));
+ }
+ free (ppm);
+
+
+ dcr_cleanup_dcraw(&dcr);
+
+ } cx_catch {
+
+ dcr_cleanup_dcraw(&dcr);
+
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_RAW) return true;
+ return false;
+ }
+ /* that's it */
+ return true;
+}
+
+#if CXIMAGE_SUPPORT_EXIF
+bool CxImageRAW::GetExifThumbnail(const TCHAR *filename, const TCHAR *outname, int32_t type)
+{
+ DCRAW dcr;
+
+ CxIOFile file;
+ if (!file.Open(filename, _T("rb")))
+ return false;
+
+ cx_try
+ {
+ // initialization
+ dcr_init_dcraw(&dcr);
+
+ dcr.opt.user_qual = GetCodecOption(CXIMAGE_FORMAT_RAW) & 0x03;
+
+ // setup variables for debugging
+ char szClass[] = "CxImageRAW";
+ dcr.ifname = szClass;
+ dcr.sz_error = info.szLastError;
+
+ // setup library options, see dcr_print_manual for the available switches
+ // call dcr_parse_command_line_options(&dcr,0,0,0) to set default options
+ // if (dcr_parse_command_line_options(&dcr,argc,argv,&arg))
+ if (dcr_parse_command_line_options(&dcr,0,0,0)){
+ cx_throw("CxImageRAW: unknown option");
+ }
+
+ // set return point for error handling
+ if (setjmp (dcr.failure)) {
+ cx_throw("");
+ }
+
+ // install file manager
+ CxFileRaw src(&file,&dcr);
+
+ // check file header
+ dcr_identify(&dcr);
+
+ if(!dcr.is_raw){
+ cx_throw("CxImageRAW: not a raw image");
+ }
+
+ if (dcr.load_raw == NULL) {
+ cx_throw("CxImageRAW: missing raw decoder");
+ }
+
+ // THUMB.
+ if (dcr.thumb_offset != 0)
+ {
+ FILE* file = _tfopen(outname, _T("wb"));
+ DCRAW* p = &dcr;
+ dcr_fseek(dcr.obj_, dcr.thumb_offset, SEEK_SET);
+ dcr.write_thumb(&dcr, file);
+ fclose(file);
+
+ // Read in the thumbnail to resize and rotate.
+ CxImage image(outname, CXIMAGE_FORMAT_UNKNOWN);
+ if (image.IsValid())
+ {
+ // Resizing.
+ if (image.GetWidth() > 256 || image.GetHeight() > 256)
+ {
+ float amount = 256.0f / max(image.GetWidth(), image.GetHeight());
+ image.Resample((int32_t)(image.GetWidth() * amount), (int32_t)(image.GetHeight() * amount), 0);
+ }
+
+ // Rotation.
+ if (p->flip != 0)
+ image.RotateExif(p->flip);
+
+ return image.Save(outname, CXIMAGE_FORMAT_JPG);
+ }
+ }
+ else
+ {
+ cx_throw("No thumbnail!");
+ }
+
+ dcr_cleanup_dcraw(&dcr);
+
+ } cx_catch {
+
+ dcr_cleanup_dcraw(&dcr);
+
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_RAW) return true;
+ return false;
+ }
+ /* that's it */
+ return true;
+}
+#endif //CXIMAGE_SUPPORT_EXIF
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageRAW::Encode(CxFile * hFile)
+{
+ if (hFile == NULL) return false;
+ strcpy(info.szLastError, "Save RAW not supported");
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_RAW
+
diff --git a/archive/hge/CxImage/ximaraw.h b/archive/hge/CxImage/ximaraw.h new file mode 100644 index 0000000..2fe4961 --- /dev/null +++ b/archive/hge/CxImage/ximaraw.h @@ -0,0 +1,112 @@ +/*
+ * File: ximaraw.h
+ * Purpose: RAW Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageRAW (c) May/2006 pdw63
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ * Special thanks to David Coffin for dcraw without which this class would not exist
+ *
+ * libdcr (c) Dec/2007 Davide Pizzolato - www.xdp.it
+ *
+ * based on dcraw.c -- Dave Coffin's raw photo decoder
+ * Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net
+ * ==========================================================
+ */
+#if !defined(__ximaRAW_h)
+#define __ximaRAW_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_RAW
+
+extern "C" {
+ #include "../raw/libdcr.h"
+}
+
+class CxImageRAW: public CxImage
+{
+
+public:
+ CxImageRAW(): CxImage(CXIMAGE_FORMAT_RAW) {}
+
+// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_ICO);}
+// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_ICO);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_EXIF
+ bool GetExifThumbnail(const TCHAR *filename, const TCHAR *outname, int32_t type);
+#endif //CXIMAGE_SUPPORT_EXIF
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+ enum CODEC_OPTION
+ {
+ DECODE_QUALITY_LIN = 0x00,
+ DECODE_QUALITY_VNG = 0x01,
+ DECODE_QUALITY_PPG = 0x02,
+ DECODE_QUALITY_AHD = 0x03,
+ };
+
+protected:
+
+ class CxFileRaw
+ {
+ public:
+ CxFileRaw(CxFile* pFile,DCRAW *stream)
+ {
+ stream->obj_ = pFile;
+
+ ras_stream_CxFile.read_ = raw_sfile_read;
+ ras_stream_CxFile.write_ = raw_sfile_write;
+ ras_stream_CxFile.seek_ = raw_sfile_seek;
+ ras_stream_CxFile.close_ = raw_sfile_close;
+ ras_stream_CxFile.gets_ = raw_sfile_gets;
+ ras_stream_CxFile.eof_ = raw_sfile_eof;
+ ras_stream_CxFile.tell_ = raw_sfile_tell;
+ ras_stream_CxFile.getc_ = raw_sfile_getc;
+ ras_stream_CxFile.scanf_ = raw_sfile_scanf;
+
+ stream->ops_ = &ras_stream_CxFile;
+
+ }
+
+ static int32_t raw_sfile_read(dcr_stream_obj *obj, void *buf, int32_t size, int32_t cnt)
+ { return ((CxFile*)obj)->Read(buf,size,cnt); }
+
+ static int32_t raw_sfile_write(dcr_stream_obj *obj, void *buf, int32_t size, int32_t cnt)
+ { return ((CxFile*)obj)->Write(buf,size,cnt); }
+
+ static long raw_sfile_seek(dcr_stream_obj *obj, long offset, int32_t origin)
+ { return ((CxFile*)obj)->Seek(offset,origin); }
+
+ static int32_t raw_sfile_close(dcr_stream_obj *obj)
+ { return 1; /*((CxFile*)obj)->Close();*/ }
+
+ static char* raw_sfile_gets(dcr_stream_obj *obj, char *string, int32_t n)
+ { return ((CxFile*)obj)->GetS(string,n); }
+
+ static int32_t raw_sfile_eof(dcr_stream_obj *obj)
+ { return ((CxFile*)obj)->Eof(); }
+
+ static long raw_sfile_tell(dcr_stream_obj *obj)
+ { return ((CxFile*)obj)->Tell(); }
+
+ static int32_t raw_sfile_getc(dcr_stream_obj *obj)
+ { return ((CxFile*)obj)->GetC(); }
+
+ static int32_t raw_sfile_scanf(dcr_stream_obj *obj,const char *format, void* output)
+ { return ((CxFile*)obj)->Scanf(format, output); }
+
+ private:
+ dcr_stream_ops ras_stream_CxFile;
+ };
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximasel.cpp b/archive/hge/CxImage/ximasel.cpp new file mode 100644 index 0000000..c50ff99 --- /dev/null +++ b/archive/hge/CxImage/ximasel.cpp @@ -0,0 +1,698 @@ +// xImaSel.cpp : Selection functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the image has a valid selection.
+ */
+bool CxImage::SelectionIsValid()
+{
+ return pSelection!=0;
+}
+
+#if CXIMAGE_SUPPORT_SELECTION
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the smallest rectangle that contains the selection
+ */
+void CxImage::SelectionGetBox(RECT& r)
+{
+ memcpy(&r,&info.rSelectionBox,sizeof(RECT));
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Empties the selection.
+ */
+bool CxImage::SelectionClear(uint8_t level)
+{
+ if (pSelection){
+ if (level==0){
+ memset(pSelection,0,head.biWidth * head.biHeight);
+ info.rSelectionBox.left = head.biWidth;
+ info.rSelectionBox.bottom = head.biHeight;
+ info.rSelectionBox.right = info.rSelectionBox.top = 0;
+ } else {
+ memset(pSelection,level,head.biWidth * head.biHeight);
+ info.rSelectionBox.right = head.biWidth;
+ info.rSelectionBox.top = head.biHeight;
+ info.rSelectionBox.left = info.rSelectionBox.bottom = 0;
+ }
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Allocates an empty selection.
+ */
+bool CxImage::SelectionCreate()
+{
+ SelectionDelete();
+ pSelection = (uint8_t*)calloc(head.biWidth * head.biHeight, 1);
+ return (pSelection!=0);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Deallocates the selction.
+ */
+bool CxImage::SelectionDelete()
+{
+ if (pSelection){
+ free(pSelection);
+ pSelection=NULL;
+ }
+ info.rSelectionBox.left = head.biWidth;
+ info.rSelectionBox.bottom = head.biHeight;
+ info.rSelectionBox.right = info.rSelectionBox.top = 0;
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the coordinates are inside the selection.
+ */
+bool CxImage::SelectionIsInside(int32_t x, int32_t y)
+{
+ if (IsInside(x,y)){
+ if (pSelection==NULL) return true;
+ return pSelection[x+y*head.biWidth]!=0;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the coordinates are inside the selection.
+ * "blind" version assumes that (x,y) is inside to the image.
+ */
+bool CxImage::BlindSelectionIsInside(int32_t x, int32_t y)
+{
+#ifdef _DEBUG
+ if (!IsInside(x,y))
+ #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+ throw 0;
+ #else
+ return 0;
+ #endif
+#endif
+ if (pSelection==NULL) return true;
+ return pSelection[x+y*head.biWidth]!=0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds a rectangle to the existing selection.
+ */
+bool CxImage::SelectionAddRect(RECT r, uint8_t level)
+{
+ if (pSelection==NULL) SelectionCreate();
+ if (pSelection==NULL) return false;
+
+ RECT r2;
+ if (r.left<r.right) {r2.left=r.left; r2.right=r.right; } else {r2.left=r.right ; r2.right=r.left; }
+ if (r.bottom<r.top) {r2.bottom=r.bottom; r2.top=r.top; } else {r2.bottom=r.top ; r2.top=r.bottom; }
+
+ if (info.rSelectionBox.top <= r2.top) info.rSelectionBox.top = max(0L,min(head.biHeight,r2.top+1));
+ if (info.rSelectionBox.left > r2.left) info.rSelectionBox.left = max(0L,min(head.biWidth,r2.left));
+ if (info.rSelectionBox.right <= r2.right) info.rSelectionBox.right = max(0L,min(head.biWidth,r2.right+1));
+ if (info.rSelectionBox.bottom > r2.bottom) info.rSelectionBox.bottom = max(0L,min(head.biHeight,r2.bottom));
+
+ int32_t ymin = max(0L,min(head.biHeight,r2.bottom));
+ int32_t ymax = max(0L,min(head.biHeight,r2.top+1));
+ int32_t xmin = max(0L,min(head.biWidth,r2.left));
+ int32_t xmax = max(0L,min(head.biWidth,r2.right+1));
+
+ for (int32_t y=ymin; y<ymax; y++)
+ memset(pSelection + xmin + y * head.biWidth, level, xmax-xmin);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds an ellipse to the existing selection.
+ */
+bool CxImage::SelectionAddEllipse(RECT r, uint8_t level)
+{
+ if (pSelection==NULL) SelectionCreate();
+ if (pSelection==NULL) return false;
+
+ int32_t xradius = abs(r.right - r.left)/2;
+ int32_t yradius = abs(r.top - r.bottom)/2;
+ if (xradius==0 || yradius==0) return false;
+
+ int32_t xcenter = (r.right + r.left)/2;
+ int32_t ycenter = (r.top + r.bottom)/2;
+
+ if (info.rSelectionBox.left > (xcenter - xradius)) info.rSelectionBox.left = max(0L,min(head.biWidth,(xcenter - xradius)));
+ if (info.rSelectionBox.right <= (xcenter + xradius)) info.rSelectionBox.right = max(0L,min(head.biWidth,(xcenter + xradius + 1)));
+ if (info.rSelectionBox.bottom > (ycenter - yradius)) info.rSelectionBox.bottom = max(0L,min(head.biHeight,(ycenter - yradius)));
+ if (info.rSelectionBox.top <= (ycenter + yradius)) info.rSelectionBox.top = max(0L,min(head.biHeight,(ycenter + yradius + 1)));
+
+ int32_t xmin = max(0L,min(head.biWidth,xcenter - xradius));
+ int32_t xmax = max(0L,min(head.biWidth,xcenter + xradius + 1));
+ int32_t ymin = max(0L,min(head.biHeight,ycenter - yradius));
+ int32_t ymax = max(0L,min(head.biHeight,ycenter + yradius + 1));
+
+ int32_t y,yo;
+ for (y=ymin; y<min(ycenter,ymax); y++){
+ for (int32_t x=xmin; x<xmax; x++){
+ yo = (int32_t)(ycenter - yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2)));
+ if (yo<y) pSelection[x + y * head.biWidth] = level;
+ }
+ }
+ for (y=ycenter; y<ymax; y++){
+ for (int32_t x=xmin; x<xmax; x++){
+ yo = (int32_t)(ycenter + yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2)));
+ if (yo>y) pSelection[x + y * head.biWidth] = level;
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Inverts the selection.
+ * Note: the SelectionBox is set to "full image", call SelectionGetBox before (if necessary)
+ */
+bool CxImage::SelectionInvert()
+{
+ if (pSelection) {
+ uint8_t *iSrc=pSelection;
+ int32_t n=head.biHeight*head.biWidth;
+ for(int32_t i=0; i < n; i++){
+ *iSrc=(uint8_t)~(*(iSrc));
+ iSrc++;
+ }
+
+ SelectionRebuildBox();
+
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Imports an existing region from another image with the same width and height.
+ */
+bool CxImage::SelectionCopy(CxImage &from)
+{
+ if (from.pSelection == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;
+ if (pSelection==NULL) pSelection = (uint8_t*)malloc(head.biWidth * head.biHeight);
+ if (pSelection==NULL) return false;
+ memcpy(pSelection,from.pSelection,head.biWidth * head.biHeight);
+ memcpy(&info.rSelectionBox,&from.info.rSelectionBox,sizeof(RECT));
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds a polygonal region to the existing selection. points points to an array of POINT structures.
+ * Each structure specifies the x-coordinate and y-coordinate of one vertex of the polygon.
+ * npoints specifies the number of POINT structures in the array pointed to by points.
+ */
+bool CxImage::SelectionAddPolygon(POINT *points, int32_t npoints, uint8_t level)
+{
+ if (points==NULL || npoints<3) return false;
+
+ if (pSelection==NULL) SelectionCreate();
+ if (pSelection==NULL) return false;
+
+ uint8_t* plocal = (uint8_t*)calloc(head.biWidth*head.biHeight, 1);
+ RECT localbox = {head.biWidth,0,0,head.biHeight};
+
+ int32_t x,y,i=0;
+ POINT *current;
+ POINT *next = NULL;
+ POINT *start = NULL;
+ //trace contour
+ while (i < npoints){
+ current = &points[i];
+ if (current->x!=-1){
+ if (i==0 || (i>0 && points[i-1].x==-1)) start = &points[i];
+
+ if ((i+1)==npoints || points[i+1].x==-1)
+ next = start;
+ else
+ next = &points[i+1];
+
+ float beta;
+ if (current->x != next->x){
+ beta = (float)(next->y - current->y)/(float)(next->x - current->x);
+ if (current->x < next->x){
+ for (x=current->x; x<=next->x; x++){
+ y = (int32_t)(current->y + (x - current->x) * beta);
+ if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;
+ }
+ } else {
+ for (x=current->x; x>=next->x; x--){
+ y = (int32_t)(current->y + (x - current->x) * beta);
+ if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;
+ }
+ }
+ }
+ if (current->y != next->y){
+ beta = (float)(next->x - current->x)/(float)(next->y - current->y);
+ if (current->y < next->y){
+ for (y=current->y; y<=next->y; y++){
+ x = (int32_t)(current->x + (y - current->y) * beta);
+ if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;
+ }
+ } else {
+ for (y=current->y; y>=next->y; y--){
+ x = (int32_t)(current->x + (y - current->y) * beta);
+ if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;
+ }
+ }
+ }
+ }
+
+ RECT r2;
+ if (current->x < next->x) {r2.left=current->x; r2.right=next->x; } else {r2.left=next->x ; r2.right=current->x; }
+ if (current->y < next->y) {r2.bottom=current->y; r2.top=next->y; } else {r2.bottom=next->y ; r2.top=current->y; }
+ if (localbox.top < r2.top) localbox.top = max(0L,min(head.biHeight-1,r2.top+1));
+ if (localbox.left > r2.left) localbox.left = max(0L,min(head.biWidth-1,r2.left-1));
+ if (localbox.right < r2.right) localbox.right = max(0L,min(head.biWidth-1,r2.right+1));
+ if (localbox.bottom > r2.bottom) localbox.bottom = max(0L,min(head.biHeight-1,r2.bottom-1));
+
+ i++;
+ }
+
+ //fill the outer region
+ int32_t npix=(localbox.right - localbox.left)*(localbox.top - localbox.bottom);
+ POINT* pix = (POINT*)calloc(npix,sizeof(POINT));
+ uint8_t back=0, mark=1;
+ int32_t fx, fy, fxx, fyy, first, last;
+ int32_t xmin = 0;
+ int32_t xmax = 0;
+ int32_t ymin = 0;
+ int32_t ymax = 0;
+
+ for (int32_t side=0; side<4; side++){
+ switch(side){
+ case 0:
+ xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.bottom+1;
+ break;
+ case 1:
+ xmin=localbox.right; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.top+1;
+ break;
+ case 2:
+ xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.top; ymax=localbox.top+1;
+ break;
+ case 3:
+ xmin=localbox.left; xmax=localbox.left+1; ymin=localbox.bottom; ymax=localbox.top+1;
+ break;
+ }
+ //fill from the border points
+ for(y=ymin;y<ymax;y++){
+ for(x=xmin;x<xmax;x++){
+ if (plocal[x+y*head.biWidth]==0){
+ // Subject: FLOOD FILL ROUTINE Date: 12-23-97 (00:57)
+ // Author: Petter Holmberg Code: QB, QBasic, PDS
+ // Origin: petter.holmberg@usa.net Packet: GRAPHICS.ABC
+ first=0;
+ last=1;
+ while(first!=last){
+ fx = pix[first].x;
+ fy = pix[first].y;
+ fxx = fx + x;
+ fyy = fy + y;
+ for(;;)
+ {
+ if ((plocal[fxx + fyy*head.biWidth] == back) &&
+ fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top )
+ {
+ plocal[fxx + fyy*head.biWidth] = mark;
+ if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){
+ pix[last].x = fx;
+ pix[last].y = fy - 1;
+ last++;
+ if (last == npix) last = 0;
+ }
+ if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){
+ pix[last].x = fx;
+ pix[last].y = fy + 1;
+ last++;
+ if (last == npix) last = 0;
+ }
+ } else {
+ break;
+ }
+ fx++;
+ fxx++;
+ };
+
+ fx = pix[first].x - 1;
+ fy = pix[first].y;
+ fxx = fx + x;
+ fyy = fy + y;
+
+ for( ;; )
+ {
+ if ((plocal[fxx + fyy*head.biWidth] == back) &&
+ fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top )
+ {
+ plocal[fxx + (y + fy)*head.biWidth] = mark;
+ if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){
+ pix[last].x = fx;
+ pix[last].y = fy - 1;
+ last++;
+ if (last == npix) last = 0;
+ }
+ if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){
+ pix[last].x = fx;
+ pix[last].y = fy + 1;
+ last++;
+ if (last == npix) last = 0;
+ }
+ } else {
+ break;
+ }
+ fx--;
+ fxx--;
+ }
+
+ first++;
+ if (first == npix) first = 0;
+ }
+ }
+ }
+ }
+ }
+
+ //transfer the region
+ int32_t yoffset;
+ for (y=localbox.bottom; y<=localbox.top; y++){
+ yoffset = y * head.biWidth;
+ for (x=localbox.left; x<=localbox.right; x++)
+ if (plocal[x + yoffset]!=1) pSelection[x + yoffset]=level;
+ }
+ if (info.rSelectionBox.top <= localbox.top) info.rSelectionBox.top = min(head.biHeight,localbox.top + 1);
+ if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = min(head.biWidth,localbox.left);
+ if (info.rSelectionBox.right <= localbox.right) info.rSelectionBox.right = min(head.biWidth,localbox.right + 1);
+ if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = min(head.biHeight,localbox.bottom);
+
+ free(plocal);
+ free(pix);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds to the selection all the pixels matching the specified color.
+ */
+bool CxImage::SelectionAddColor(RGBQUAD c, uint8_t level)
+{
+ if (pSelection==NULL) SelectionCreate();
+ if (pSelection==NULL) return false;
+
+ RECT localbox = {head.biWidth,0,0,head.biHeight};
+
+ for (int32_t y = 0; y < head.biHeight; y++){
+ for (int32_t x = 0; x < head.biWidth; x++){
+ RGBQUAD color = BlindGetPixelColor(x, y);
+ if (color.rgbRed == c.rgbRed &&
+ color.rgbGreen == c.rgbGreen &&
+ color.rgbBlue == c.rgbBlue)
+ {
+ pSelection[x + y * head.biWidth] = level;
+
+ if (localbox.top < y) localbox.top = y;
+ if (localbox.left > x) localbox.left = x;
+ if (localbox.right < x) localbox.right = x;
+ if (localbox.bottom > y) localbox.bottom = y;
+ }
+ }
+ }
+
+ if (info.rSelectionBox.top <= localbox.top) info.rSelectionBox.top = localbox.top + 1;
+ if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = localbox.left;
+ if (info.rSelectionBox.right <= localbox.right) info.rSelectionBox.right = localbox.right + 1;
+ if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = localbox.bottom;
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds a single pixel to the existing selection.
+ */
+bool CxImage::SelectionAddPixel(int32_t x, int32_t y, uint8_t level)
+{
+ if (pSelection==NULL) SelectionCreate();
+ if (pSelection==NULL) return false;
+
+ if (IsInside(x,y)) {
+ pSelection[x + y * head.biWidth] = level; // set the correct mask bit
+
+ if (info.rSelectionBox.top <= y) info.rSelectionBox.top = y+1;
+ if (info.rSelectionBox.left > x) info.rSelectionBox.left = x;
+ if (info.rSelectionBox.right <= x) info.rSelectionBox.right = x+1;
+ if (info.rSelectionBox.bottom > y) info.rSelectionBox.bottom = y;
+
+ return true;
+ }
+
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Exports the selection channel in a 8bpp grayscale image.
+ */
+bool CxImage::SelectionSplit(CxImage *dest)
+{
+ if (!pSelection || !dest) return false;
+
+ CxImage tmp(head.biWidth,head.biHeight,8);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ for(int32_t y=0; y<head.biHeight; y++){
+ for(int32_t x=0; x<head.biWidth; x++){
+ tmp.BlindSetPixelIndex(x,y,pSelection[x+y*head.biWidth]);
+ }
+ }
+
+ tmp.SetGrayPalette();
+ dest->Transfer(tmp);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Creates the selection channel from a gray scale image.
+ * black = unselected
+ */
+bool CxImage::SelectionSet(CxImage &from)
+{
+ if (!from.IsGrayScale() || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight){
+ strcpy(info.szLastError,"CxImage::SelectionSet: wrong width or height, or image is not gray scale");
+ return false;
+ }
+
+ if (pSelection==NULL) pSelection = (uint8_t*)malloc(head.biWidth * head.biHeight);
+
+ uint8_t* src = from.info.pImage;
+ uint8_t* dst = pSelection;
+ if (src==NULL || dst==NULL){
+ strcpy(info.szLastError,"CxImage::SelectionSet: null pointer");
+ return false;
+ }
+
+ for (int32_t y=0; y<head.biHeight; y++){
+ memcpy(dst,src,head.biWidth);
+ dst += head.biWidth;
+ src += from.info.dwEffWidth;
+ }
+
+ SelectionRebuildBox();
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the Selection level for a single pixel
+ * internal use only: doesn't set SelectionBox. Use SelectionAddPixel
+ */
+void CxImage::SelectionSet(const int32_t x,const int32_t y,const uint8_t level)
+{
+ if (pSelection && IsInside(x,y)) pSelection[x+y*head.biWidth]=level;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the Selection level for a single pixel
+ */
+uint8_t CxImage::SelectionGet(const int32_t x,const int32_t y)
+{
+ if (pSelection && IsInside(x,y)) return pSelection[x+y*head.biWidth];
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Rebuilds the SelectionBox
+ */
+void CxImage::SelectionRebuildBox()
+{
+ info.rSelectionBox.left = head.biWidth;
+ info.rSelectionBox.bottom = head.biHeight;
+ info.rSelectionBox.right = info.rSelectionBox.top = 0;
+
+ if (!pSelection)
+ return;
+
+ int32_t x,y;
+
+ for (y=0; y<head.biHeight; y++){
+ for (x=0; x<info.rSelectionBox.left; x++){
+ if (pSelection[x+y*head.biWidth]){
+ info.rSelectionBox.left = x;
+ continue;
+ }
+ }
+ }
+
+ for (y=0; y<head.biHeight; y++){
+ for (x=head.biWidth-1; x>=info.rSelectionBox.right; x--){
+ if (pSelection[x+y*head.biWidth]){
+ info.rSelectionBox.right = x+1;
+ continue;
+ }
+ }
+ }
+
+ for (x=0; x<head.biWidth; x++){
+ for (y=0; y<info.rSelectionBox.bottom; y++){
+ if (pSelection[x+y*head.biWidth]){
+ info.rSelectionBox.bottom = y;
+ continue;
+ }
+ }
+ }
+
+ for (x=0; x<head.biWidth; x++){
+ for (y=head.biHeight-1; y>=info.rSelectionBox.top; y--){
+ if (pSelection[x+y*head.biWidth]){
+ info.rSelectionBox.top = y+1;
+ continue;
+ }
+ }
+ }
+
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the Selection level for a single pixel
+ * "blind" version assumes that (x,y) is inside to the image.
+ */
+uint8_t CxImage::BlindSelectionGet(const int32_t x,const int32_t y)
+{
+#ifdef _DEBUG
+ if (!IsInside(x,y) || (pSelection==0))
+ #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING
+ throw 0;
+ #else
+ return 0;
+ #endif
+#endif
+ return pSelection[x+y*head.biWidth];
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns pointer to selection data for pixel (x,y).
+ */
+uint8_t* CxImage::SelectionGetPointer(const int32_t x,const int32_t y)
+{
+ if (pSelection && IsInside(x,y)) return pSelection+x+y*head.biWidth;
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::SelectionFlip()
+{
+ if (!pSelection) return false;
+
+ uint8_t *buff = (uint8_t*)malloc(head.biWidth);
+ if (!buff) return false;
+
+ uint8_t *iSrc,*iDst;
+ iSrc = pSelection + (head.biHeight-1)*head.biWidth;
+ iDst = pSelection;
+ for (int32_t i=0; i<(head.biHeight/2); ++i)
+ {
+ memcpy(buff, iSrc, head.biWidth);
+ memcpy(iSrc, iDst, head.biWidth);
+ memcpy(iDst, buff, head.biWidth);
+ iSrc-=head.biWidth;
+ iDst+=head.biWidth;
+ }
+
+ free(buff);
+
+ int32_t top = info.rSelectionBox.top;
+ info.rSelectionBox.top = head.biHeight - info.rSelectionBox.bottom;
+ info.rSelectionBox.bottom = head.biHeight - top;
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::SelectionMirror()
+{
+ if (!pSelection) return false;
+ uint8_t* pSelection2 = (uint8_t*)malloc(head.biWidth * head.biHeight);
+ if (!pSelection2) return false;
+
+ uint8_t *iSrc,*iDst;
+ int32_t wdt=head.biWidth-1;
+ iSrc=pSelection + wdt;
+ iDst=pSelection2;
+ for(int32_t y=0; y < head.biHeight; y++){
+ for(int32_t x=0; x <= wdt; x++)
+ *(iDst+x)=*(iSrc-x);
+ iSrc+=head.biWidth;
+ iDst+=head.biWidth;
+ }
+ free(pSelection);
+ pSelection=pSelection2;
+
+ int32_t left = info.rSelectionBox.left;
+ info.rSelectionBox.left = head.biWidth - info.rSelectionBox.right;
+ info.rSelectionBox.right = head.biWidth - left;
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_WINDOWS
+/**
+ * Converts the selection in a HRGN object.
+ */
+bool CxImage::SelectionToHRGN(HRGN& region)
+{
+ if (pSelection && region){
+ for(int32_t y = 0; y < head.biHeight; y++){
+ HRGN hTemp = NULL;
+ int32_t iStart = -1;
+ int32_t x = 0;
+ for(; x < head.biWidth; x++){
+ if (pSelection[x + y * head.biWidth] != 0){
+ if (iStart == -1) iStart = x;
+ continue;
+ }else{
+ if (iStart >= 0){
+ hTemp = CreateRectRgn(iStart, y, x, y + 1);
+ CombineRgn(region, hTemp, region, RGN_OR);
+ DeleteObject(hTemp);
+ iStart = -1;
+ }
+ }
+ }
+ if (iStart >= 0){
+ hTemp = CreateRectRgn(iStart, y, x, y + 1);
+ CombineRgn(region, hTemp, region, RGN_OR);
+ DeleteObject(hTemp);
+ iStart = -1;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+#endif //CXIMAGE_SUPPORT_WINDOWS
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_SELECTION
diff --git a/archive/hge/CxImage/ximaska.cpp b/archive/hge/CxImage/ximaska.cpp new file mode 100644 index 0000000..6f1b1c2 --- /dev/null +++ b/archive/hge/CxImage/ximaska.cpp @@ -0,0 +1,126 @@ +/*
+ * File: ximaska.cpp
+ * Purpose: Platform Independent SKA Image Class Loader and Writer
+ * 25/Sep/2007 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximaska.h"
+
+#if CXIMAGE_SUPPORT_SKA
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageSKA::Decode(CxFile *hFile)
+{
+ if (hFile==NULL)
+ return false;
+
+ // read the header
+ SKAHEADER ska_header;
+ hFile->Read(&ska_header,sizeof(SKAHEADER),1);
+
+ ska_header.Width = m_ntohs(ska_header.Width);
+ ska_header.Height = m_ntohs(ska_header.Height);
+ ska_header.dwUnknown = m_ntohl(ska_header.dwUnknown);
+
+ // check header
+ if (ska_header.dwUnknown != 0x01000000 ||
+ ska_header.Width > 0x7FFF || ska_header.Height > 0x7FFF ||
+ ska_header.BppExp != 3)
+ return false;
+
+ if (info.nEscape == -1){
+ head.biWidth = ska_header.Width ;
+ head.biHeight= ska_header.Height;
+ info.dwType = CXIMAGE_FORMAT_SKA;
+ return true;
+ }
+
+ int32_t bpp = 1<<ska_header.BppExp;
+
+ Create(ska_header.Width,ska_header.Height,bpp,CXIMAGE_FORMAT_SKA);
+ if (!IsValid())
+ return false;
+
+ // read the palette
+ int32_t nColors = 1<<bpp;
+ rgb_color* ppal = (rgb_color*)malloc(nColors*sizeof(rgb_color));
+ if (!ppal) return false;
+ hFile->Read(ppal,nColors*sizeof(rgb_color),1);
+ SetPalette(ppal,nColors);
+ free(ppal);
+
+ //read the image
+ hFile->Read(GetBits(),ska_header.Width*ska_header.Height,1);
+
+ //reorder rows
+ if (GetEffWidth() != ska_header.Width){
+ uint8_t *src,*dst;
+ src = GetBits() + ska_header.Width*(ska_header.Height-1);
+ dst = GetBits(ska_header.Height-1);
+ for(int32_t y=0;y<ska_header.Height;y++){
+ memcpy(dst,src,ska_header.Width);
+ src -= ska_header.Width;
+ dst -= GetEffWidth();
+ }
+ }
+
+ Flip();
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageSKA::Encode(CxFile * hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ if(head.biBitCount > 8) {
+ strcpy(info.szLastError,"SKA Images must be 8 bit or less");
+ return false;
+ }
+
+ SKAHEADER ska_header;
+
+ ska_header.Width = (uint16_t)GetWidth();
+ ska_header.Height = (uint16_t)GetHeight();
+ ska_header.BppExp = 3;
+ ska_header.dwUnknown = 0x01000000;
+
+ ska_header.Width = m_ntohs(ska_header.Width);
+ ska_header.Height = m_ntohs(ska_header.Height);
+ ska_header.dwUnknown = m_ntohl(ska_header.dwUnknown);
+
+ hFile->Write(&ska_header,sizeof(SKAHEADER),1);
+
+ ska_header.Width = m_ntohs(ska_header.Width);
+ ska_header.Height = m_ntohs(ska_header.Height);
+ ska_header.dwUnknown = m_ntohl(ska_header.dwUnknown);
+
+ if (head.biBitCount<8) IncreaseBpp(8);
+
+ rgb_color pal[256];
+ for(int32_t idx=0; idx<256; idx++){
+ GetPaletteColor(idx,&(pal[idx].r),&(pal[idx].g),&(pal[idx].b));
+ }
+
+ hFile->Write(pal,256*sizeof(rgb_color),1);
+
+ uint8_t* src = GetBits(ska_header.Height-1);
+ for(int32_t y=0;y<ska_header.Height;y++){
+ hFile->Write(src,ska_header.Width,1);
+ src -= GetEffWidth();
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_SKA
+
diff --git a/archive/hge/CxImage/ximaska.h b/archive/hge/CxImage/ximaska.h new file mode 100644 index 0000000..ad3f598 --- /dev/null +++ b/archive/hge/CxImage/ximaska.h @@ -0,0 +1,44 @@ +/*
+ * File: ximaska.h
+ * Purpose: SKA Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageSKA (c) 25/Sep/2007 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ * ==========================================================
+ */
+#if !defined(__ximaSKA_h)
+#define __ximaSKA_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_SKA
+
+class CxImageSKA: public CxImage
+{
+#pragma pack(1)
+ typedef struct tagSkaHeader {
+ uint16_t Width;
+ uint16_t Height;
+ uint8_t BppExp;
+ uint32_t dwUnknown;
+} SKAHEADER;
+#pragma pack()
+
+public:
+ CxImageSKA(): CxImage(CXIMAGE_FORMAT_SKA) {}
+
+// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_ICO);}
+// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_ICO);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximatga.cpp b/archive/hge/CxImage/ximatga.cpp new file mode 100644 index 0000000..f1a762a --- /dev/null +++ b/archive/hge/CxImage/ximatga.cpp @@ -0,0 +1,320 @@ +/*
+ * File: ximatga.cpp
+ * Purpose: Platform Independent TGA Image Class Loader and Writer
+ * 05/Jan/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximatga.h"
+
+#if CXIMAGE_SUPPORT_TGA
+
+#include "ximaiter.h"
+
+// Definitions for image types.
+#define TGA_Null 0
+#define TGA_Map 1
+#define TGA_RGB 2
+#define TGA_Mono 3
+#define TGA_RLEMap 9
+#define TGA_RLERGB 10
+#define TGA_RLEMono 11
+#define TGA_CompMap 32
+#define TGA_CompMap4 33
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageTGA::Decode(CxFile *hFile)
+{
+ if (hFile == NULL) return false;
+
+ TGAHEADER tgaHead;
+
+ cx_try
+ {
+ if (hFile->Read(&tgaHead,sizeof(tgaHead),1)==0)
+ cx_throw("Not a TGA");
+
+ tga_toh(&tgaHead);
+
+ bool bCompressed;
+ switch (tgaHead.ImageType){
+ case TGA_Map:
+ case TGA_RGB:
+ case TGA_Mono:
+ bCompressed = false;
+ break;
+ case TGA_RLEMap:
+ case TGA_RLERGB:
+ case TGA_RLEMono:
+ bCompressed = true;
+ break;
+ default:
+ cx_throw("Unknown TGA image type");
+ }
+
+ if (tgaHead.ImageWidth==0 || tgaHead.ImageHeight==0 || tgaHead.PixelDepth==0 || tgaHead.CmapLength>256)
+ cx_throw("bad TGA header");
+
+ if (tgaHead.PixelDepth!=8 && tgaHead.PixelDepth!=15 && tgaHead.PixelDepth!=16 && tgaHead.PixelDepth!=24 && tgaHead.PixelDepth!=32)
+ cx_throw("bad TGA header");
+
+ if (info.nEscape == -1){
+ head.biWidth = tgaHead.ImageWidth ;
+ head.biHeight= tgaHead.ImageHeight;
+ info.dwType = CXIMAGE_FORMAT_TGA;
+ return true;
+ }
+
+ if (tgaHead.IdLength>0) hFile->Seek(tgaHead.IdLength,SEEK_CUR); //skip descriptor
+
+ Create(tgaHead.ImageWidth, tgaHead.ImageHeight, tgaHead.PixelDepth, CXIMAGE_FORMAT_TGA);
+#if CXIMAGE_SUPPORT_ALPHA // <vho>
+ if (tgaHead.PixelDepth==32) AlphaCreate(); // Image has alpha channel
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ if (!IsValid()) cx_throw("TGA Create failed");
+
+ if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+ if (tgaHead.CmapType != 0){ // read the palette
+ rgb_color pal[256];
+ hFile->Read(pal,tgaHead.CmapLength*sizeof(rgb_color), 1);
+ for (int32_t i=0;i<tgaHead.CmapLength; i++) SetPaletteColor((uint8_t)i,pal[i].b,pal[i].g,pal[i].r);
+ }
+
+ if (tgaHead.ImageType == TGA_Mono || tgaHead.ImageType == TGA_RLEMono)
+ SetGrayPalette();
+
+ // Bits 4 & 5 of the Image Descriptor byte control the ordering of the pixels.
+ bool bXReversed = ((tgaHead.ImagDesc & 16) == 16);
+ bool bYReversed = ((tgaHead.ImagDesc & 32) == 32);
+
+ CImageIterator iter(this);
+ uint8_t rleLeftover = 255; //for images with illegal packet boundary
+ uint8_t* pDest;
+ for (int32_t y=0; y < tgaHead.ImageHeight; y++){
+
+ if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+ if (hFile == NULL || hFile->Eof()) cx_throw("corrupted TGA");
+
+ if (bYReversed) pDest = iter.GetRow(tgaHead.ImageHeight-y-1);
+ else pDest = iter.GetRow(y);
+
+ if (bCompressed) rleLeftover = ExpandCompressedLine(pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,rleLeftover);
+ else ExpandUncompressedLine (pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,0);
+ }
+
+ if (bXReversed) Mirror();
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (bYReversed && tgaHead.PixelDepth==32) AlphaFlip(); //<lioucr>
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageTGA::Encode(CxFile * hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ if (head.biBitCount<8){
+ strcpy(info.szLastError,"Bit depth must be 8 or 24");
+ return false;
+ }
+
+ TGAHEADER tgaHead;
+
+ tgaHead.IdLength = 0; // Image ID Field Length
+ tgaHead.CmapType = GetPalette()!=0; // Color Map Type
+ tgaHead.ImageType = (head.biBitCount == 8) ? (uint8_t)TGA_Map : (uint8_t)TGA_RGB; // Image Type
+
+ tgaHead.CmapIndex=0; // First Entry Index
+ tgaHead.CmapLength=(head.biBitCount == 8) ? 256 : 0; // Color Map Length
+ tgaHead.CmapEntrySize=(head.biBitCount == 8) ? (uint8_t)24 : (uint8_t)0; // Color Map Entry Size
+
+ tgaHead.X_Origin=0; // X-origin of Image
+ tgaHead.Y_Origin=0; // Y-origin of Image
+ tgaHead.ImageWidth=(uint16_t)head.biWidth; // Image Width
+ tgaHead.ImageHeight=(uint16_t)head.biHeight; // Image Height
+ tgaHead.PixelDepth=(uint8_t)head.biBitCount; // Pixel Depth
+ tgaHead.ImagDesc=0; // Image Descriptor
+
+ if (pAlpha && head.biBitCount==24) tgaHead.PixelDepth=32;
+
+ tga_toh(&tgaHead);
+ hFile->Write(&tgaHead,sizeof(TGAHEADER),1);
+ tga_toh(&tgaHead);
+
+ if (head.biBitCount==8){
+ rgb_color pal[256];
+ RGBQUAD* ppal = GetPalette();
+ for (int32_t i=0;i<256; i++){
+ pal[i].r = ppal[i].rgbBlue;
+ pal[i].g = ppal[i].rgbGreen;
+ pal[i].b = ppal[i].rgbRed;
+ }
+ hFile->Write(&pal,256*sizeof(rgb_color),1);
+ }
+
+ CImageIterator iter(this);
+ uint8_t* pDest;
+ if (pAlpha==0 || head.biBitCount==8){
+ for (int32_t y=0; y < tgaHead.ImageHeight; y++){
+ pDest = iter.GetRow(y);
+ hFile->Write(pDest,tgaHead.ImageWidth * (head.biBitCount >> 3),1);
+ }
+ } else {
+ pDest = (uint8_t*)malloc(4*tgaHead.ImageWidth);
+ RGBQUAD c;
+ for (int32_t y=0; y < tgaHead.ImageHeight; y++){
+ for(int32_t x=0, x4=0;x<tgaHead.ImageWidth;x++, x4+=4){
+ c = BlindGetPixelColor(x,y);
+ pDest[x4+0]=c.rgbBlue;
+ pDest[x4+1]=c.rgbGreen;
+ pDest[x4+2]=c.rgbRed;
+#if CXIMAGE_SUPPORT_ALPHA // <vho>
+ pDest[x4+3]=AlphaGet(x,y);
+#else
+ pDest[x4+3]=0;
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ hFile->Write(pDest,4*tgaHead.ImageWidth,1);
+ }
+ free(pDest);
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+uint8_t CxImageTGA::ExpandCompressedLine(uint8_t* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int32_t width, int32_t y, uint8_t rleLeftover)
+{
+ uint8_t rle;
+ int32_t filePos=0;
+ for (int32_t x=0; x<width; ){
+ if (rleLeftover != 255){
+ rle = rleLeftover;
+ rleLeftover = 255;
+ } else {
+ hFile->Read(&rle,1,1);
+ }
+ if (rle & 128) { // RLE-Encoded packet
+ rle -= 127; // Calculate real repeat count.
+ if ((x+rle)>width){
+ rleLeftover = (uint8_t)(128 + (rle - (width - x) - 1));
+ filePos = hFile->Tell();
+ rle = (uint8_t)(width - x);
+ }
+ switch (ptgaHead->PixelDepth)
+ {
+ case 32: {
+ RGBQUAD color;
+ hFile->Read(&color,4,1);
+ for (int32_t ix = 0; ix < rle; ix++){
+ memcpy(&pDest[3*ix],&color,3);
+#if CXIMAGE_SUPPORT_ALPHA // <vho>
+ AlphaSet(ix+x,y,color.rgbReserved);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ break;
+ }
+ case 24: {
+ rgb_color triple;
+ hFile->Read(&triple,3,1);
+ for (int32_t ix = 0; ix < rle; ix++) memcpy(&pDest[3*ix],&triple,3);
+ break;
+ }
+ case 15:
+ case 16: {
+ uint16_t pixel;
+ hFile->Read(&pixel,2,1);
+ rgb_color triple;
+ triple.r = (uint8_t)(( pixel & 0x1F ) * 8); // red
+ triple.g = (uint8_t)(( pixel >> 2 ) & 0x0F8); // green
+ triple.b = (uint8_t)(( pixel >> 7 ) & 0x0F8); // blue
+ for (int32_t ix = 0; ix < rle; ix++){
+ memcpy(&pDest[3*ix],&triple,3);
+ }
+ break;
+ }
+ case 8: {
+ uint8_t pixel;
+ hFile->Read(&pixel,1,1);
+ for (int32_t ix = 0; ix < rle; ix++) pDest[ix] = pixel;
+ }
+ }
+ if (rleLeftover!=255) hFile->Seek(filePos, SEEK_SET);
+ } else { // Raw packet
+ rle += 1; // Calculate real repeat count.
+ if ((x+rle)>width){
+ rleLeftover = (uint8_t)(rle - (width - x) - 1);
+ rle = (uint8_t)(width - x);
+ }
+ ExpandUncompressedLine(pDest,ptgaHead,hFile,rle,y,x);
+ }
+ if (head.biBitCount == 24) pDest += rle*3; else pDest += rle;
+ x += rle;
+ }
+ return rleLeftover;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageTGA::ExpandUncompressedLine(uint8_t* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int32_t width, int32_t y, int32_t xoffset)
+{
+ switch (ptgaHead->PixelDepth){
+ case 8:
+ hFile->Read(pDest,width,1);
+ break;
+ case 15:
+ case 16:{
+ uint8_t* dst=pDest;
+ uint16_t pixel;
+ for (int32_t x=0; x<width; x++){
+ hFile->Read(&pixel,2,1);
+ *dst++ = (uint8_t)(( pixel & 0x1F ) * 8); // blue
+ *dst++ = (uint8_t)(( pixel >> 2 ) & 0x0F8); // green
+ *dst++ = (uint8_t)(( pixel >> 7 ) & 0x0F8); // red
+ }
+ break;
+ }
+ case 24:
+ hFile->Read(pDest,3*width,1);
+ break;
+ case 32:{
+ uint8_t* dst=pDest;
+ for (int32_t x=0; x<width; x++){
+ RGBQUAD pixel;
+ hFile->Read(&pixel,4,1);
+ *dst++ = pixel.rgbBlue;
+ *dst++ = pixel.rgbGreen;
+ *dst++ = pixel.rgbRed;
+#if CXIMAGE_SUPPORT_ALPHA // <vho>
+ AlphaSet(x+xoffset,y,pixel.rgbReserved); //alpha
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ break;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageTGA::tga_toh(TGAHEADER* p)
+{
+ p->CmapIndex = m_ntohs(p->CmapIndex);
+ p->CmapLength = m_ntohs(p->CmapLength);
+ p->X_Origin = m_ntohs(p->X_Origin);
+ p->Y_Origin = m_ntohs(p->Y_Origin);
+ p->ImageWidth = m_ntohs(p->ImageWidth);
+ p->ImageHeight = m_ntohs(p->ImageHeight);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_TGA
diff --git a/archive/hge/CxImage/ximatga.h b/archive/hge/CxImage/ximatga.h new file mode 100644 index 0000000..3cbc36a --- /dev/null +++ b/archive/hge/CxImage/ximatga.h @@ -0,0 +1,61 @@ +/*
+ * File: ximatga.h
+ * Purpose: TARGA Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageTGA (c) 05/Jan/2002 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Parts of the code come from Paintlib : Copyright (c) 1996-1998 Ulrich von Zadow
+ * ==========================================================
+ */
+#if !defined(__ximaTGA_h)
+#define __ximaTGA_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_TGA
+
+class CxImageTGA: public CxImage
+{
+#pragma pack(1)
+typedef struct tagTgaHeader
+{
+ uint8_t IdLength; // Image ID Field Length
+ uint8_t CmapType; // Color Map Type
+ uint8_t ImageType; // Image Type
+
+ uint16_t CmapIndex; // First Entry Index
+ uint16_t CmapLength; // Color Map Length
+ uint8_t CmapEntrySize; // Color Map Entry Size
+
+ uint16_t X_Origin; // X-origin of Image
+ uint16_t Y_Origin; // Y-origin of Image
+ uint16_t ImageWidth; // Image Width
+ uint16_t ImageHeight; // Image Height
+ uint8_t PixelDepth; // Pixel Depth
+ uint8_t ImagDesc; // Image Descriptor
+} TGAHEADER;
+#pragma pack()
+
+public:
+ CxImageTGA(): CxImage(CXIMAGE_FORMAT_TGA) {}
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_TGA);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_TGA);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+protected:
+ uint8_t ExpandCompressedLine(uint8_t* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int32_t width, int32_t y, uint8_t rleLeftover);
+ void ExpandUncompressedLine(uint8_t* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int32_t width, int32_t y, int32_t xoffset);
+ void tga_toh(TGAHEADER* p);
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximath.cpp b/archive/hge/CxImage/ximath.cpp new file mode 100644 index 0000000..0175184 --- /dev/null +++ b/archive/hge/CxImage/ximath.cpp @@ -0,0 +1,97 @@ +#include "ximage.h"
+#include "ximath.h"
+#include <math.h>
+
+//this module should contain some classes for geometrical transformations
+//usable with selections, etc... once it's done, that is. :)
+
+CxPoint2::CxPoint2()
+{
+ x=y=0.0f;
+}
+
+CxPoint2::CxPoint2(float const x_, float const y_)
+{
+ x=x_;
+ y=y_;
+}
+
+CxPoint2::CxPoint2(CxPoint2 const &p)
+{
+ x=p.x;
+ y=p.y;
+}
+
+float CxPoint2::Distance(CxPoint2 const p2)
+{
+ return (float)sqrt((x-p2.x)*(x-p2.x)+(y-p2.y)*(y-p2.y));
+}
+
+float CxPoint2::Distance(float const x_, float const y_)
+{
+ return (float)sqrt((x-x_)*(x-x_)+(y-y_)*(y-y_));
+}
+
+CxRect2::CxRect2()
+{
+}
+
+CxRect2::CxRect2(float const x1_, float const y1_, float const x2_, float const y2_)
+{
+ botLeft.x=x1_;
+ botLeft.y=y1_;
+ topRight.x=x2_;
+ topRight.y=y2_;
+}
+
+CxRect2::CxRect2(CxRect2 const &p)
+{
+ botLeft=p.botLeft;
+ topRight=p.topRight;
+}
+
+float CxRect2::Surface() const
+/*
+ * Returns the surface of rectangle.
+ */
+{
+ return (topRight.x-botLeft.x)*(topRight.y-botLeft.y);
+}
+
+CxRect2 CxRect2::CrossSection(CxRect2 const &r2) const
+/*
+ * Returns crossection with another rectangle.
+ */
+{
+ CxRect2 cs;
+ cs.botLeft.x=max(botLeft.x, r2.botLeft.x);
+ cs.botLeft.y=max(botLeft.y, r2.botLeft.y);
+ cs.topRight.x=min(topRight.x, r2.topRight.x);
+ cs.topRight.y=min(topRight.y, r2.topRight.y);
+ if (cs.botLeft.x<=cs.topRight.x && cs.botLeft.y<=cs.topRight.y) {
+ return cs;
+ } else {
+ return CxRect2(0,0,0,0);
+ }//if
+}
+
+CxPoint2 CxRect2::Center() const
+/*
+ * Returns the center point of rectangle.
+ */
+{
+ return CxPoint2((topRight.x+botLeft.x)/2.0f, (topRight.y+botLeft.y)/2.0f);
+}
+
+float CxRect2::Width() const
+//returns rectangle width
+{
+ return topRight.x-botLeft.x;
+}
+
+float CxRect2::Height() const
+//returns rectangle height
+{
+ return topRight.y-botLeft.y;
+}
+
diff --git a/archive/hge/CxImage/ximath.h b/archive/hge/CxImage/ximath.h new file mode 100644 index 0000000..014c14b --- /dev/null +++ b/archive/hge/CxImage/ximath.h @@ -0,0 +1,39 @@ +#if !defined(__ximath_h)
+#define __ximath_h
+
+#include "ximadef.h"
+
+//***bd*** simple floating point point
+class DLL_EXP CxPoint2
+{
+public:
+ CxPoint2();
+ CxPoint2(float const x_, float const y_);
+ CxPoint2(CxPoint2 const &p);
+
+ float Distance(CxPoint2 const p2);
+ float Distance(float const x_, float const y_);
+
+ float x,y;
+};
+
+//and simple rectangle
+class DLL_EXP CxRect2
+{
+public:
+ CxRect2();
+ CxRect2(float const x1_, float const y1_, float const x2_, float const y2_);
+ CxRect2(CxPoint2 const &bl, CxPoint2 const &tr);
+ CxRect2(CxRect2 const &p);
+
+ float Surface() const;
+ CxRect2 CrossSection(CxRect2 const &r2) const;
+ CxPoint2 Center() const;
+ float Width() const;
+ float Height() const;
+
+ CxPoint2 botLeft;
+ CxPoint2 topRight;
+};
+
+#endif
diff --git a/archive/hge/CxImage/ximatif.cpp b/archive/hge/CxImage/ximatif.cpp new file mode 100644 index 0000000..7675361 --- /dev/null +++ b/archive/hge/CxImage/ximatif.cpp @@ -0,0 +1,982 @@ +/*
+ * File: ximatif.cpp
+ * Purpose: Platform Independent TIFF Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximatif.h"
+
+#if CXIMAGE_SUPPORT_TIF
+
+#define FIX_16BPP_DARKIMG // + VK: if uncomment, dark 16bpp images are fixed
+
+#include "../tiff/tiffio.h"
+
+#define CVT(x) (((x) * 255L) / ((1L<<16)-1))
+#define SCALE(x) (((x)*((1L<<16)-1))/255)
+#define CalculateLine(width,bitdepth) (((width * bitdepth) + 7) / 8)
+#define CalculatePitch(line) (line + 3 & ~3)
+
+extern "C" TIFF* _TIFFOpenEx(CxFile* stream, const char* mode);
+
+////////////////////////////////////////////////////////////////////////////////
+CxImageTIF::~CxImageTIF()
+{
+ if (m_tif2) TIFFClose(m_tif2);
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageTIF::Decode(CxFile * hFile)
+{
+ //Comment this line if you need more information on errors
+ // TIFFSetErrorHandler(NULL); //<Patrick Hoffmann>
+
+ //Open file and fill the TIFF structure
+ // m_tif = TIFFOpen(imageFileName,"rb");
+ TIFF* m_tif = _TIFFOpenEx(hFile, "rb");
+
+ uint32 height=0;
+ uint32 width=0;
+ uint16 bitspersample=1;
+ uint16 samplesperpixel=1;
+ uint32 rowsperstrip=(uint32_t)-1;
+ uint16 photometric=0;
+ uint16 compression=1;
+ uint16 orientation=ORIENTATION_TOPLEFT; //<vho>
+ uint16 res_unit; //<Trifon>
+ uint32 x, y;
+ float resolution, offset;
+ BOOL isRGB;
+ uint8_t *bits; //pointer to source data
+ uint8_t *bits2; //pointer to destination data
+
+ cx_try
+ {
+ //check if it's a tiff file
+ if (!m_tif)
+ cx_throw("Error encountered while opening TIFF file");
+
+ // <Robert Abram> - 12/2002 : get NumFrames directly, instead of looping
+ // info.nNumFrames=0;
+ // while(TIFFSetDirectory(m_tif,(uint16)info.nNumFrames)) info.nNumFrames++;
+ info.nNumFrames = TIFFNumberOfDirectories(m_tif);
+
+ if (!TIFFSetDirectory(m_tif, (uint16)info.nFrame))
+ cx_throw("Error: page not present in TIFF file");
+
+ //get image info
+ TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width);
+ TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height);
+ TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
+ TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
+ TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+ TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric);
+ TIFFGetField(m_tif, TIFFTAG_ORIENTATION, &orientation);
+
+ if (info.nEscape == -1) {
+ // Return output dimensions only
+ head.biWidth = width;
+ head.biHeight = height;
+ info.dwType = CXIMAGE_FORMAT_TIF;
+ cx_throw("output dimensions returned");
+ }
+
+ TIFFGetFieldDefaulted(m_tif, TIFFTAG_RESOLUTIONUNIT, &res_unit);
+ if (TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &resolution))
+ {
+ if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);
+ SetXDPI((int32_t)resolution);
+ }
+ if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution))
+ {
+ if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);
+ SetYDPI((int32_t)resolution);
+ }
+
+ if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset)) info.xOffset = (int32_t)offset;
+ if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset)) info.yOffset = (int32_t)offset;
+
+ head.biClrUsed=0;
+ info.nBkgndIndex =-1;
+
+ if (rowsperstrip>height){
+ rowsperstrip=height;
+ TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
+ }
+
+ isRGB = /*(bitspersample >= 8) && (VK: it is possible so for RGB to have < 8 bpp!)*/
+ (photometric == PHOTOMETRIC_RGB) ||
+ (photometric == PHOTOMETRIC_YCBCR) ||
+ (photometric == PHOTOMETRIC_SEPARATED) ||
+ (photometric == PHOTOMETRIC_LOGL) ||
+ (photometric == PHOTOMETRIC_LOGLUV);
+
+ if (isRGB){
+ head.biBitCount=24;
+ }else{
+ if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)||(photometric==PHOTOMETRIC_PALETTE)){
+ if (bitspersample == 1){
+ head.biBitCount=1; //B&W image
+ head.biClrUsed =2;
+ } else if (bitspersample == 4) {
+ head.biBitCount=4; //16 colors gray scale
+ head.biClrUsed =16;
+ } else {
+ head.biBitCount=8; //gray scale
+ head.biClrUsed =256;
+ }
+ } else if (bitspersample == 4) {
+ head.biBitCount=4; // 16 colors
+ head.biClrUsed=16;
+ } else {
+ head.biBitCount=8; //256 colors
+ head.biClrUsed=256;
+ }
+
+ if ((bitspersample > 8) && (photometric==PHOTOMETRIC_PALETTE)) // + VK + (BIG palette! => convert to RGB)
+ { head.biBitCount=24;
+ head.biClrUsed =0;
+ }
+ }
+
+ if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+ Create(width,height,head.biBitCount,CXIMAGE_FORMAT_TIF); //image creation
+ if (!pDib) cx_throw("CxImageTIF can't create image");
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (samplesperpixel==4) AlphaCreate(); //add alpha support for 32bpp tiffs
+ if (samplesperpixel==2 && bitspersample==8) AlphaCreate(); //add alpha support for 8bpp + alpha
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression);
+ SetCodecOption(compression); // <DPR> save original compression type
+
+ if (isRGB) {
+ // Read the whole image into one big RGBA buffer using
+ // the traditional TIFFReadRGBAImage() API that we trust.
+ uint32* raster; // retrieve RGBA image
+ uint32 *row;
+
+ raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32));
+ if (raster == NULL) cx_throw("No space for raster buffer");
+
+ // Read the image in one chunk into an RGBA array
+ if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) {
+ _TIFFfree(raster);
+ cx_throw("Corrupted TIFF file!");
+ }
+
+ // read the raster lines and save them in the DIB
+ // with RGB mode, we have to change the order of the 3 samples RGB
+ row = &raster[0];
+ bits2 = info.pImage;
+ for (y = 0; y < height; y++) {
+
+ if (info.nEscape){ // <vho> - cancel decoding
+ _TIFFfree(raster);
+ cx_throw("Cancelled");
+ }
+
+ bits = bits2;
+ for (x = 0; x < width; x++) {
+ *bits++ = (uint8_t)TIFFGetB(row[x]);
+ *bits++ = (uint8_t)TIFFGetG(row[x]);
+ *bits++ = (uint8_t)TIFFGetR(row[x]);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (samplesperpixel==4) AlphaSet(x,y,(uint8_t)TIFFGetA(row[x]));
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ row += width;
+ bits2 += info.dwEffWidth;
+ }
+ _TIFFfree(raster);
+ } else {
+ int32_t BIG_palette = (bitspersample > 8) && // + VK
+ (photometric==PHOTOMETRIC_PALETTE);
+ if (BIG_palette && (bitspersample > 24)) // + VK
+ cx_throw("Too big palette to handle"); // + VK
+
+ RGBQUAD *pal;
+ pal=(RGBQUAD*)calloc(BIG_palette ? 1<<bitspersample : 256,sizeof(RGBQUAD));
+ // ! VK: it coasts nothing but more correct to use 256 as temp palette storage
+ // ! VK: but for case of BIG palette it just copied
+ if (pal==NULL) cx_throw("Unable to allocate TIFF palette");
+
+ int32_t bpp = bitspersample <= 8 ? bitspersample : 8; // + VK (to use instead of bitspersample for case of > 8)
+
+ // set up the colormap based on photometric
+ switch(photometric) {
+ case PHOTOMETRIC_MINISBLACK: // bitmap and greyscale image types
+ case PHOTOMETRIC_MINISWHITE:
+ if (bitspersample == 1) { // Monochrome image
+ if (photometric == PHOTOMETRIC_MINISBLACK) {
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+ } else {
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
+ }
+ } else { // need to build the scale for greyscale images
+ if (photometric == PHOTOMETRIC_MINISBLACK) {
+ for (int32_t i=0; i<(1<<bpp); i++){
+ pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (uint8_t)(i*(255/((1<<bpp)-1)));
+ }
+ } else {
+ for (int32_t i=0; i<(1<<bpp); i++){
+ pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (uint8_t)(255-i*(255/((1<<bpp)-1)));
+ }
+ }
+ }
+ break;
+ case PHOTOMETRIC_PALETTE: // color map indexed
+ uint16 *red;
+ uint16 *green;
+ uint16 *blue;
+ TIFFGetField(m_tif, TIFFTAG_COLORMAP, &red, &green, &blue);
+
+ // Is the palette 16 or 8 bits ?
+ BOOL Palette16Bits = /*FALSE*/ BIG_palette;
+ if (!BIG_palette) {
+ int32_t n= 1<<bpp;
+ while (n-- > 0) {
+ if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) {
+ Palette16Bits=TRUE;
+ break;
+ }
+ }
+ }
+
+ // load the palette in the DIB
+ for (int32_t i = (1 << ( BIG_palette ? bitspersample : bpp )) - 1; i >= 0; i--) {
+ if (Palette16Bits) {
+ pal[i].rgbRed =(uint8_t) CVT(red[i]);
+ pal[i].rgbGreen = (uint8_t) CVT(green[i]);
+ pal[i].rgbBlue = (uint8_t) CVT(blue[i]);
+ } else {
+ pal[i].rgbRed = (uint8_t) red[i];
+ pal[i].rgbGreen = (uint8_t) green[i];
+ pal[i].rgbBlue = (uint8_t) blue[i];
+ }
+ }
+ break;
+ }
+ if (!BIG_palette) { // + VK (BIG palette is stored until image is ready)
+ SetPalette(pal,/*head.biClrUsed*/ 1<<bpp); //palette assign // * VK
+ free(pal);
+ pal = NULL;
+ }
+
+ // read the tiff lines and save them in the DIB
+ uint32 nrow;
+ uint32 ys;
+ int32_t line = CalculateLine(width, bitspersample * samplesperpixel);
+
+ int32_t bitsize = TIFFStripSize(m_tif);
+ //verify bitsize: could be wrong if StripByteCounts is missing.
+ if (bitsize>(int32_t)(head.biSizeImage*samplesperpixel))
+ bitsize = head.biSizeImage*samplesperpixel;
+ if (bitsize<(int32_t)(info.dwEffWidth*rowsperstrip))
+ bitsize = info.dwEffWidth*rowsperstrip;
+
+ if ((bitspersample > 8) && (bitspersample != 16)) // + VK (for bitspersample == 9..15,17..32..64
+ bitsize *= (bitspersample + 7)/8;
+
+ int32_t tiled_image = TIFFIsTiled(m_tif);
+ uint32 tw=0, tl=0;
+ uint8_t* tilebuf=NULL;
+ if (tiled_image){
+ TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw);
+ TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl);
+ rowsperstrip = tl;
+ bitsize = TIFFTileSize(m_tif) * (int32_t)(1+width/tw);
+ tilebuf = (uint8_t*)malloc(TIFFTileSize(m_tif));
+ }
+
+ bits = (uint8_t*)malloc(bitspersample==16? bitsize*2 : bitsize); // * VK
+ uint8_t * bits16 = NULL; // + VK
+ int32_t line16 = 0; // + VK
+
+ if (!tiled_image && bitspersample==16) { // + VK +
+ line16 = line;
+ line = CalculateLine(width, 8 * samplesperpixel);
+ bits16 = bits;
+ bits = (uint8_t*)malloc(bitsize);
+ }
+
+ if (bits==NULL){
+ if (bits16) free(bits16); // + VK
+ if (pal) free(pal); // + VK
+ if (tilebuf)free(tilebuf); // + VK
+ cx_throw("CxImageTIF can't allocate memory");
+ }
+
+#ifdef FIX_16BPP_DARKIMG // + VK: for each line, store shift count bits used to fix it
+ uint8_t* row_shifts = NULL;
+ if (bits16) row_shifts = (uint8_t*)malloc(height);
+#endif
+
+ for (ys = 0; ys < height; ys += rowsperstrip) {
+
+ if (info.nEscape){ // <vho> - cancel decoding
+ free(bits);
+ cx_throw("Cancelled");
+ }
+
+ nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip);
+
+ if (tiled_image){
+ uint32 imagew = TIFFScanlineSize(m_tif);
+ uint32 tilew = TIFFTileRowSize(m_tif);
+ int32_t iskew = imagew - tilew;
+ uint8* bufp = (uint8*) bits;
+
+ uint32 colb = 0;
+ for (uint32 col = 0; col < width; col += tw) {
+ if (TIFFReadTile(m_tif, tilebuf, col, ys, 0, 0) < 0){
+ free(tilebuf);
+ free(bits);
+ cx_throw("Corrupted tiled TIFF file!");
+ }
+
+ if (colb + tw > imagew) {
+ uint32 owidth = imagew - colb;
+ uint32 oskew = tilew - owidth;
+ TileToStrip(bufp + colb, tilebuf, nrow, owidth, oskew + iskew, oskew );
+ } else {
+ TileToStrip(bufp + colb, tilebuf, nrow, tilew, iskew, 0);
+ }
+ colb += tilew;
+ }
+
+ } else {
+ if (TIFFReadEncodedStrip(m_tif, TIFFComputeStrip(m_tif, ys, 0),
+ (bits16? bits16 : bits), nrow * (bits16 ? line16 : line)) == -1) { // * VK
+
+#ifdef NOT_IGNORE_CORRUPTED
+ free(bits);
+ if (bits16) free(bits16); // + VK
+ cx_throw("Corrupted TIFF file!");
+#else
+ break;
+#endif
+ }
+ }
+
+ for (y = 0; y < nrow; y++) {
+ int32_t offset=(nrow-y-1)*line;
+ if ((bitspersample==16) && !BIG_palette) { // * VK
+ int32_t offset16 = (nrow-y-1)*line16; // + VK
+ if (bits16) { // + VK +
+#ifdef FIX_16BPP_DARKIMG
+ int32_t the_shift;
+ uint8_t hi_byte, hi_max=0;
+ uint32_t xi;
+ for (xi=0;xi<(uint32)line;xi++) {
+ hi_byte = bits16[xi*2+offset16+1];
+ if(hi_byte>hi_max)
+ hi_max = hi_byte;
+ }
+ the_shift = (hi_max == 0) ? 8 : 0;
+ if (!the_shift)
+ while( ! (hi_max & 0x80) ) {
+ the_shift++;
+ hi_max <<= 1;
+ }
+ row_shifts[height-ys-nrow+y] = the_shift;
+ the_shift = 8 - the_shift;
+ for (xi=0;xi<(uint32)line;xi++)
+ bits[xi+offset]= ((bits16[xi*2+offset16+1]<<8) | bits16[xi*2+offset16]) >> the_shift;
+#else
+ for (uint32_t xi=0;xi<(uint32)line;xi++)
+ bits[xi+offset]=bits16[xi*2+offset16+1];
+#endif
+ } else {
+ for (uint32_t xi=0;xi<width;xi++)
+ bits[xi+offset]=bits[xi*2+offset+1];
+ }
+ }
+ if (samplesperpixel==1) {
+ if (BIG_palette)
+ if (bits16) {
+ int32_t offset16 = (nrow-y-1)*line16; // + VK
+ MoveBitsPal( info.pImage + info.dwEffWidth * (height-ys-nrow+y),
+ bits16 + offset16, width, bitspersample, pal );
+ } else
+ MoveBitsPal( info.pImage + info.dwEffWidth * (height-ys-nrow+y),
+ bits + offset, width, bitspersample, pal );
+ else if ((bitspersample == head.biBitCount) ||
+ (bitspersample == 16)) //simple 8bpp, 4bpp image or 16bpp
+ memcpy(info.pImage+info.dwEffWidth*(height-ys-nrow+y),bits+offset,min((unsigned)line, info.dwEffWidth));
+ else
+ MoveBits( info.pImage + info.dwEffWidth * (height-ys-nrow+y),
+ bits + offset, width, bitspersample );
+ } else if (samplesperpixel==2) { //8bpp image with alpha layer
+ int32_t xi=0;
+ int32_t ii=0;
+ int32_t yi=height-ys-nrow+y;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (!pAlpha) AlphaCreate(); // + VK
+#endif //CXIMAGE_SUPPORT_ALPHA
+ while (ii<line){
+ SetPixelIndex(xi,yi,bits[ii+offset]);
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaSet(xi,yi,bits[ii+offset+1]);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ ii+=2;
+ xi++;
+ if (xi>=(int32_t)width){
+ yi--;
+ xi=0;
+ }
+ }
+ } else { //photometric==PHOTOMETRIC_CIELAB
+ if (head.biBitCount!=24){ //fix image
+ Create(width,height,24,CXIMAGE_FORMAT_TIF);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (samplesperpixel==4) AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+
+ int32_t xi=0;
+ uint32 ii=0;
+ int32_t yi=height-ys-nrow+y;
+ RGBQUAD c;
+ int32_t l,a,b,bitsoffset;
+ double p,cx,cy,cz,cr,cg,cb;
+ while (ii</*line*/width){ // * VK
+ bitsoffset = ii*samplesperpixel+offset;
+ l=bits[bitsoffset];
+ a=bits[bitsoffset+1];
+ b=bits[bitsoffset+2];
+ if (a>127) a-=256;
+ if (b>127) b-=256;
+ // lab to xyz
+ p = (l/2.55 + 16) / 116.0;
+ cx = pow( p + a * 0.002, 3);
+ cy = pow( p, 3);
+ cz = pow( p - b * 0.005, 3);
+ // white point
+ cx*=0.95047;
+ //cy*=1.000;
+ cz*=1.0883;
+ // xyz to rgb
+ cr = 3.240479 * cx - 1.537150 * cy - 0.498535 * cz;
+ cg = -0.969256 * cx + 1.875992 * cy + 0.041556 * cz;
+ cb = 0.055648 * cx - 0.204043 * cy + 1.057311 * cz;
+
+ if ( cr > 0.00304 ) cr = 1.055 * pow(cr,0.41667) - 0.055;
+ else cr = 12.92 * cr;
+ if ( cg > 0.00304 ) cg = 1.055 * pow(cg,0.41667) - 0.055;
+ else cg = 12.92 * cg;
+ if ( cb > 0.00304 ) cb = 1.055 * pow(cb,0.41667) - 0.055;
+ else cb = 12.92 * cb;
+
+ c.rgbRed =(uint8_t)max(0,min(255,(int32_t)(cr*255)));
+ c.rgbGreen=(uint8_t)max(0,min(255,(int32_t)(cg*255)));
+ c.rgbBlue =(uint8_t)max(0,min(255,(int32_t)(cb*255)));
+
+ SetPixelColor(xi,yi,c);
+#if CXIMAGE_SUPPORT_ALPHA
+ if (samplesperpixel==4) AlphaSet(xi,yi,bits[bitsoffset+3]);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ ii++;
+ xi++;
+ if (xi>=(int32_t)width){
+ yi--;
+ xi=0;
+ }
+ }
+ }
+ }
+ }
+ free(bits);
+ if (bits16) free(bits16);
+
+#ifdef FIX_16BPP_DARKIMG
+ if (row_shifts && (samplesperpixel == 1) && (bitspersample==16) && !BIG_palette) {
+ // 1. calculate maximum necessary shift
+ int32_t min_row_shift = 8;
+ for( y=0; y<height; y++ ) {
+ if (min_row_shift > row_shifts[y]) min_row_shift = row_shifts[y];
+ }
+ // 2. for rows having less shift value, correct such rows:
+ for( y=0; y<height; y++ ) {
+ if (min_row_shift < row_shifts[y]) {
+ int32_t need_shift = row_shifts[y] - min_row_shift;
+ uint8_t* data = info.pImage + info.dwEffWidth * y;
+ for( x=0; x<width; x++, data++ )
+ *data >>= need_shift;
+ }
+ }
+ }
+ if (row_shifts) free( row_shifts );
+#endif
+
+ if (tiled_image) free(tilebuf);
+ if (pal) free(pal);
+
+ switch(orientation){
+ case ORIENTATION_TOPRIGHT: /* row 0 top, col 0 rhs */
+ Mirror();
+ break;
+ case ORIENTATION_BOTRIGHT: /* row 0 bottom, col 0 rhs */
+ Flip();
+ Mirror();
+ break;
+ case ORIENTATION_BOTLEFT: /* row 0 bottom, col 0 lhs */
+ Flip();
+ break;
+ case ORIENTATION_LEFTTOP: /* row 0 lhs, col 0 top */
+ RotateRight();
+ Mirror();
+ break;
+ case ORIENTATION_RIGHTTOP: /* row 0 rhs, col 0 top */
+ RotateLeft();
+ break;
+ case ORIENTATION_RIGHTBOT: /* row 0 rhs, col 0 bottom */
+ RotateLeft();
+ Mirror();
+ break;
+ case ORIENTATION_LEFTBOT: /* row 0 lhs, col 0 bottom */
+ RotateRight();
+ break;
+ }
+
+ }
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (m_tif) TIFFClose(m_tif);
+ if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_TIF) return true;
+ return false;
+ }
+ TIFFClose(m_tif);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageTIF::Encode(CxFile * hFile, bool bAppend)
+{
+ cx_try
+ {
+ if (hFile==NULL) cx_throw(CXIMAGE_ERR_NOFILE);
+ if (pDib==NULL) cx_throw(CXIMAGE_ERR_NOIMAGE);
+
+ // <RJ> replaced "w+b" with "a", to append an image directly on an existing file
+ if (m_tif2==NULL) m_tif2=_TIFFOpenEx(hFile, "a");
+ if (m_tif2==NULL) cx_throw("initialization fail");
+
+ if (bAppend || m_pages) m_multipage=true;
+ m_pages++;
+
+ if (!EncodeBody(m_tif2,m_multipage,m_pages,m_pages)) cx_throw("Error saving TIFF file");
+ if (bAppend) {
+ if (!TIFFWriteDirectory(m_tif2)) cx_throw("Error saving TIFF directory");
+ }
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ if (m_tif2){
+ TIFFClose(m_tif2);
+ m_tif2=NULL;
+ m_multipage=false;
+ m_pages=0;
+ }
+ return false;
+ }
+ if (!bAppend){
+ TIFFClose(m_tif2);
+ m_tif2=NULL;
+ m_multipage=false;
+ m_pages=0;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+// Thanks to Abe <God(dot)bless(at)marihuana(dot)com>
+bool CxImageTIF::Encode(CxFile * hFile, CxImage ** pImages, int32_t pagecount)
+{
+ cx_try
+ {
+ if (hFile==NULL) cx_throw("invalid file pointer");
+ if (pImages==NULL || pagecount<=0) cx_throw("multipage TIFF, no images!");
+
+ int32_t i;
+ for (i=0; i<pagecount; i++){
+ if (pImages[i]==NULL)
+ cx_throw("Bad image pointer");
+ if (!(pImages[i]->IsValid()))
+ cx_throw("Empty image");
+ }
+
+ CxImageTIF ghost;
+ for (i=0; i<pagecount; i++){
+ ghost.Ghost(pImages[i]);
+ if (!ghost.Encode(hFile,true)) cx_throw("Error saving TIFF file");
+ }
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ return false;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageTIF::EncodeBody(TIFF *m_tif, bool multipage, int32_t page, int32_t pagecount)
+{
+ uint32 height=head.biHeight;
+ uint32 width=head.biWidth;
+ uint16 bitcount=head.biBitCount;
+ uint16 bitspersample;
+ uint16 samplesperpixel;
+ uint16 photometric=0;
+ uint16 compression;
+// uint16 pitch;
+// int32_t line;
+ uint32 x, y;
+
+ samplesperpixel = ((bitcount == 24) || (bitcount == 32)) ? (uint8_t)3 : (uint8_t)1;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (bitcount==24 && AlphaIsValid()) { bitcount=32; samplesperpixel=4; }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ bitspersample = bitcount / samplesperpixel;
+
+ //set the PHOTOMETRIC tag
+ RGBQUAD *rgb = GetPalette();
+ switch (bitcount) {
+ case 1:
+ if (CompareColors(&rgb[0],&rgb[1])<0) {
+ /* <abe> some viewers do not handle PHOTOMETRIC_MINISBLACK:
+ * let's transform the image in PHOTOMETRIC_MINISWHITE
+ */
+ //invert the colors
+ RGBQUAD tempRGB=GetPaletteColor(0);
+ SetPaletteColor(0,GetPaletteColor(1));
+ SetPaletteColor(1,tempRGB);
+ //invert the pixels
+ uint8_t *iSrc=info.pImage;
+ for (uint32_t i=0;i<head.biSizeImage;i++){
+ *iSrc=(uint8_t)~(*(iSrc));
+ iSrc++;
+ }
+ photometric = PHOTOMETRIC_MINISWHITE;
+ //photometric = PHOTOMETRIC_MINISBLACK;
+ } else {
+ photometric = PHOTOMETRIC_MINISWHITE;
+ }
+ break;
+ case 4: // Check if the DIB has a color or a greyscale palette
+ case 8:
+ photometric = PHOTOMETRIC_MINISBLACK; //default to gray scale
+ for (x = 0; x < head.biClrUsed; x++) {
+ if ((rgb->rgbRed != x)||(rgb->rgbRed != rgb->rgbGreen)||(rgb->rgbRed != rgb->rgbBlue)){
+ photometric = PHOTOMETRIC_PALETTE;
+ break;
+ }
+ rgb++;
+ }
+ break;
+ case 24:
+ case 32:
+ photometric = PHOTOMETRIC_RGB;
+ break;
+ }
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid() && bitcount==8) samplesperpixel=2; //8bpp + alpha layer
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+// line = CalculateLine(width, bitspersample * samplesperpixel);
+// pitch = (uint16)CalculatePitch(line);
+
+ //prepare the palette struct
+ RGBQUAD pal[256];
+ if (GetPalette()){
+ uint8_t b;
+ memcpy(pal,GetPalette(),GetPaletteSize());
+ for(uint16_t a=0;a<head.biClrUsed;a++){ //swap blue and red components
+ b=pal[a].rgbBlue; pal[a].rgbBlue=pal[a].rgbRed; pal[a].rgbRed=b;
+ }
+ }
+
+ // handle standard width/height/bpp stuff
+ TIFFSetField(m_tif, TIFFTAG_IMAGEWIDTH, width);
+ TIFFSetField(m_tif, TIFFTAG_IMAGELENGTH, height);
+ TIFFSetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
+ TIFFSetField(m_tif, TIFFTAG_BITSPERSAMPLE, bitspersample);
+ TIFFSetField(m_tif, TIFFTAG_PHOTOMETRIC, photometric);
+ TIFFSetField(m_tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // single image plane
+ TIFFSetField(m_tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
+
+ uint32 rowsperstrip = TIFFDefaultStripSize(m_tif, (uint32) -1); //<REC> gives better compression
+ TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
+
+ // handle metrics
+ TIFFSetField(m_tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
+ TIFFSetField(m_tif, TIFFTAG_XRESOLUTION, (float)info.xDPI);
+ TIFFSetField(m_tif, TIFFTAG_YRESOLUTION, (float)info.yDPI);
+// TIFFSetField(m_tif, TIFFTAG_XPOSITION, (float)info.xOffset);
+// TIFFSetField(m_tif, TIFFTAG_YPOSITION, (float)info.yOffset);
+
+ // multi-paging - Thanks to Abe <God(dot)bless(at)marihuana(dot)com>
+ if (multipage)
+ {
+ char page_number[20];
+ sprintf(page_number, "Page %d", page);
+
+ TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
+ TIFFSetField(m_tif, TIFFTAG_PAGENUMBER, page,pagecount);
+ TIFFSetField(m_tif, TIFFTAG_PAGENAME, page_number);
+ } else {
+ TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, 0);
+ }
+
+ // palettes (image colormaps are automatically scaled to 16-bits)
+ if (photometric == PHOTOMETRIC_PALETTE) {
+ uint16 *r, *g, *b;
+ r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * 256);
+ g = r + 256;
+ b = g + 256;
+
+ for (int32_t i = 255; i >= 0; i--) {
+ b[i] = (uint16)SCALE((uint16)pal[i].rgbRed);
+ g[i] = (uint16)SCALE((uint16)pal[i].rgbGreen);
+ r[i] = (uint16)SCALE((uint16)pal[i].rgbBlue);
+ }
+
+ TIFFSetField(m_tif, TIFFTAG_COLORMAP, r, g, b);
+ _TIFFfree(r);
+ }
+
+ // compression
+ if (GetCodecOption(CXIMAGE_FORMAT_TIF)) {
+ compression = (uint16_t)GetCodecOption(CXIMAGE_FORMAT_TIF);
+ } else {
+ switch (bitcount) {
+ case 1 :
+ compression = COMPRESSION_CCITTFAX4;
+ break;
+ case 4 :
+ case 8 :
+ compression = COMPRESSION_LZW;
+ break;
+ case 24 :
+ case 32 :
+ compression = COMPRESSION_JPEG;
+ break;
+ default :
+ compression = COMPRESSION_NONE;
+ break;
+ }
+ }
+ TIFFSetField(m_tif, TIFFTAG_COMPRESSION, compression);
+
+ switch (compression) {
+ case COMPRESSION_JPEG:
+ TIFFSetField(m_tif, TIFFTAG_JPEGQUALITY, GetJpegQuality());
+ TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, ((7+rowsperstrip)>>3)<<3);
+ break;
+ case COMPRESSION_LZW:
+ if (bitcount>=8) TIFFSetField(m_tif, TIFFTAG_PREDICTOR, 2);
+ break;
+ }
+
+ // read the DIB lines from bottom to top and save them in the TIF
+
+ uint8_t *bits;
+ switch(bitcount) {
+ case 1 :
+ case 4 :
+ case 8 :
+ {
+ if (samplesperpixel==1){
+ bits = (uint8_t*)malloc(info.dwEffWidth);
+ if (!bits) return false;
+ for (y = 0; y < height; y++) {
+ memcpy(bits,info.pImage + (height - y - 1)*info.dwEffWidth,info.dwEffWidth);
+ if (TIFFWriteScanline(m_tif,bits, y, 0)==-1){
+ free(bits);
+ return false;
+ }
+ }
+ free(bits);
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ else { //8bpp + alpha layer
+ bits = (uint8_t*)malloc(2*width);
+ if (!bits) return false;
+ for (y = 0; y < height; y++) {
+ for (x=0;x<width;x++){
+ bits[2*x]=BlindGetPixelIndex(x,height - y - 1);
+ bits[2*x+1]=AlphaGet(x,height - y - 1);
+ }
+ if (TIFFWriteScanline(m_tif,bits, y, 0)==-1) {
+ free(bits);
+ return false;
+ }
+ }
+ free(bits);
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+ break;
+ }
+ case 24:
+ {
+ uint8_t *buffer = (uint8_t *)malloc(info.dwEffWidth);
+ if (!buffer) return false;
+ for (y = 0; y < height; y++) {
+ // get a pointer to the scanline
+ memcpy(buffer, info.pImage + (height - y - 1)*info.dwEffWidth, info.dwEffWidth);
+ // TIFFs store color data RGB instead of BGR
+ uint8_t *pBuf = buffer;
+ for (x = 0; x < width; x++) {
+ uint8_t tmp = pBuf[0];
+ pBuf[0] = pBuf[2];
+ pBuf[2] = tmp;
+ pBuf += 3;
+ }
+ // write the scanline to disc
+ if (TIFFWriteScanline(m_tif, buffer, y, 0)==-1){
+ free(buffer);
+ return false;
+ }
+ }
+ free(buffer);
+ break;
+ }
+ case 32 :
+ {
+#if CXIMAGE_SUPPORT_ALPHA
+ uint8_t *buffer = (uint8_t *)malloc((info.dwEffWidth*4)/3);
+ if (!buffer) return false;
+ for (y = 0; y < height; y++) {
+ // get a pointer to the scanline
+ memcpy(buffer, info.pImage + (height - y - 1)*info.dwEffWidth, info.dwEffWidth);
+ // TIFFs store color data RGB instead of BGR
+ uint8_t *pSrc = buffer + 3 * width;
+ uint8_t *pDst = buffer + 4 * width;
+ for (x = 0; x < width; x++) {
+ pDst-=4;
+ pSrc-=3;
+ pDst[3] = AlphaGet(width-x-1,height-y-1);
+ pDst[2] = pSrc[0];
+ pDst[1] = pSrc[1];
+ pDst[0] = pSrc[2];
+ }
+ // write the scanline to disc
+ if (TIFFWriteScanline(m_tif, buffer, y, 0)==-1){
+ free(buffer);
+ return false;
+ }
+ }
+ free(buffer);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ break;
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+void CxImageTIF::TileToStrip(uint8* out, uint8* in, uint32 rows, uint32 cols, int32_t outskew, int32_t inskew)
+{
+ while (rows-- > 0) {
+ uint32 j = cols;
+ while (j-- > 0)
+ *out++ = *in++;
+ out += outskew;
+ in += inskew;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+TIFF* CxImageTIF::TIFFOpenEx(CxFile * hFile)
+{
+ if (hFile) return _TIFFOpenEx(hFile, "rb");
+ return NULL;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageTIF::TIFFCloseEx(TIFF* tif)
+{
+ if (tif) TIFFClose(tif);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageTIF::MoveBits( uint8_t* dest, uint8_t* from, int32_t count, int32_t bpp )
+{ int32_t offbits = 0;
+ uint16 w;
+ uint32 d;
+ if (bpp <= 8) {
+ while (count-- > 0) {
+ if (offbits + bpp <= 8)
+ w = *from >> (8 - offbits - bpp);
+ else {
+ w = *from++ << (offbits + bpp - 8);
+ w |= *from >> (16 - offbits - bpp);
+ }
+ offbits += bpp;
+ if (offbits >= 8) {
+ offbits -= 8;
+ if (offbits == 0) from++;
+ }
+ *dest++ = (uint8_t)w & ((1 << bpp)-1);
+ }
+ } else if (bpp < 16) {
+ while (count-- > 0) {
+ d = (*from << 24) | (from[1]<<16) | (from[2]<<8) | from[3];
+ d >>= (24 - offbits);
+ *dest++ = (uint8_t) ( d );
+ offbits += bpp;
+ while (offbits >= 8) {
+ from++;
+ offbits -= 8;
+ }
+ }
+ } else if (bpp < 32) {
+ while (count-- > 0) {
+ d = (*from << 24) | (from[1]<<16) | (from[2]<<8) | from[3];
+ //d = *(uint32*)from;
+ *dest++ = (uint8_t) ( d >> (offbits + bpp - 8) );
+ offbits += bpp;
+ while (offbits >= 8) {
+ from++;
+ offbits -= 8;
+ }
+ }
+ } else {
+ while (count-- > 0) {
+ d = *(uint32*)from;
+ *dest++ = (uint8_t) (d >> 24);
+ from += 4;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageTIF::MoveBitsPal( uint8_t* dest, uint8_t*from, int32_t count, int32_t bpp, RGBQUAD* pal )
+{ int32_t offbits = 0;
+ uint32 d;
+ uint16 palidx;
+ while (count-- > 0) {
+ d = (*from << 24) | ( *( from + 1 ) << 16 )
+ | ( *( from + 2 ) << 8 )
+ | ( *( from + 3 ) );
+ palidx = (uint16) (d >> (32 - offbits - bpp));
+ if (bpp < 16) {
+ palidx <<= 16-bpp;
+ palidx = (palidx >> 8) | (palidx <<8);
+ palidx >>= 16-bpp;
+ } else palidx = (palidx >> 8) | (palidx << 8);
+ *dest++ = pal[palidx].rgbBlue;
+ *dest++ = pal[palidx].rgbGreen;
+ *dest++ = pal[palidx].rgbRed;
+ offbits += bpp;
+ while (offbits >= 8) {
+ from++;
+ offbits -= 8;
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+
+#endif // CXIMAGE_SUPPORT_TIF
diff --git a/archive/hge/CxImage/ximatif.h b/archive/hge/CxImage/ximatif.h new file mode 100644 index 0000000..5ea31f0 --- /dev/null +++ b/archive/hge/CxImage/ximatif.h @@ -0,0 +1,62 @@ +/*
+ * File: ximatif.h
+ * Purpose: TIFF Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageTIF (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes
+ *
+ * Special thanks to Abe <God(dot)bless(at)marihuana(dot)com> for MultiPageTIFF code.
+ *
+ * LibTIFF is:
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ * ==========================================================
+ */
+
+#if !defined(__ximatif_h)
+#define __ximatif_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_TIF
+
+#include "../tiff/tiffio.h"
+
+class DLL_EXP CxImageTIF: public CxImage
+{
+public:
+ CxImageTIF(): CxImage(CXIMAGE_FORMAT_TIF) {m_tif2=NULL; m_multipage=false; m_pages=0;}
+ ~CxImageTIF();
+
+ TIFF* TIFFOpenEx(CxFile * hFile);
+ void TIFFCloseEx(TIFF* tif);
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_TIF);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_TIF);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile, bool bAppend=false);
+ bool Encode(CxFile * hFile, CxImage ** pImages, int32_t pagecount);
+ bool Encode(FILE *hFile, bool bAppend=false) { CxIOFile file(hFile); return Encode(&file,bAppend); }
+ bool Encode(FILE *hFile, CxImage ** pImages, int32_t pagecount)
+ { CxIOFile file(hFile); return Encode(&file, pImages, pagecount); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+protected:
+ void TileToStrip(uint8* out, uint8* in, uint32 rows, uint32 cols, int32_t outskew, int32_t inskew);
+ bool EncodeBody(TIFF *m_tif, bool multipage=false, int32_t page=0, int32_t pagecount=0);
+ TIFF *m_tif2;
+ bool m_multipage;
+ int32_t m_pages;
+ void MoveBits( uint8_t* dest, uint8_t* from, int32_t count, int32_t bpp );
+ void MoveBitsPal( uint8_t* dest, uint8_t*from, int32_t count, int32_t bpp, RGBQUAD* pal );
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximatran.cpp b/archive/hge/CxImage/ximatran.cpp new file mode 100644 index 0000000..decac18 --- /dev/null +++ b/archive/hge/CxImage/ximatran.cpp @@ -0,0 +1,2728 @@ +// xImaTran.cpp : Transformation functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+#include "ximath.h"
+
+#if CXIMAGE_SUPPORT_BASICTRANSFORMATIONS
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Increases the number of bits per pixel of the image.
+ * \param nbit: 4, 8, 24
+ */
+bool CxImage::IncreaseBpp(uint32_t nbit)
+{
+ if (!pDib) return false;
+ switch (nbit){
+ case 4:
+ {
+ if (head.biBitCount==4) return true;
+ if (head.biBitCount>4) return false;
+
+ CxImage tmp;
+ tmp.CopyInfo(*this);
+ tmp.Create(head.biWidth,head.biHeight,4,info.dwType);
+ tmp.SetPalette(GetPalette(),GetNumColors());
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+
+#if CXIMAGE_SUPPORT_SELECTION
+ tmp.SelectionCopy(*this);
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+#if CXIMAGE_SUPPORT_ALPHA
+ tmp.AlphaCopy(*this);
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+ tmp.BlindSetPixelIndex(x,y,BlindGetPixelIndex(x,y));
+ }
+ }
+ Transfer(tmp);
+ return true;
+ }
+ case 8:
+ {
+ if (head.biBitCount==8) return true;
+ if (head.biBitCount>8) return false;
+
+ CxImage tmp;
+ tmp.CopyInfo(*this);
+ tmp.Create(head.biWidth,head.biHeight,8,info.dwType);
+ tmp.SetPalette(GetPalette(),GetNumColors());
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+#if CXIMAGE_SUPPORT_SELECTION
+ tmp.SelectionCopy(*this);
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+#if CXIMAGE_SUPPORT_ALPHA
+ tmp.AlphaCopy(*this);
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+ tmp.BlindSetPixelIndex(x,y,BlindGetPixelIndex(x,y));
+ }
+ }
+ Transfer(tmp);
+ return true;
+ }
+ case 24:
+ {
+ if (head.biBitCount==24) return true;
+ if (head.biBitCount>24) return false;
+
+ CxImage tmp;
+ tmp.CopyInfo(*this);
+ tmp.Create(head.biWidth,head.biHeight,24,info.dwType);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ if (info.nBkgndIndex>=0) //translate transparency
+ tmp.info.nBkgndColor=GetPaletteColor((uint8_t)info.nBkgndIndex);
+
+#if CXIMAGE_SUPPORT_SELECTION
+ tmp.SelectionCopy(*this);
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+#if CXIMAGE_SUPPORT_ALPHA
+ tmp.AlphaCopy(*this);
+ if (AlphaPaletteIsValid() && !AlphaIsValid()) tmp.AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+ tmp.BlindSetPixelColor(x,y,BlindGetPixelColor(x,y),true);
+ }
+ }
+ Transfer(tmp);
+ return true;
+ }
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::GrayScale()
+{
+ if (!pDib) return false;
+ if (head.biBitCount<=8){
+ RGBQUAD* ppal=GetPalette();
+ int32_t gray;
+ //converts the colors to gray, use the blue channel only
+ for(uint32_t i=0;i<head.biClrUsed;i++){
+ gray=(int32_t)RGB2GRAY(ppal[i].rgbRed,ppal[i].rgbGreen,ppal[i].rgbBlue);
+ ppal[i].rgbBlue = (uint8_t)gray;
+ }
+ // preserve transparency
+ if (info.nBkgndIndex >= 0) info.nBkgndIndex = ppal[info.nBkgndIndex].rgbBlue;
+ //create a "real" 8 bit gray scale image
+ if (head.biBitCount==8){
+ uint8_t *img=info.pImage;
+ for(uint32_t i=0;i<head.biSizeImage;i++) img[i]=ppal[img[i]].rgbBlue;
+ SetGrayPalette();
+ }
+ //transform to 8 bit gray scale
+ if (head.biBitCount==4 || head.biBitCount==1){
+ CxImage ima;
+ ima.CopyInfo(*this);
+ if (!ima.Create(head.biWidth,head.biHeight,8,info.dwType)) return false;
+ ima.SetGrayPalette();
+#if CXIMAGE_SUPPORT_SELECTION
+ ima.SelectionCopy(*this);
+#endif //CXIMAGE_SUPPORT_SELECTION
+#if CXIMAGE_SUPPORT_ALPHA
+ ima.AlphaCopy(*this);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ for (int32_t y=0;y<head.biHeight;y++){
+ uint8_t *iDst = ima.GetBits(y);
+ uint8_t *iSrc = GetBits(y);
+ for (int32_t x=0;x<head.biWidth; x++){
+ //iDst[x]=ppal[BlindGetPixelIndex(x,y)].rgbBlue;
+ if (head.biBitCount==4){
+ uint8_t pos = (uint8_t)(4*(1-x%2));
+ iDst[x]= ppal[(uint8_t)((iSrc[x >> 1]&((uint8_t)0x0F<<pos)) >> pos)].rgbBlue;
+ } else {
+ uint8_t pos = (uint8_t)(7-x%8);
+ iDst[x]= ppal[(uint8_t)((iSrc[x >> 3]&((uint8_t)0x01<<pos)) >> pos)].rgbBlue;
+ }
+ }
+ }
+ Transfer(ima);
+ }
+ } else { //from RGB to 8 bit gray scale
+ uint8_t *iSrc=info.pImage;
+ CxImage ima;
+ ima.CopyInfo(*this);
+ if (!ima.Create(head.biWidth,head.biHeight,8,info.dwType)) return false;
+ ima.SetGrayPalette();
+ if (GetTransIndex()>=0){
+ RGBQUAD c = GetTransColor();
+ ima.SetTransIndex((uint8_t)RGB2GRAY(c.rgbRed,c.rgbGreen,c.rgbBlue));
+ }
+#if CXIMAGE_SUPPORT_SELECTION
+ ima.SelectionCopy(*this);
+#endif //CXIMAGE_SUPPORT_SELECTION
+#if CXIMAGE_SUPPORT_ALPHA
+ ima.AlphaCopy(*this);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ uint8_t *img=ima.GetBits();
+ int32_t l8=ima.GetEffWidth();
+ int32_t l=head.biWidth * 3;
+ for(int32_t y=0; y < head.biHeight; y++) {
+ for(int32_t x=0,x8=0; x < l; x+=3,x8++) {
+ img[x8+y*l8]=(uint8_t)RGB2GRAY(*(iSrc+x+2),*(iSrc+x+1),*(iSrc+x+0));
+ }
+ iSrc+=info.dwEffWidth;
+ }
+ Transfer(ima);
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa Mirror
+ * \author [qhbo]
+ */
+bool CxImage::Flip(bool bFlipSelection, bool bFlipAlpha)
+{
+ if (!pDib) return false;
+
+ uint8_t *buff = (uint8_t*)malloc(info.dwEffWidth);
+ if (!buff) return false;
+
+ uint8_t *iSrc,*iDst;
+ iSrc = GetBits(head.biHeight-1);
+ iDst = GetBits(0);
+ for (int32_t i=0; i<(head.biHeight/2); ++i)
+ {
+ memcpy(buff, iSrc, info.dwEffWidth);
+ memcpy(iSrc, iDst, info.dwEffWidth);
+ memcpy(iDst, buff, info.dwEffWidth);
+ iSrc-=info.dwEffWidth;
+ iDst+=info.dwEffWidth;
+ }
+
+ free(buff);
+
+ if (bFlipSelection){
+#if CXIMAGE_SUPPORT_SELECTION
+ SelectionFlip();
+#endif //CXIMAGE_SUPPORT_SELECTION
+ }
+
+ if (bFlipAlpha){
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaFlip();
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa Flip
+ */
+bool CxImage::Mirror(bool bMirrorSelection, bool bMirrorAlpha)
+{
+ if (!pDib) return false;
+
+ CxImage* imatmp = new CxImage(*this,false,true,true);
+ if (!imatmp) return false;
+ if (!imatmp->IsValid()){
+ delete imatmp;
+ return false;
+ }
+
+ uint8_t *iSrc,*iDst;
+ int32_t wdt=(head.biWidth-1) * (head.biBitCount==24 ? 3:1);
+ iSrc=info.pImage + wdt;
+ iDst=imatmp->info.pImage;
+ int32_t x,y;
+ switch (head.biBitCount){
+ case 24:
+ for(y=0; y < head.biHeight; y++){
+ for(x=0; x <= wdt; x+=3){
+ *(iDst+x)=*(iSrc-x);
+ *(iDst+x+1)=*(iSrc-x+1);
+ *(iDst+x+2)=*(iSrc-x+2);
+ }
+ iSrc+=info.dwEffWidth;
+ iDst+=info.dwEffWidth;
+ }
+ break;
+ case 8:
+ for(y=0; y < head.biHeight; y++){
+ for(x=0; x <= wdt; x++)
+ *(iDst+x)=*(iSrc-x);
+ iSrc+=info.dwEffWidth;
+ iDst+=info.dwEffWidth;
+ }
+ break;
+ default:
+ for(y=0; y < head.biHeight; y++){
+ for(x=0; x <= wdt; x++)
+ imatmp->SetPixelIndex(x,y,GetPixelIndex(wdt-x,y));
+ }
+ }
+
+ if (bMirrorSelection){
+#if CXIMAGE_SUPPORT_SELECTION
+ imatmp->SelectionMirror();
+#endif //CXIMAGE_SUPPORT_SELECTION
+ }
+
+ if (bMirrorAlpha){
+#if CXIMAGE_SUPPORT_ALPHA
+ imatmp->AlphaMirror();
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+
+ Transfer(*imatmp);
+ delete imatmp;
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#define RBLOCK 64
+
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::RotateLeft(CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ int32_t newWidth = GetHeight();
+ int32_t newHeight = GetWidth();
+
+ CxImage imgDest;
+ imgDest.CopyInfo(*this);
+ imgDest.Create(newWidth,newHeight,GetBpp(),GetType());
+ imgDest.SetPalette(GetPalette());
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) imgDest.AlphaCreate();
+#endif
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (SelectionIsValid()) imgDest.SelectionCreate();
+#endif
+
+ int32_t x,x2,y,dlineup;
+
+ // Speedy rotate for BW images <Robert Abram>
+ if (head.biBitCount == 1) {
+
+ uint8_t *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp;
+ ldiv_t div_r;
+
+ uint8_t *bsrc = GetBits(), *bdest = imgDest.GetBits();
+ dbitsmax = bdest + imgDest.head.biSizeImage - 1;
+ dlineup = 8 * imgDest.info.dwEffWidth - imgDest.head.biWidth;
+
+ imgDest.Clear(0);
+ for (y = 0; y < head.biHeight; y++) {
+ // Figure out the Column we are going to be copying to
+ div_r = ldiv(y + dlineup, (int32_t)8);
+ // set bit pos of src column byte
+ bitpos = (uint8_t)(1 << div_r.rem);
+ srcdisp = bsrc + y * info.dwEffWidth;
+ for (x = 0; x < (int32_t)info.dwEffWidth; x++) {
+ // Get Source Bits
+ sbits = srcdisp + x;
+ // Get destination column
+ nrow = bdest + (x * 8) * imgDest.info.dwEffWidth + imgDest.info.dwEffWidth - 1 - div_r.quot;
+ for (int32_t z = 0; z < 8; z++) {
+ // Get Destination Byte
+ dbits = nrow + z * imgDest.info.dwEffWidth;
+ if ((dbits < bdest) || (dbits > dbitsmax)) break;
+ if (*sbits & (128 >> z)) *dbits |= bitpos;
+ }
+ }
+ }//for y
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) {
+ for (x = 0; x < newWidth; x++){
+ x2=newWidth-x-1;
+ for (y = 0; y < newHeight; y++){
+ imgDest.AlphaSet(x,y,BlindAlphaGet(y, x2));
+ }//for y
+ }//for x
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (SelectionIsValid()) {
+ imgDest.info.rSelectionBox.left = newWidth-info.rSelectionBox.top;
+ imgDest.info.rSelectionBox.right = newWidth-info.rSelectionBox.bottom;
+ imgDest.info.rSelectionBox.bottom = info.rSelectionBox.left;
+ imgDest.info.rSelectionBox.top = info.rSelectionBox.right;
+ for (x = 0; x < newWidth; x++){
+ x2=newWidth-x-1;
+ for (y = 0; y < newHeight; y++){
+ imgDest.SelectionSet(x,y,BlindSelectionGet(y, x2));
+ }//for y
+ }//for x
+ }
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+ } else {
+ //anything other than BW:
+ //bd, 10. 2004: This optimized version of rotation rotates image by smaller blocks. It is quite
+ //a bit faster than obvious algorithm, because it produces much less CPU cache misses.
+ //This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current
+ //CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase
+ //speed somehow, but once you drop out of CPU's cache, things will slow down drastically.
+ //For older CPUs with less cache, lower value would yield better results.
+
+ uint8_t *srcPtr, *dstPtr; //source and destionation for 24-bit version
+ int32_t xs, ys; //x-segment and y-segment
+ for (xs = 0; xs < newWidth; xs+=RBLOCK) { //for all image blocks of RBLOCK*RBLOCK pixels
+ for (ys = 0; ys < newHeight; ys+=RBLOCK) {
+ if (head.biBitCount==24) {
+ //RGB24 optimized pixel access:
+ for (x = xs; x < min(newWidth, xs+RBLOCK); x++){ //do rotation
+ info.nProgress = (int32_t)(100*x/newWidth);
+ x2=newWidth-x-1;
+ dstPtr = (uint8_t*) imgDest.BlindGetPixelPointer(x,ys);
+ srcPtr = (uint8_t*) BlindGetPixelPointer(ys, x2);
+ for (y = ys; y < min(newHeight, ys+RBLOCK); y++){
+ //imgDest.SetPixelColor(x, y, GetPixelColor(y, x2));
+ *(dstPtr) = *(srcPtr);
+ *(dstPtr+1) = *(srcPtr+1);
+ *(dstPtr+2) = *(srcPtr+2);
+ srcPtr += 3;
+ dstPtr += imgDest.info.dwEffWidth;
+ }//for y
+ }//for x
+ } else {
+ //anything else than 24bpp (and 1bpp): palette
+ for (x = xs; x < min(newWidth, xs+RBLOCK); x++){
+ info.nProgress = (int32_t)(100*x/newWidth); //<Anatoly Ivasyuk>
+ x2=newWidth-x-1;
+ for (y = ys; y < min(newHeight, ys+RBLOCK); y++){
+ imgDest.SetPixelIndex(x, y, BlindGetPixelIndex(y, x2));
+ }//for y
+ }//for x
+ }//if (version selection)
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) {
+ for (x = xs; x < min(newWidth, xs+RBLOCK); x++){
+ x2=newWidth-x-1;
+ for (y = ys; y < min(newHeight, ys+RBLOCK); y++){
+ imgDest.AlphaSet(x,y,BlindAlphaGet(y, x2));
+ }//for y
+ }//for x
+ }//if (alpha channel)
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (SelectionIsValid()) {
+ imgDest.info.rSelectionBox.left = newWidth-info.rSelectionBox.top;
+ imgDest.info.rSelectionBox.right = newWidth-info.rSelectionBox.bottom;
+ imgDest.info.rSelectionBox.bottom = info.rSelectionBox.left;
+ imgDest.info.rSelectionBox.top = info.rSelectionBox.right;
+ for (x = xs; x < min(newWidth, xs+RBLOCK); x++){
+ x2=newWidth-x-1;
+ for (y = ys; y < min(newHeight, ys+RBLOCK); y++){
+ imgDest.SelectionSet(x,y,BlindSelectionGet(y, x2));
+ }//for y
+ }//for x
+ }//if (selection)
+#endif //CXIMAGE_SUPPORT_SELECTION
+ }//for ys
+ }//for xs
+ }//if
+
+ //select the destination
+ if (iDst) iDst->Transfer(imgDest);
+ else Transfer(imgDest);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::RotateRight(CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ int32_t newWidth = GetHeight();
+ int32_t newHeight = GetWidth();
+
+ CxImage imgDest;
+ imgDest.CopyInfo(*this);
+ imgDest.Create(newWidth,newHeight,GetBpp(),GetType());
+ imgDest.SetPalette(GetPalette());
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) imgDest.AlphaCreate();
+#endif
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (SelectionIsValid()) imgDest.SelectionCreate();
+#endif
+
+ int32_t x,y,y2;
+ // Speedy rotate for BW images <Robert Abram>
+ if (head.biBitCount == 1) {
+
+ uint8_t *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp;
+ ldiv_t div_r;
+
+ uint8_t *bsrc = GetBits(), *bdest = imgDest.GetBits();
+ dbitsmax = bdest + imgDest.head.biSizeImage - 1;
+
+ imgDest.Clear(0);
+ for (y = 0; y < head.biHeight; y++) {
+ // Figure out the Column we are going to be copying to
+ div_r = ldiv(y, (int32_t)8);
+ // set bit pos of src column byte
+ bitpos = (uint8_t)(128 >> div_r.rem);
+ srcdisp = bsrc + y * info.dwEffWidth;
+ for (x = 0; x < (int32_t)info.dwEffWidth; x++) {
+ // Get Source Bits
+ sbits = srcdisp + x;
+ // Get destination column
+ nrow = bdest + (imgDest.head.biHeight-1-(x*8)) * imgDest.info.dwEffWidth + div_r.quot;
+ for (int32_t z = 0; z < 8; z++) {
+ // Get Destination Byte
+ dbits = nrow - z * imgDest.info.dwEffWidth;
+ if ((dbits < bdest) || (dbits > dbitsmax)) break;
+ if (*sbits & (128 >> z)) *dbits |= bitpos;
+ }
+ }
+ }
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()){
+ for (y = 0; y < newHeight; y++){
+ y2=newHeight-y-1;
+ for (x = 0; x < newWidth; x++){
+ imgDest.AlphaSet(x,y,BlindAlphaGet(y2, x));
+ }
+ }
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (SelectionIsValid()){
+ imgDest.info.rSelectionBox.left = info.rSelectionBox.bottom;
+ imgDest.info.rSelectionBox.right = info.rSelectionBox.top;
+ imgDest.info.rSelectionBox.bottom = newHeight-info.rSelectionBox.right;
+ imgDest.info.rSelectionBox.top = newHeight-info.rSelectionBox.left;
+ for (y = 0; y < newHeight; y++){
+ y2=newHeight-y-1;
+ for (x = 0; x < newWidth; x++){
+ imgDest.SelectionSet(x,y,BlindSelectionGet(y2, x));
+ }
+ }
+ }
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+ } else {
+ //anything else but BW
+ uint8_t *srcPtr, *dstPtr; //source and destionation for 24-bit version
+ int32_t xs, ys; //x-segment and y-segment
+ for (xs = 0; xs < newWidth; xs+=RBLOCK) {
+ for (ys = 0; ys < newHeight; ys+=RBLOCK) {
+ if (head.biBitCount==24) {
+ //RGB24 optimized pixel access:
+ for (y = ys; y < min(newHeight, ys+RBLOCK); y++){
+ info.nProgress = (int32_t)(100*y/newHeight); //<Anatoly Ivasyuk>
+ y2=newHeight-y-1;
+ dstPtr = (uint8_t*) imgDest.BlindGetPixelPointer(xs,y);
+ srcPtr = (uint8_t*) BlindGetPixelPointer(y2, xs);
+ for (x = xs; x < min(newWidth, xs+RBLOCK); x++){
+ //imgDest.SetPixelColor(x, y, GetPixelColor(y2, x));
+ *(dstPtr) = *(srcPtr);
+ *(dstPtr+1) = *(srcPtr+1);
+ *(dstPtr+2) = *(srcPtr+2);
+ dstPtr += 3;
+ srcPtr += info.dwEffWidth;
+ }//for x
+ }//for y
+ } else {
+ //anything else than BW & RGB24: palette
+ for (y = ys; y < min(newHeight, ys+RBLOCK); y++){
+ info.nProgress = (int32_t)(100*y/newHeight); //<Anatoly Ivasyuk>
+ y2=newHeight-y-1;
+ for (x = xs; x < min(newWidth, xs+RBLOCK); x++){
+ imgDest.SetPixelIndex(x, y, BlindGetPixelIndex(y2, x));
+ }//for x
+ }//for y
+ }//if
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()){
+ for (y = ys; y < min(newHeight, ys+RBLOCK); y++){
+ y2=newHeight-y-1;
+ for (x = xs; x < min(newWidth, xs+RBLOCK); x++){
+ imgDest.AlphaSet(x,y,BlindAlphaGet(y2, x));
+ }//for x
+ }//for y
+ }//if (has alpha)
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (SelectionIsValid()){
+ imgDest.info.rSelectionBox.left = info.rSelectionBox.bottom;
+ imgDest.info.rSelectionBox.right = info.rSelectionBox.top;
+ imgDest.info.rSelectionBox.bottom = newHeight-info.rSelectionBox.right;
+ imgDest.info.rSelectionBox.top = newHeight-info.rSelectionBox.left;
+ for (y = ys; y < min(newHeight, ys+RBLOCK); y++){
+ y2=newHeight-y-1;
+ for (x = xs; x < min(newWidth, xs+RBLOCK); x++){
+ imgDest.SelectionSet(x,y,BlindSelectionGet(y2, x));
+ }//for x
+ }//for y
+ }//if (has alpha)
+#endif //CXIMAGE_SUPPORT_SELECTION
+ }//for ys
+ }//for xs
+ }//if
+
+ //select the destination
+ if (iDst) iDst->Transfer(imgDest);
+ else Transfer(imgDest);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::Negative()
+{
+ if (!pDib) return false;
+
+ if (head.biBitCount<=8){
+ if (IsGrayScale()){ //GRAYSCALE, selection
+ if (pSelection){
+ for(int32_t y=info.rSelectionBox.bottom; y<info.rSelectionBox.top; y++){
+ for(int32_t x=info.rSelectionBox.left; x<info.rSelectionBox.right; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ BlindSetPixelIndex(x,y,(uint8_t)(255-BlindGetPixelIndex(x,y)));
+ }
+ }
+ }
+ } else {
+ uint8_t *iSrc=info.pImage;
+ for(uint32_t i=0; i < head.biSizeImage; i++){
+ *iSrc=(uint8_t)~(*(iSrc));
+ iSrc++;
+ }
+ }
+ } else { //PALETTE, full image
+ RGBQUAD* ppal=GetPalette();
+ for(uint32_t i=0;i<head.biClrUsed;i++){
+ ppal[i].rgbBlue =(uint8_t)(255-ppal[i].rgbBlue);
+ ppal[i].rgbGreen =(uint8_t)(255-ppal[i].rgbGreen);
+ ppal[i].rgbRed =(uint8_t)(255-ppal[i].rgbRed);
+ }
+ }
+ } else {
+ if (pSelection==NULL){ //RGB, full image
+ uint8_t *iSrc=info.pImage;
+ for(uint32_t i=0; i < head.biSizeImage; i++){
+ *iSrc=(uint8_t)~(*(iSrc));
+ iSrc++;
+ }
+ } else { // RGB with selection
+ RGBQUAD color;
+ for(int32_t y=info.rSelectionBox.bottom; y<info.rSelectionBox.top; y++){
+ for(int32_t x=info.rSelectionBox.left; x<info.rSelectionBox.right; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ color = BlindGetPixelColor(x,y);
+ color.rgbRed = (uint8_t)(255-color.rgbRed);
+ color.rgbGreen = (uint8_t)(255-color.rgbGreen);
+ color.rgbBlue = (uint8_t)(255-color.rgbBlue);
+ BlindSetPixelColor(x,y,color);
+ }
+ }
+ }
+ }
+ //<DP> invert transparent color too
+ info.nBkgndColor.rgbBlue = (uint8_t)(255-info.nBkgndColor.rgbBlue);
+ info.nBkgndColor.rgbGreen = (uint8_t)(255-info.nBkgndColor.rgbGreen);
+ info.nBkgndColor.rgbRed = (uint8_t)(255-info.nBkgndColor.rgbRed);
+ }
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_BASICTRANSFORMATIONS
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_TRANSFORMATION
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_EXIF
+bool CxImage::RotateExif(int32_t orientation /* = 0 */)
+{
+ bool ret = true;
+ if (orientation <= 0)
+ orientation = info.ExifInfo.Orientation;
+ if (orientation == 3)
+ ret = Rotate180();
+ else if (orientation == 6)
+ ret = RotateRight();
+ else if (orientation == 8)
+ ret = RotateLeft();
+ else if (orientation == 5)
+ ret = RotateLeft();
+
+ info.ExifInfo.Orientation = 1;
+ return ret;
+}
+#endif //CXIMAGE_SUPPORT_EXIF
+
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::Rotate(float angle, CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ if (fmod(angle,180.0f)==0.0f && fmod(angle,360.0f)!=0.0f)
+ return Rotate180(iDst);
+
+ // Copyright (c) 1996-1998 Ulrich von Zadow
+
+ // Negative the angle, because the y-axis is negative.
+ double ang = -angle*acos((float)0)/90;
+ int32_t newWidth, newHeight;
+ int32_t nWidth = GetWidth();
+ int32_t nHeight= GetHeight();
+ double cos_angle = cos(ang);
+ double sin_angle = sin(ang);
+
+ // Calculate the size of the new bitmap
+ POINT p1={0,0};
+ POINT p2={nWidth,0};
+ POINT p3={0,nHeight};
+ POINT p4={nWidth,nHeight};
+ CxPoint2 newP1,newP2,newP3,newP4, leftTop, rightTop, leftBottom, rightBottom;
+
+ newP1.x = (float)p1.x;
+ newP1.y = (float)p1.y;
+ newP2.x = (float)(p2.x*cos_angle - p2.y*sin_angle);
+ newP2.y = (float)(p2.x*sin_angle + p2.y*cos_angle);
+ newP3.x = (float)(p3.x*cos_angle - p3.y*sin_angle);
+ newP3.y = (float)(p3.x*sin_angle + p3.y*cos_angle);
+ newP4.x = (float)(p4.x*cos_angle - p4.y*sin_angle);
+ newP4.y = (float)(p4.x*sin_angle + p4.y*cos_angle);
+
+ leftTop.x = min(min(newP1.x,newP2.x),min(newP3.x,newP4.x));
+ leftTop.y = min(min(newP1.y,newP2.y),min(newP3.y,newP4.y));
+ rightBottom.x = max(max(newP1.x,newP2.x),max(newP3.x,newP4.x));
+ rightBottom.y = max(max(newP1.y,newP2.y),max(newP3.y,newP4.y));
+ leftBottom.x = leftTop.x;
+ leftBottom.y = rightBottom.y;
+ rightTop.x = rightBottom.x;
+ rightTop.y = leftTop.y;
+
+ newWidth = (int32_t) floor(0.5f + rightTop.x - leftTop.x);
+ newHeight= (int32_t) floor(0.5f + leftBottom.y - leftTop.y);
+ CxImage imgDest;
+ imgDest.CopyInfo(*this);
+ imgDest.Create(newWidth,newHeight,GetBpp(),GetType());
+ imgDest.SetPalette(GetPalette());
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if(AlphaIsValid()) //MTA: Fix for rotation problem when the image has an alpha channel
+ {
+ imgDest.AlphaCreate();
+ imgDest.AlphaClear();
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ int32_t x,y,newX,newY,oldX,oldY;
+
+ if (head.biClrUsed==0){ //RGB
+ for (y = (int32_t)leftTop.y, newY = 0; y<=(int32_t)leftBottom.y; y++,newY++){
+ info.nProgress = (int32_t)(100*newY/newHeight);
+ if (info.nEscape) break;
+ for (x = (int32_t)leftTop.x, newX = 0; x<=(int32_t)rightTop.x; x++,newX++){
+ oldX = (int32_t)(x*cos_angle + y*sin_angle + 0.5);
+ oldY = (int32_t)(y*cos_angle - x*sin_angle + 0.5);
+ imgDest.SetPixelColor(newX,newY,GetPixelColor(oldX,oldY));
+#if CXIMAGE_SUPPORT_ALPHA
+ imgDest.AlphaSet(newX,newY,AlphaGet(oldX,oldY)); //MTA: copy the alpha value
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+ } else { //PALETTE
+ for (y = (int32_t)leftTop.y, newY = 0; y<=(int32_t)leftBottom.y; y++,newY++){
+ info.nProgress = (int32_t)(100*newY/newHeight);
+ if (info.nEscape) break;
+ for (x = (int32_t)leftTop.x, newX = 0; x<=(int32_t)rightTop.x; x++,newX++){
+ oldX = (int32_t)(x*cos_angle + y*sin_angle + 0.5);
+ oldY = (int32_t)(y*cos_angle - x*sin_angle + 0.5);
+ imgDest.SetPixelIndex(newX,newY,GetPixelIndex(oldX,oldY));
+#if CXIMAGE_SUPPORT_ALPHA
+ imgDest.AlphaSet(newX,newY,AlphaGet(oldX,oldY)); //MTA: copy the alpha value
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+ }
+ //select the destination
+ if (iDst) iDst->Transfer(imgDest);
+ else Transfer(imgDest);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Rotates image around it's center.
+ * Method can use interpolation with paletted images, but does not change pallete, so results vary.
+ * (If you have only four colours in a palette, there's not much room for interpolation.)
+ *
+ * \param angle - angle in degrees (positive values rotate clockwise)
+ * \param *iDst - destination image (if null, this image is changed)
+ * \param inMethod - interpolation method used
+ * (IM_NEAREST_NEIGHBOUR produces aliasing (fast), IM_BILINEAR softens picture a bit (slower)
+ * IM_SHARPBICUBIC is slower and produces some halos...)
+ * \param ofMethod - overflow method (how to choose colour of pixels that have no source)
+ * \param replColor - replacement colour to use (OM_COLOR, OM_BACKGROUND with no background colour...)
+ * \param optimizeRightAngles - call faster methods for 90, 180, and 270 degree rotations. Faster methods
+ * are called for angles, where error (in location of corner pixels) is less
+ * than 0.25 pixels.
+ * \param bKeepOriginalSize - rotates the image without resizing.
+ *
+ * \author ***bd*** 2.2004
+ */
+bool CxImage::Rotate2(float angle,
+ CxImage *iDst,
+ InterpolationMethod inMethod,
+ OverflowMethod ofMethod,
+ RGBQUAD *replColor,
+ bool const optimizeRightAngles,
+ bool const bKeepOriginalSize)
+{
+ if (!pDib) return false; //no dib no go
+
+ if (fmod(angle,180.0f)==0.0f && fmod(angle,360.0f)!=0.0f)
+ return Rotate180(iDst);
+
+ double ang = -angle*acos(0.0f)/90.0f; //convert angle to radians and invert (positive angle performs clockwise rotation)
+ float cos_angle = (float) cos(ang); //these two are needed later (to rotate)
+ float sin_angle = (float) sin(ang);
+
+ //Calculate the size of the new bitmap (rotate corners of image)
+ CxPoint2 p[4]; //original corners of the image
+ p[0]=CxPoint2(-0.5f,-0.5f);
+ p[1]=CxPoint2(GetWidth()-0.5f,-0.5f);
+ p[2]=CxPoint2(-0.5f,GetHeight()-0.5f);
+ p[3]=CxPoint2(GetWidth()-0.5f,GetHeight()-0.5f);
+ CxPoint2 newp[4]; //rotated positions of corners
+ //(rotate corners)
+ if (bKeepOriginalSize){
+ for (int32_t i=0; i<4; i++) {
+ newp[i].x = p[i].x;
+ newp[i].y = p[i].y;
+ }//for
+ } else {
+ for (int32_t i=0; i<4; i++) {
+ newp[i].x = (p[i].x*cos_angle - p[i].y*sin_angle);
+ newp[i].y = (p[i].x*sin_angle + p[i].y*cos_angle);
+ }//for i
+
+ if (optimizeRightAngles) {
+ //For rotations of 90, -90 or 180 or 0 degrees, call faster routines
+ if (newp[3].Distance(CxPoint2(GetHeight()-0.5f, 0.5f-GetWidth())) < 0.25)
+ //rotation right for circa 90 degrees (diagonal pixels less than 0.25 pixel away from 90 degree rotation destination)
+ return RotateRight(iDst);
+ if (newp[3].Distance(CxPoint2(0.5f-GetHeight(), -0.5f+GetWidth())) < 0.25)
+ //rotation left for ~90 degrees
+ return RotateLeft(iDst);
+ if (newp[3].Distance(CxPoint2(0.5f-GetWidth(), 0.5f-GetHeight())) < 0.25)
+ //rotation left for ~180 degrees
+ return Rotate180(iDst);
+ if (newp[3].Distance(p[3]) < 0.25) {
+ //rotation not significant
+ if (iDst) iDst->Copy(*this); //copy image to iDst, if required
+ return true; //and we're done
+ }//if
+ }//if
+ }//if
+
+ //(read new dimensions from location of corners)
+ float minx = (float) min(min(newp[0].x,newp[1].x),min(newp[2].x,newp[3].x));
+ float miny = (float) min(min(newp[0].y,newp[1].y),min(newp[2].y,newp[3].y));
+ float maxx = (float) max(max(newp[0].x,newp[1].x),max(newp[2].x,newp[3].x));
+ float maxy = (float) max(max(newp[0].y,newp[1].y),max(newp[2].y,newp[3].y));
+ int32_t newWidth = (int32_t) floor(maxx-minx+0.5f);
+ int32_t newHeight= (int32_t) floor(maxy-miny+0.5f);
+ float ssx=((maxx+minx)- ((float) newWidth-1))/2.0f; //start for x
+ float ssy=((maxy+miny)- ((float) newHeight-1))/2.0f; //start for y
+
+ float newxcenteroffset = 0.5f * newWidth;
+ float newycenteroffset = 0.5f * newHeight;
+ if (bKeepOriginalSize){
+ ssx -= 0.5f * GetWidth();
+ ssy -= 0.5f * GetHeight();
+ }
+
+ //create destination image
+ CxImage imgDest;
+ imgDest.CopyInfo(*this);
+ imgDest.Create(newWidth,newHeight,GetBpp(),GetType());
+ imgDest.SetPalette(GetPalette());
+#if CXIMAGE_SUPPORT_ALPHA
+ if(AlphaIsValid()) imgDest.AlphaCreate(); //MTA: Fix for rotation problem when the image has an alpha channel
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ RGBQUAD rgb; //pixel colour
+ RGBQUAD rc;
+ if (replColor!=0)
+ rc=*replColor;
+ else {
+ rc.rgbRed=255; rc.rgbGreen=255; rc.rgbBlue=255; rc.rgbReserved=0;
+ }//if
+ float x,y; //destination location (float, with proper offset)
+ float origx, origy; //origin location
+ int32_t destx, desty; //destination location
+
+ y=ssy; //initialize y
+ if (!IsIndexed()){ //RGB24
+ //optimized RGB24 implementation (direct write to destination):
+ uint8_t *pxptr;
+#if CXIMAGE_SUPPORT_ALPHA
+ uint8_t *pxptra=0;
+#endif //CXIMAGE_SUPPORT_ALPHA
+ for (desty=0; desty<newHeight; desty++) {
+ info.nProgress = (int32_t)(100*desty/newHeight);
+ if (info.nEscape) break;
+ //initialize x
+ x=ssx;
+ //calculate pointer to first byte in row
+ pxptr=(uint8_t *)imgDest.BlindGetPixelPointer(0, desty);
+#if CXIMAGE_SUPPORT_ALPHA
+ //calculate pointer to first byte in row
+ if (AlphaIsValid()) pxptra=imgDest.AlphaGetPointer(0, desty);
+#endif //CXIMAGE_SUPPORT_ALPHA
+ for (destx=0; destx<newWidth; destx++) {
+ //get source pixel coordinate for current destination point
+ //origx = (cos_angle*(x-head.biWidth/2)+sin_angle*(y-head.biHeight/2))+newWidth/2;
+ //origy = (cos_angle*(y-head.biHeight/2)-sin_angle*(x-head.biWidth/2))+newHeight/2;
+ origx = cos_angle*x+sin_angle*y;
+ origy = cos_angle*y-sin_angle*x;
+ if (bKeepOriginalSize){
+ origx += newxcenteroffset;
+ origy += newycenteroffset;
+ }
+ rgb = GetPixelColorInterpolated(origx, origy, inMethod, ofMethod, &rc); //get interpolated colour value
+ //copy alpha and colour value to destination
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pxptra) *pxptra++ = rgb.rgbReserved;
+#endif //CXIMAGE_SUPPORT_ALPHA
+ *pxptr++ = rgb.rgbBlue;
+ *pxptr++ = rgb.rgbGreen;
+ *pxptr++ = rgb.rgbRed;
+ x++;
+ }//for destx
+ y++;
+ }//for desty
+ } else {
+ //non-optimized implementation for paletted images
+ for (desty=0; desty<newHeight; desty++) {
+ info.nProgress = (int32_t)(100*desty/newHeight);
+ if (info.nEscape) break;
+ x=ssx;
+ for (destx=0; destx<newWidth; destx++) {
+ //get source pixel coordinate for current destination point
+ origx=(cos_angle*x+sin_angle*y);
+ origy=(cos_angle*y-sin_angle*x);
+ if (bKeepOriginalSize){
+ origx += newxcenteroffset;
+ origy += newycenteroffset;
+ }
+ rgb = GetPixelColorInterpolated(origx, origy, inMethod, ofMethod, &rc);
+ //***!*** SetPixelColor is slow for palleted images
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid())
+ imgDest.SetPixelColor(destx,desty,rgb,true);
+ else
+#endif //CXIMAGE_SUPPORT_ALPHA
+ imgDest.SetPixelColor(destx,desty,rgb,false);
+ x++;
+ }//for destx
+ y++;
+ }//for desty
+ }
+ //select the destination
+
+ if (iDst) iDst->Transfer(imgDest);
+ else Transfer(imgDest);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::Rotate180(CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ int32_t wid = GetWidth();
+ int32_t ht = GetHeight();
+
+ CxImage imgDest;
+ imgDest.CopyInfo(*this);
+ imgDest.Create(wid,ht,GetBpp(),GetType());
+ imgDest.SetPalette(GetPalette());
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) imgDest.AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ int32_t x,y,y2;
+ for (y = 0; y < ht; y++){
+ info.nProgress = (int32_t)(100*y/ht); //<Anatoly Ivasyuk>
+ y2=ht-y-1;
+ for (x = 0; x < wid; x++){
+ if(head.biClrUsed==0)//RGB
+ imgDest.SetPixelColor(wid-x-1, y2, BlindGetPixelColor(x, y));
+ else //PALETTE
+ imgDest.SetPixelIndex(wid-x-1, y2, BlindGetPixelIndex(x, y));
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) imgDest.AlphaSet(wid-x-1, y2,BlindAlphaGet(x, y));
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ }
+ }
+
+ //select the destination
+ if (iDst) iDst->Transfer(imgDest);
+ else Transfer(imgDest);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Resizes the image. mode can be 0 for slow (bilinear) method ,
+ * 1 for fast (nearest pixel) method, or 2 for accurate (bicubic spline interpolation) method.
+ * The function is faster with 24 and 1 bpp images, slow for 4 bpp images and slowest for 8 bpp images.
+ */
+bool CxImage::Resample(int32_t newx, int32_t newy, int32_t mode, CxImage* iDst)
+{
+ if (newx==0 || newy==0) return false;
+
+ if (head.biWidth==newx && head.biHeight==newy){
+ if (iDst) iDst->Copy(*this);
+ return true;
+ }
+
+ float xScale, yScale, fX, fY;
+ xScale = (float)head.biWidth / (float)newx;
+ yScale = (float)head.biHeight / (float)newy;
+
+ CxImage newImage;
+ newImage.CopyInfo(*this);
+ newImage.Create(newx,newy,head.biBitCount,GetType());
+ newImage.SetPalette(GetPalette());
+ if (!newImage.IsValid()){
+ strcpy(info.szLastError,newImage.GetLastError());
+ return false;
+ }
+
+ switch (mode) {
+ case 1: // nearest pixel
+ {
+ for(int32_t y=0; y<newy; y++){
+ info.nProgress = (int32_t)(100*y/newy);
+ if (info.nEscape) break;
+ fY = y * yScale;
+ for(int32_t x=0; x<newx; x++){
+ fX = x * xScale;
+ newImage.SetPixelColor(x,y,GetPixelColor((int32_t)fX,(int32_t)fY));
+ }
+ }
+ break;
+ }
+ case 2: // bicubic interpolation by Blake L. Carlson <blake-carlson(at)uiowa(dot)edu
+ {
+ float f_x, f_y, a, b, rr, gg, bb, r1, r2;
+ int32_t i_x, i_y, xx, yy;
+ RGBQUAD rgb;
+ uint8_t* iDst;
+ for(int32_t y=0; y<newy; y++){
+ info.nProgress = (int32_t)(100*y/newy);
+ if (info.nEscape) break;
+ f_y = (float) y * yScale - 0.5f;
+ i_y = (int32_t) floor(f_y);
+ a = f_y - (float)floor(f_y);
+ for(int32_t x=0; x<newx; x++){
+ f_x = (float) x * xScale - 0.5f;
+ i_x = (int32_t) floor(f_x);
+ b = f_x - (float)floor(f_x);
+
+ rr = gg = bb = 0.0f;
+ for(int32_t m=-1; m<3; m++) {
+ r1 = KernelBSpline((float) m - a);
+ yy = i_y+m;
+ if (yy<0) yy=0;
+ if (yy>=head.biHeight) yy = head.biHeight-1;
+ for(int32_t n=-1; n<3; n++) {
+ r2 = r1 * KernelBSpline(b - (float)n);
+ xx = i_x+n;
+ if (xx<0) xx=0;
+ if (xx>=head.biWidth) xx=head.biWidth-1;
+
+ if (head.biClrUsed){
+ rgb = GetPixelColor(xx,yy);
+ } else {
+ iDst = info.pImage + yy*info.dwEffWidth + xx*3;
+ rgb.rgbBlue = *iDst++;
+ rgb.rgbGreen= *iDst++;
+ rgb.rgbRed = *iDst;
+ }
+
+ rr += rgb.rgbRed * r2;
+ gg += rgb.rgbGreen * r2;
+ bb += rgb.rgbBlue * r2;
+ }
+ }
+
+ if (head.biClrUsed)
+ newImage.SetPixelColor(x,y,RGB(rr,gg,bb));
+ else {
+ iDst = newImage.info.pImage + y*newImage.info.dwEffWidth + x*3;
+ *iDst++ = (uint8_t)bb;
+ *iDst++ = (uint8_t)gg;
+ *iDst = (uint8_t)rr;
+ }
+
+ }
+ }
+ break;
+ }
+ default: // bilinear interpolation
+ if (!(head.biWidth>newx && head.biHeight>newy && head.biBitCount==24)) {
+ // (c) 1999 Steve McMahon (steve@dogma.demon.co.uk)
+ int32_t ifX, ifY, ifX1, ifY1, xmax, ymax;
+ float ir1, ir2, ig1, ig2, ib1, ib2, dx, dy;
+ uint8_t r,g,b;
+ RGBQUAD rgb1, rgb2, rgb3, rgb4;
+ xmax = head.biWidth-1;
+ ymax = head.biHeight-1;
+ for(int32_t y=0; y<newy; y++){
+ info.nProgress = (int32_t)(100*y/newy);
+ if (info.nEscape) break;
+ fY = y * yScale;
+ ifY = (int32_t)fY;
+ ifY1 = min(ymax, ifY+1);
+ dy = fY - ifY;
+ for(int32_t x=0; x<newx; x++){
+ fX = x * xScale;
+ ifX = (int32_t)fX;
+ ifX1 = min(xmax, ifX+1);
+ dx = fX - ifX;
+ // Interpolate using the four nearest pixels in the source
+ if (head.biClrUsed){
+ rgb1=GetPaletteColor(GetPixelIndex(ifX,ifY));
+ rgb2=GetPaletteColor(GetPixelIndex(ifX1,ifY));
+ rgb3=GetPaletteColor(GetPixelIndex(ifX,ifY1));
+ rgb4=GetPaletteColor(GetPixelIndex(ifX1,ifY1));
+ }
+ else {
+ uint8_t* iDst;
+ iDst = info.pImage + ifY*info.dwEffWidth + ifX*3;
+ rgb1.rgbBlue = *iDst++; rgb1.rgbGreen= *iDst++; rgb1.rgbRed =*iDst;
+ iDst = info.pImage + ifY*info.dwEffWidth + ifX1*3;
+ rgb2.rgbBlue = *iDst++; rgb2.rgbGreen= *iDst++; rgb2.rgbRed =*iDst;
+ iDst = info.pImage + ifY1*info.dwEffWidth + ifX*3;
+ rgb3.rgbBlue = *iDst++; rgb3.rgbGreen= *iDst++; rgb3.rgbRed =*iDst;
+ iDst = info.pImage + ifY1*info.dwEffWidth + ifX1*3;
+ rgb4.rgbBlue = *iDst++; rgb4.rgbGreen= *iDst++; rgb4.rgbRed =*iDst;
+ }
+ // Interplate in x direction:
+ ir1 = rgb1.rgbRed + (rgb3.rgbRed - rgb1.rgbRed) * dy;
+ ig1 = rgb1.rgbGreen + (rgb3.rgbGreen - rgb1.rgbGreen) * dy;
+ ib1 = rgb1.rgbBlue + (rgb3.rgbBlue - rgb1.rgbBlue) * dy;
+ ir2 = rgb2.rgbRed + (rgb4.rgbRed - rgb2.rgbRed) * dy;
+ ig2 = rgb2.rgbGreen + (rgb4.rgbGreen - rgb2.rgbGreen) * dy;
+ ib2 = rgb2.rgbBlue + (rgb4.rgbBlue - rgb2.rgbBlue) * dy;
+ // Interpolate in y:
+ r = (uint8_t)(ir1 + (ir2-ir1) * dx);
+ g = (uint8_t)(ig1 + (ig2-ig1) * dx);
+ b = (uint8_t)(ib1 + (ib2-ib1) * dx);
+ // Set output
+ newImage.SetPixelColor(x,y,RGB(r,g,b));
+ }
+ }
+ } else {
+ //high resolution shrink, thanks to Henrik Stellmann <henrik.stellmann@volleynet.de>
+ const int32_t ACCURACY = 1000;
+ int32_t i,j; // index for faValue
+ int32_t x,y; // coordinates in source image
+ uint8_t* pSource;
+ uint8_t* pDest = newImage.info.pImage;
+ int32_t* naAccu = new int32_t[3 * newx + 3];
+ int32_t* naCarry = new int32_t[3 * newx + 3];
+ int32_t* naTemp;
+ int32_t nWeightX,nWeightY;
+ float fEndX;
+ int32_t nScale = (int32_t)(ACCURACY * xScale * yScale);
+
+ memset(naAccu, 0, sizeof(int32_t) * 3 * newx);
+ memset(naCarry, 0, sizeof(int32_t) * 3 * newx);
+
+ int32_t u, v = 0; // coordinates in dest image
+ float fEndY = yScale - 1.0f;
+ for (y = 0; y < head.biHeight; y++){
+ info.nProgress = (int32_t)(100*y/head.biHeight); //<Anatoly Ivasyuk>
+ if (info.nEscape) break;
+ pSource = info.pImage + y * info.dwEffWidth;
+ u = i = 0;
+ fEndX = xScale - 1.0f;
+ if ((float)y < fEndY) { // complete source row goes into dest row
+ for (x = 0; x < head.biWidth; x++){
+ if ((float)x < fEndX){ // complete source pixel goes into dest pixel
+ for (j = 0; j < 3; j++) naAccu[i + j] += (*pSource++) * ACCURACY;
+ } else { // source pixel is splitted for 2 dest pixels
+ nWeightX = (int32_t)(((float)x - fEndX) * ACCURACY);
+ for (j = 0; j < 3; j++){
+ naAccu[i] += (ACCURACY - nWeightX) * (*pSource);
+ naAccu[3 + i++] += nWeightX * (*pSource++);
+ }
+ fEndX += xScale;
+ u++;
+ }
+ }
+ } else { // source row is splitted for 2 dest rows
+ nWeightY = (int32_t)(((float)y - fEndY) * ACCURACY);
+ for (x = 0; x < head.biWidth; x++){
+ if ((float)x < fEndX){ // complete source pixel goes into 2 pixel
+ for (j = 0; j < 3; j++){
+ naAccu[i + j] += ((ACCURACY - nWeightY) * (*pSource));
+ naCarry[i + j] += nWeightY * (*pSource++);
+ }
+ } else { // source pixel is splitted for 4 dest pixels
+ nWeightX = (int32_t)(((float)x - fEndX) * ACCURACY);
+ for (j = 0; j < 3; j++) {
+ naAccu[i] += ((ACCURACY - nWeightY) * (ACCURACY - nWeightX)) * (*pSource) / ACCURACY;
+ *pDest++ = (uint8_t)(naAccu[i] / nScale);
+ naCarry[i] += (nWeightY * (ACCURACY - nWeightX) * (*pSource)) / ACCURACY;
+ naAccu[i + 3] += ((ACCURACY - nWeightY) * nWeightX * (*pSource)) / ACCURACY;
+ naCarry[i + 3] = (nWeightY * nWeightX * (*pSource)) / ACCURACY;
+ i++;
+ pSource++;
+ }
+ fEndX += xScale;
+ u++;
+ }
+ }
+ if (u < newx){ // possibly not completed due to rounding errors
+ for (j = 0; j < 3; j++) *pDest++ = (uint8_t)(naAccu[i++] / nScale);
+ }
+ naTemp = naCarry;
+ naCarry = naAccu;
+ naAccu = naTemp;
+ memset(naCarry, 0, sizeof(int32_t) * 3); // need only to set first pixel zero
+ pDest = newImage.info.pImage + (++v * newImage.info.dwEffWidth);
+ fEndY += yScale;
+ }
+ }
+ if (v < newy){ // possibly not completed due to rounding errors
+ for (i = 0; i < 3 * newx; i++) *pDest++ = (uint8_t)(naAccu[i] / nScale);
+ }
+ delete [] naAccu;
+ delete [] naCarry;
+ }
+ }
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()){
+ if (1 == mode){
+ newImage.AlphaCreate();
+ for(int32_t y=0; y<newy; y++){
+ fY = y * yScale;
+ for(int32_t x=0; x<newx; x++){
+ fX = x * xScale;
+ newImage.AlphaSet(x,y,AlphaGet((int32_t)fX,(int32_t)fY));
+ }
+ }
+ } else {
+ CxImage newAlpha;
+ AlphaSplit(&newAlpha);
+ newAlpha.Resample(newx, newy, mode);
+ newImage.AlphaSet(newAlpha);
+ }
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ //select the destination
+ if (iDst) iDst->Transfer(newImage);
+ else Transfer(newImage);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * New simpler resample. Adds new interpolation methods and simplifies code (using GetPixelColorInterpolated
+ * and GetAreaColorInterpolated). It also (unlike old method) interpolates alpha layer.
+ *
+ * \param newx, newy - size of resampled image
+ * \param inMethod - interpolation method to use (see comments at GetPixelColorInterpolated)
+ * If image size is being reduced, averaging is used instead (or simultaneously with) inMethod.
+ * \param ofMethod - what to replace outside pixels by (only significant for bordering pixels of enlarged image)
+ * \param iDst - pointer to destination CxImage or NULL.
+ * \param disableAveraging - force no averaging when shrinking images (Produces aliasing.
+ * You probably just want to leave this off...)
+ *
+ * \author ***bd*** 2.2004
+ */
+bool CxImage::Resample2(
+ int32_t newx, int32_t newy,
+ InterpolationMethod const inMethod,
+ OverflowMethod const ofMethod,
+ CxImage* const iDst,
+ bool const disableAveraging)
+{
+ if (newx<=0 || newy<=0 || !pDib) return false;
+
+ if (head.biWidth==newx && head.biHeight==newy) {
+ //image already correct size (just copy and return)
+ if (iDst) iDst->Copy(*this);
+ return true;
+ }//if
+
+ //calculate scale of new image (less than 1 for enlarge)
+ float xScale, yScale;
+ xScale = (float)head.biWidth / (float)newx;
+ yScale = (float)head.biHeight / (float)newy;
+
+ //create temporary destination image
+ CxImage newImage;
+ newImage.CopyInfo(*this);
+ newImage.Create(newx,newy,head.biBitCount,GetType());
+ newImage.SetPalette(GetPalette());
+ if (!newImage.IsValid()){
+ strcpy(info.szLastError,newImage.GetLastError());
+ return false;
+ }
+
+ //and alpha channel if required
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) newImage.AlphaCreate();
+ uint8_t *pxptra = 0; // destination alpha data
+#endif
+
+ float sX, sY; //source location
+ int32_t dX,dY; //destination pixel (int32_t value)
+ if ((xScale<=1 && yScale<=1) || disableAveraging) {
+ //image is being enlarged (or interpolation on demand)
+ if (!IsIndexed()) {
+ //RGB24 image (optimized version with direct writes)
+ RGBQUAD q; //pixel colour
+ uint8_t *pxptr; //pointer to destination pixel
+ for(dY=0; dY<newy; dY++){
+ info.nProgress = (int32_t)(100*dY/newy);
+ if (info.nEscape) break;
+ sY = (dY + 0.5f) * yScale - 0.5f;
+ pxptr=(uint8_t*)(newImage.BlindGetPixelPointer(0,dY));
+#if CXIMAGE_SUPPORT_ALPHA
+ pxptra=newImage.AlphaGetPointer(0,dY);
+#endif
+ for(dX=0; dX<newx; dX++){
+ sX = (dX + 0.5f) * xScale - 0.5f;
+ q=GetPixelColorInterpolated(sX,sY,inMethod,ofMethod,0);
+ *pxptr++=q.rgbBlue;
+ *pxptr++=q.rgbGreen;
+ *pxptr++=q.rgbRed;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pxptra) *pxptra++=q.rgbReserved;
+#endif
+ }//for dX
+ }//for dY
+ } else {
+ //enlarge paletted image. Slower method.
+ for(dY=0; dY<newy; dY++){
+ info.nProgress = (int32_t)(100*dY/newy);
+ if (info.nEscape) break;
+ sY = (dY + 0.5f) * yScale - 0.5f;
+ for(dX=0; dX<newx; dX++){
+ sX = (dX + 0.5f) * xScale - 0.5f;
+ newImage.SetPixelColor(dX,dY,GetPixelColorInterpolated(sX,sY,inMethod,ofMethod,0),true);
+ }//for x
+ }//for y
+ }//if
+ } else {
+ //image size is being reduced (averaging enabled)
+ for(dY=0; dY<newy; dY++){
+ info.nProgress = (int32_t)(100*dY/newy); if (info.nEscape) break;
+ sY = (dY+0.5f) * yScale - 0.5f;
+ for(dX=0; dX<newx; dX++){
+ sX = (dX+0.5f) * xScale - 0.5f;
+ newImage.SetPixelColor(dX,dY,GetAreaColorInterpolated(sX, sY, xScale, yScale, inMethod, ofMethod,0),true);
+ }//for x
+ }//for y
+ }//if
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid() && pxptra == 0){
+ for(int32_t y=0; y<newy; y++){
+ dY = (int32_t)(y * yScale);
+ for(int32_t x=0; x<newx; x++){
+ dX = (int32_t)(x * xScale);
+ newImage.AlphaSet(x,y,AlphaGet(dX,dY));
+ }
+ }
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ //copy new image to the destination
+ if (iDst)
+ iDst->Transfer(newImage);
+ else
+ Transfer(newImage);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Reduces the number of bits per pixel to nbit (1, 4 or 8).
+ * ppal points to a valid palette for the final image; if not supplied the function will use a standard palette.
+ * ppal is not necessary for reduction to 1 bpp.
+ */
+bool CxImage::DecreaseBpp(uint32_t nbit, bool errordiffusion, RGBQUAD* ppal, uint32_t clrimportant)
+{
+ if (!pDib) return false;
+ if (head.biBitCount < nbit){
+ strcpy(info.szLastError,"DecreaseBpp: target BPP greater than source BPP");
+ return false;
+ }
+ if (head.biBitCount == nbit){
+ if (clrimportant==0) return true;
+ if (head.biClrImportant && (head.biClrImportant<clrimportant)) return true;
+ }
+
+ int32_t er,eg,eb;
+ RGBQUAD c,ce;
+
+ CxImage tmp;
+ tmp.CopyInfo(*this);
+ tmp.Create(head.biWidth,head.biHeight,(uint16_t)nbit,info.dwType);
+ if (clrimportant) tmp.SetClrImportant(clrimportant);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+#if CXIMAGE_SUPPORT_SELECTION
+ tmp.SelectionCopy(*this);
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+#if CXIMAGE_SUPPORT_ALPHA
+ tmp.AlphaCopy(*this);
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ if (ppal) {
+ if (clrimportant) {
+ tmp.SetPalette(ppal,clrimportant);
+ } else {
+ tmp.SetPalette(ppal,1<<tmp.head.biBitCount);
+ }
+ } else {
+ tmp.SetStdPalette();
+ }
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ if (info.nEscape) break;
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ for (int32_t x=0;x<head.biWidth;x++){
+ if (!errordiffusion){
+ tmp.BlindSetPixelColor(x,y,BlindGetPixelColor(x,y));
+ } else {
+ c = BlindGetPixelColor(x,y);
+ tmp.BlindSetPixelColor(x,y,c);
+
+ ce = tmp.BlindGetPixelColor(x,y);
+ er=(int32_t)c.rgbRed - (int32_t)ce.rgbRed;
+ eg=(int32_t)c.rgbGreen - (int32_t)ce.rgbGreen;
+ eb=(int32_t)c.rgbBlue - (int32_t)ce.rgbBlue;
+
+ c = GetPixelColor(x+1,y);
+ c.rgbRed = (uint8_t)min(255L,max(0L,(int32_t)c.rgbRed + ((er*7)/16)));
+ c.rgbGreen = (uint8_t)min(255L,max(0L,(int32_t)c.rgbGreen + ((eg*7)/16)));
+ c.rgbBlue = (uint8_t)min(255L,max(0L,(int32_t)c.rgbBlue + ((eb*7)/16)));
+ SetPixelColor(x+1,y,c);
+ int32_t coeff=1;
+ for(int32_t i=-1; i<2; i++){
+ switch(i){
+ case -1:
+ coeff=2; break;
+ case 0:
+ coeff=4; break;
+ case 1:
+ coeff=1; break;
+ }
+ c = GetPixelColor(x+i,y+1);
+ c.rgbRed = (uint8_t)min(255L,max(0L,(int32_t)c.rgbRed + ((er * coeff)/16)));
+ c.rgbGreen = (uint8_t)min(255L,max(0L,(int32_t)c.rgbGreen + ((eg * coeff)/16)));
+ c.rgbBlue = (uint8_t)min(255L,max(0L,(int32_t)c.rgbBlue + ((eb * coeff)/16)));
+ SetPixelColor(x+i,y+1,c);
+ }
+ }
+ }
+ }
+
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Converts the image to B&W using the desired method :
+ * - 0 = Floyd-Steinberg
+ * - 1 = Ordered-Dithering (4x4)
+ * - 2 = Burkes
+ * - 3 = Stucki
+ * - 4 = Jarvis-Judice-Ninke
+ * - 5 = Sierra
+ * - 6 = Stevenson-Arce
+ * - 7 = Bayer (4x4 ordered dithering)
+ * - 8 = Bayer (8x8 ordered dithering)
+ * - 9 = Bayer (16x16 ordered dithering)
+ */
+bool CxImage::Dither(int32_t method)
+{
+ if (!pDib) return false;
+ if (head.biBitCount == 1) return true;
+
+ GrayScale();
+
+ CxImage tmp;
+ tmp.CopyInfo(*this);
+ tmp.Create(head.biWidth, head.biHeight, 1, info.dwType);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+#if CXIMAGE_SUPPORT_SELECTION
+ tmp.SelectionCopy(*this);
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+#if CXIMAGE_SUPPORT_ALPHA
+ tmp.AlphaCopy(*this);
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ switch (method){
+ case 1:
+ {
+ // Multi-Level Ordered-Dithering by Kenny Hoff (Oct. 12, 1995)
+ #define dth_NumRows 4
+ #define dth_NumCols 4
+ #define dth_NumIntensityLevels 2
+ #define dth_NumRowsLessOne (dth_NumRows-1)
+ #define dth_NumColsLessOne (dth_NumCols-1)
+ #define dth_RowsXCols (dth_NumRows*dth_NumCols)
+ #define dth_MaxIntensityVal 255
+ #define dth_MaxDitherIntensityVal (dth_NumRows*dth_NumCols*(dth_NumIntensityLevels-1))
+
+ int32_t DitherMatrix[dth_NumRows][dth_NumCols] = {{0,8,2,10}, {12,4,14,6}, {3,11,1,9}, {15,7,13,5} };
+
+ uint8_t Intensity[dth_NumIntensityLevels] = { 0,1 }; // 2 LEVELS B/W
+ //uint8_t Intensity[NumIntensityLevels] = { 0,255 }; // 2 LEVELS
+ //uint8_t Intensity[NumIntensityLevels] = { 0,127,255 }; // 3 LEVELS
+ //uint8_t Intensity[NumIntensityLevels] = { 0,85,170,255 }; // 4 LEVELS
+ //uint8_t Intensity[NumIntensityLevels] = { 0,63,127,191,255 }; // 5 LEVELS
+ //uint8_t Intensity[NumIntensityLevels] = { 0,51,102,153,204,255 }; // 6 LEVELS
+ //uint8_t Intensity[NumIntensityLevels] = { 0,42,85,127,170,213,255 }; // 7 LEVELS
+ //uint8_t Intensity[NumIntensityLevels] = { 0,36,73,109,145,182,219,255 }; // 8 LEVELS
+ int32_t DitherIntensity, DitherMatrixIntensity, Offset, DeviceIntensity;
+ uint8_t DitherValue;
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+
+ DeviceIntensity = BlindGetPixelIndex(x,y);
+ DitherIntensity = DeviceIntensity*dth_MaxDitherIntensityVal/dth_MaxIntensityVal;
+ DitherMatrixIntensity = DitherIntensity % dth_RowsXCols;
+ Offset = DitherIntensity / dth_RowsXCols;
+ if (DitherMatrix[y&dth_NumRowsLessOne][x&dth_NumColsLessOne] < DitherMatrixIntensity)
+ DitherValue = Intensity[1+Offset];
+ else
+ DitherValue = Intensity[0+Offset];
+
+ tmp.BlindSetPixelIndex(x,y,DitherValue);
+ }
+ }
+ break;
+ }
+ case 2:
+ {
+ //Burkes error diffusion (Thanks to Franco Gerevini)
+ int32_t TotalCoeffSum = 32;
+ int32_t error, nlevel, coeff=1;
+ uint8_t level;
+
+ for (int32_t y = 0; y < head.biHeight; y++) {
+ info.nProgress = (int32_t)(100 * y / head.biHeight);
+ if (info.nEscape)
+ break;
+ for (int32_t x = 0; x < head.biWidth; x++) {
+ level = BlindGetPixelIndex(x, y);
+ if (level > 128) {
+ tmp.SetPixelIndex(x, y, 1);
+ error = level - 255;
+ } else {
+ tmp.SetPixelIndex(x, y, 0);
+ error = level;
+ }
+
+ nlevel = GetPixelIndex(x + 1, y) + (error * 8) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + 1, y, level);
+ nlevel = GetPixelIndex(x + 2, y) + (error * 4) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + 2, y, level);
+ int32_t i;
+ for (i = -2; i < 3; i++) {
+ switch (i) {
+ case -2:
+ coeff = 2;
+ break;
+ case -1:
+ coeff = 4;
+ break;
+ case 0:
+ coeff = 8;
+ break;
+ case 1:
+ coeff = 4;
+ break;
+ case 2:
+ coeff = 2;
+ break;
+ }
+ nlevel = GetPixelIndex(x + i, y + 1) + (error * coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + i, y + 1, level);
+ }
+ }
+ }
+ break;
+ }
+ case 3:
+ {
+ //Stucki error diffusion (Thanks to Franco Gerevini)
+ int32_t TotalCoeffSum = 42;
+ int32_t error, nlevel, coeff=1;
+ uint8_t level;
+
+ for (int32_t y = 0; y < head.biHeight; y++) {
+ info.nProgress = (int32_t)(100 * y / head.biHeight);
+ if (info.nEscape)
+ break;
+ for (int32_t x = 0; x < head.biWidth; x++) {
+ level = BlindGetPixelIndex(x, y);
+ if (level > 128) {
+ tmp.SetPixelIndex(x, y, 1);
+ error = level - 255;
+ } else {
+ tmp.SetPixelIndex(x, y, 0);
+ error = level;
+ }
+
+ nlevel = GetPixelIndex(x + 1, y) + (error * 8) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + 1, y, level);
+ nlevel = GetPixelIndex(x + 2, y) + (error * 4) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + 2, y, level);
+ int32_t i;
+ for (i = -2; i < 3; i++) {
+ switch (i) {
+ case -2:
+ coeff = 2;
+ break;
+ case -1:
+ coeff = 4;
+ break;
+ case 0:
+ coeff = 8;
+ break;
+ case 1:
+ coeff = 4;
+ break;
+ case 2:
+ coeff = 2;
+ break;
+ }
+ nlevel = GetPixelIndex(x + i, y + 1) + (error * coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + i, y + 1, level);
+ }
+ for (i = -2; i < 3; i++) {
+ switch (i) {
+ case -2:
+ coeff = 1;
+ break;
+ case -1:
+ coeff = 2;
+ break;
+ case 0:
+ coeff = 4;
+ break;
+ case 1:
+ coeff = 2;
+ break;
+ case 2:
+ coeff = 1;
+ break;
+ }
+ nlevel = GetPixelIndex(x + i, y + 2) + (error * coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + i, y + 2, level);
+ }
+ }
+ }
+ break;
+ }
+ case 4:
+ {
+ //Jarvis, Judice and Ninke error diffusion (Thanks to Franco Gerevini)
+ int32_t TotalCoeffSum = 48;
+ int32_t error, nlevel, coeff=1;
+ uint8_t level;
+
+ for (int32_t y = 0; y < head.biHeight; y++) {
+ info.nProgress = (int32_t)(100 * y / head.biHeight);
+ if (info.nEscape)
+ break;
+ for (int32_t x = 0; x < head.biWidth; x++) {
+ level = BlindGetPixelIndex(x, y);
+ if (level > 128) {
+ tmp.SetPixelIndex(x, y, 1);
+ error = level - 255;
+ } else {
+ tmp.SetPixelIndex(x, y, 0);
+ error = level;
+ }
+
+ nlevel = GetPixelIndex(x + 1, y) + (error * 7) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + 1, y, level);
+ nlevel = GetPixelIndex(x + 2, y) + (error * 5) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + 2, y, level);
+ int32_t i;
+ for (i = -2; i < 3; i++) {
+ switch (i) {
+ case -2:
+ coeff = 3;
+ break;
+ case -1:
+ coeff = 5;
+ break;
+ case 0:
+ coeff = 7;
+ break;
+ case 1:
+ coeff = 5;
+ break;
+ case 2:
+ coeff = 3;
+ break;
+ }
+ nlevel = GetPixelIndex(x + i, y + 1) + (error * coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + i, y + 1, level);
+ }
+ for (i = -2; i < 3; i++) {
+ switch (i) {
+ case -2:
+ coeff = 1;
+ break;
+ case -1:
+ coeff = 3;
+ break;
+ case 0:
+ coeff = 5;
+ break;
+ case 1:
+ coeff = 3;
+ break;
+ case 2:
+ coeff = 1;
+ break;
+ }
+ nlevel = GetPixelIndex(x + i, y + 2) + (error * coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + i, y + 2, level);
+ }
+ }
+ }
+ break;
+ }
+ case 5:
+ {
+ //Sierra error diffusion (Thanks to Franco Gerevini)
+ int32_t TotalCoeffSum = 32;
+ int32_t error, nlevel, coeff=1;
+ uint8_t level;
+
+ for (int32_t y = 0; y < head.biHeight; y++) {
+ info.nProgress = (int32_t)(100 * y / head.biHeight);
+ if (info.nEscape)
+ break;
+ for (int32_t x = 0; x < head.biWidth; x++) {
+ level = BlindGetPixelIndex(x, y);
+ if (level > 128) {
+ tmp.SetPixelIndex(x, y, 1);
+ error = level - 255;
+ } else {
+ tmp.SetPixelIndex(x, y, 0);
+ error = level;
+ }
+
+ nlevel = GetPixelIndex(x + 1, y) + (error * 5) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + 1, y, level);
+ nlevel = GetPixelIndex(x + 2, y) + (error * 3) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + 2, y, level);
+ int32_t i;
+ for (i = -2; i < 3; i++) {
+ switch (i) {
+ case -2:
+ coeff = 2;
+ break;
+ case -1:
+ coeff = 4;
+ break;
+ case 0:
+ coeff = 5;
+ break;
+ case 1:
+ coeff = 4;
+ break;
+ case 2:
+ coeff = 2;
+ break;
+ }
+ nlevel = GetPixelIndex(x + i, y + 1) + (error * coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + i, y + 1, level);
+ }
+ for (i = -1; i < 2; i++) {
+ switch (i) {
+ case -1:
+ coeff = 2;
+ break;
+ case 0:
+ coeff = 3;
+ break;
+ case 1:
+ coeff = 2;
+ break;
+ }
+ nlevel = GetPixelIndex(x + i, y + 2) + (error * coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(x + i, y + 2, level);
+ }
+ }
+ }
+ break;
+ }
+ case 6:
+ {
+ //Stevenson and Arce error diffusion (Thanks to Franco Gerevini)
+ int32_t TotalCoeffSum = 200;
+ int32_t error, nlevel;
+ uint8_t level;
+
+ for (int32_t y = 0; y < head.biHeight; y++) {
+ info.nProgress = (int32_t)(100 * y / head.biHeight);
+ if (info.nEscape)
+ break;
+ for (int32_t x = 0; x < head.biWidth; x++) {
+ level = BlindGetPixelIndex(x, y);
+ if (level > 128) {
+ tmp.SetPixelIndex(x, y, 1);
+ error = level - 255;
+ } else {
+ tmp.SetPixelIndex(x, y, 0);
+ error = level;
+ }
+
+ int32_t tmp_index_x = x + 2;
+ int32_t tmp_index_y = y;
+ int32_t tmp_coeff = 32;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x - 3;
+ tmp_index_y = y + 1;
+ tmp_coeff = 12;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x - 1;
+ tmp_coeff = 26;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x + 1;
+ tmp_coeff = 30;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x + 3;
+ tmp_coeff = 16;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x - 2;
+ tmp_index_y = y + 2;
+ tmp_coeff = 12;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x;
+ tmp_coeff = 26;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x + 2;
+ tmp_coeff = 12;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x - 3;
+ tmp_index_y = y + 3;
+ tmp_coeff = 5;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x - 1;
+ tmp_coeff = 12;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x + 1;
+ tmp_coeff = 12;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+
+ tmp_index_x = x + 3;
+ tmp_coeff = 5;
+ nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+ level = (uint8_t)min(255, max(0, (int32_t)nlevel));
+ SetPixelIndex(tmp_index_x, tmp_index_y, level);
+ }
+ }
+ break;
+ }
+ case 7:
+ {
+ // Bayer ordered dither
+ int32_t order = 4;
+ //create Bayer matrix
+ if (order>4) order = 4;
+ int32_t size = (1 << (2*order));
+ uint8_t* Bmatrix = (uint8_t*) malloc(size * sizeof(uint8_t));
+ for(int32_t i = 0; i < size; i++) {
+ int32_t n = order;
+ int32_t x = i / n;
+ int32_t y = i % n;
+ int32_t dither = 0;
+ while (n-- > 0){
+ dither = (((dither<<1)|((x&1) ^ (y&1)))<<1) | (y&1);
+ x >>= 1;
+ y >>= 1;
+ }
+ Bmatrix[i] = (uint8_t)(dither);
+ }
+
+ int32_t scale = max(0,(8-2*order));
+ int32_t level;
+ for (int32_t y=0;y<head.biHeight;y++){
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+ level = BlindGetPixelIndex(x,y) >> scale;
+ if(level > Bmatrix[ (x % order) + order * (y % order) ]){
+ tmp.SetPixelIndex(x,y,1);
+ } else {
+ tmp.SetPixelIndex(x,y,0);
+ }
+ }
+ }
+
+ free(Bmatrix);
+
+ break;
+ }
+ case 8:
+ {
+ // 8x8 Bayer ordered dither
+ int32_t const pattern8x8[8][8] = {
+ { 0, 32, 8, 40, 2, 34, 10, 42}, /* 8x8 Bayer ordered dithering */
+ {48, 16, 56, 24, 50, 18, 58, 26}, /* pattern. Each input pixel */
+ {12, 44, 4, 36, 14, 46, 6, 38}, /* is scaled to the 0..63 range */
+ {60, 28, 52, 20, 62, 30, 54, 22}, /* before looking in this table */
+ { 3, 35, 11, 43, 1, 33, 9, 41}, /* to determine the action. */
+ {51, 19, 59, 27, 49, 17, 57, 25},
+ {15, 47, 7, 39, 13, 45, 5, 37},
+ {63, 31, 55, 23, 61, 29, 53, 21} };
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+ int32_t level = BlindGetPixelIndex(x,y) >> 2;
+ if(level && level >= pattern8x8[x & 7][y & 7]){
+ tmp.SetPixelIndex(x,y,1);
+ } else {
+ tmp.SetPixelIndex(x,y,0);
+ }
+ }
+ }
+ break;
+ }
+ case 9:
+ {
+ // 16x16 Bayer ordered dither
+ int32_t const pattern16x16[16][16] = {
+ { 1,235, 59,219, 15,231, 55,215, 2,232, 56,216, 12,228, 52,212},
+ { 129, 65,187,123,143, 79,183,119,130, 66,184,120,140, 76,180,116},
+ { 33,193, 17,251, 47,207, 31,247, 34,194, 18,248, 44,204, 28,244},
+ { 161, 97,145, 81,175,111,159, 95,162, 98,146, 82,172,108,156, 92},
+ { 9,225, 49,209, 5,239, 63,223, 10,226, 50,210, 6,236, 60,220},
+ { 137, 73,177,113,133, 69,191,127,138, 74,178,114,134, 70,188,124},
+ { 41,201, 25,241, 37,197, 21,255, 42,202, 26,242, 38,198, 22,252},
+ { 169,105,153, 89,165,101,149, 85,170,106,154, 90,166,102,150, 86},
+ { 3,233, 57,217, 13,229, 53,213, 0,234, 58,218, 14,230, 54,214},
+ { 131, 67,185,121,141, 77,181,117,128, 64,186,122,142, 78,182,118},
+ { 35,195, 19,249, 45,205, 29,245, 32,192, 16,250, 46,206, 30,246},
+ { 163, 99,147, 83,173,109,157, 93,160, 96,144, 80,174,110,158, 94},
+ { 11,227, 51,211, 7,237, 61,221, 8,224, 48,208, 4,238, 62,222},
+ { 139, 75,179,115,135, 71,189,125,136, 72,176,112,132, 68,190,126},
+ { 43,203, 27,243, 39,199, 23,253, 40,200, 24,240, 36,196, 20,254},
+ { 171,107,155, 91,167,103,151, 87,168,104,152, 88,164,100,148, 84}
+ };
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+ if (BlindGetPixelIndex(x,y) > pattern16x16[x & 15][y & 15]){
+ tmp.SetPixelIndex(x,y,1);
+ } else {
+ tmp.SetPixelIndex(x,y,0);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ // Floyd-Steinberg error diffusion (Thanks to Steve McMahon)
+ int32_t error,nlevel,coeff=1;
+ uint8_t level;
+
+ for (int32_t y=0;y<head.biHeight;y++){
+ info.nProgress = (int32_t)(100*y/head.biHeight);
+ if (info.nEscape) break;
+ for (int32_t x=0;x<head.biWidth;x++){
+
+ level = BlindGetPixelIndex(x,y);
+ if (level > 128){
+ tmp.SetPixelIndex(x,y,1);
+ error = level-255;
+ } else {
+ tmp.SetPixelIndex(x,y,0);
+ error = level;
+ }
+
+ nlevel = GetPixelIndex(x+1,y) + (error * 7)/16;
+ level = (uint8_t)min(255,max(0,(int32_t)nlevel));
+ SetPixelIndex(x+1,y,level);
+ for(int32_t i=-1; i<2; i++){
+ switch(i){
+ case -1:
+ coeff=3; break;
+ case 0:
+ coeff=5; break;
+ case 1:
+ coeff=1; break;
+ }
+ nlevel = GetPixelIndex(x+i,y+1) + (error * coeff)/16;
+ level = (uint8_t)min(255,max(0,(int32_t)nlevel));
+ SetPixelIndex(x+i,y+1,level);
+ }
+ }
+ }
+ }
+ }
+
+ tmp.SetPaletteColor(0,0,0,0);
+ tmp.SetPaletteColor(1,255,255,255);
+ Transfer(tmp);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * CropRotatedRectangle
+ * \param topx,topy : topmost and leftmost point of the rectangle
+ (topmost, and if there are 2 topmost points, the left one)
+ * \param width : size of the right hand side of rect, from (topx,topy) roundwalking clockwise
+ * \param height : size of the left hand side of rect, from (topx,topy) roundwalking clockwise
+ * \param angle : angle of the right hand side of rect, from (topx,topy)
+ * \param iDst : pointer to destination image (if 0, this image is modified)
+ * \author [VATI]
+ */
+bool CxImage::CropRotatedRectangle( int32_t topx, int32_t topy, int32_t width, int32_t height, float angle, CxImage* iDst)
+{
+ if (!pDib) return false;
+
+
+ int32_t startx,starty,endx,endy;
+ double cos_angle = cos(angle/*/57.295779513082320877*/);
+ double sin_angle = sin(angle/*/57.295779513082320877*/);
+
+ // if there is nothing special, call the original Crop():
+ if ( fabs(angle)<0.0002 )
+ return Crop( topx, topy, topx+width, topy+height, iDst);
+
+ startx = min(topx, topx - (int32_t)(sin_angle*(double)height));
+ endx = topx + (int32_t)(cos_angle*(double)width);
+ endy = topy + (int32_t)(cos_angle*(double)height + sin_angle*(double)width);
+ // check: corners of the rectangle must be inside
+ if ( IsInside( startx, topy )==false ||
+ IsInside( endx, endy ) == false )
+ return false;
+
+ // first crop to bounding rectangle
+ CxImage tmp(*this, true, false, true);
+ // tmp.Copy(*this, true, false, true);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+ if (!tmp.Crop( startx, topy, endx, endy)){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ // the midpoint of the image now became the same as the midpoint of the rectangle
+ // rotate new image with minus angle amount
+ if ( false == tmp.Rotate( (float)(-angle*57.295779513082320877) ) ) // Rotate expects angle in degrees
+ return false;
+
+ // crop rotated image to the original selection rectangle
+ endx = (tmp.head.biWidth+width)/2;
+ startx = (tmp.head.biWidth-width)/2;
+ starty = (tmp.head.biHeight+height)/2;
+ endy = (tmp.head.biHeight-height)/2;
+ if ( false == tmp.Crop( startx, starty, endx, endy ) )
+ return false;
+
+ if (iDst) iDst->Transfer(tmp);
+ else Transfer(tmp);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::Crop(const RECT& rect, CxImage* iDst)
+{
+ return Crop(rect.left, rect.top, rect.right, rect.bottom, iDst);
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::Crop(int32_t left, int32_t top, int32_t right, int32_t bottom, CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ int32_t startx = max(0L,min(left,head.biWidth));
+ int32_t endx = max(0L,min(right,head.biWidth));
+ int32_t starty = head.biHeight - max(0L,min(top,head.biHeight));
+ int32_t endy = head.biHeight - max(0L,min(bottom,head.biHeight));
+
+ if (startx==endx || starty==endy) return false;
+
+ if (startx>endx) {int32_t tmp=startx; startx=endx; endx=tmp;}
+ if (starty>endy) {int32_t tmp=starty; starty=endy; endy=tmp;}
+
+ CxImage tmp;
+ tmp.CopyInfo(*this);
+ tmp.Create(endx-startx,endy-starty,head.biBitCount,info.dwType);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ tmp.SetPalette(GetPalette(),head.biClrUsed);
+ tmp.info.nBkgndIndex = info.nBkgndIndex;
+ tmp.info.nBkgndColor = info.nBkgndColor;
+
+ switch (head.biBitCount) {
+ case 1:
+ case 4:
+ {
+ for(int32_t y=starty, yd=0; y<endy; y++, yd++){
+ info.nProgress = (int32_t)(100*(y-starty)/(endy-starty)); //<Anatoly Ivasyuk>
+ for(int32_t x=startx, xd=0; x<endx; x++, xd++){
+ tmp.SetPixelIndex(xd,yd,GetPixelIndex(x,y));
+ }
+ }
+ break;
+ }
+ case 8:
+ case 24:
+ {
+ int32_t linelen = tmp.head.biWidth * tmp.head.biBitCount >> 3;
+ uint8_t* pDest = tmp.info.pImage;
+ uint8_t* pSrc = info.pImage + starty * info.dwEffWidth + (startx*head.biBitCount >> 3);
+ for(int32_t y=starty; y<endy; y++){
+ info.nProgress = (int32_t)(100*(y-starty)/(endy-starty)); //<Anatoly Ivasyuk>
+ memcpy(pDest,pSrc,linelen);
+ pDest+=tmp.info.dwEffWidth;
+ pSrc+=info.dwEffWidth;
+ }
+ }
+ }
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()){ //<oboolo>
+ tmp.AlphaCreate();
+ if (!tmp.AlphaIsValid()) return false;
+ uint8_t* pDest = tmp.pAlpha;
+ uint8_t* pSrc = pAlpha + startx + starty*head.biWidth;
+ for (int32_t y=starty; y<endy; y++){
+ memcpy(pDest,pSrc,endx-startx);
+ pDest+=tmp.head.biWidth;
+ pSrc+=head.biWidth;
+ }
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ //select the destination
+ if (iDst) iDst->Transfer(tmp);
+ else Transfer(tmp);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \param xgain, ygain : can be from 0 to 1.
+ * \param xpivot, ypivot : is the center of the transformation.
+ * \param bEnableInterpolation : if true, enables bilinear interpolation.
+ * \return true if everything is ok
+ */
+bool CxImage::Skew(float xgain, float ygain, int32_t xpivot, int32_t ypivot, bool bEnableInterpolation)
+{
+ if (!pDib) return false;
+ float nx,ny;
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t xmin,xmax,ymin,ymax;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ nx = x + (xgain*(y - ypivot));
+ ny = y + (ygain*(x - xpivot));
+#if CXIMAGE_SUPPORT_INTERPOLATION
+ if (bEnableInterpolation){
+ tmp.SetPixelColor(x,y,GetPixelColorInterpolated(nx, ny, CxImage::IM_BILINEAR, CxImage::OM_BACKGROUND),true);
+ } else
+#endif //CXIMAGE_SUPPORT_INTERPOLATION
+ {
+ if (head.biClrUsed==0){
+ tmp.SetPixelColor(x,y,GetPixelColor((int32_t)nx,(int32_t)ny));
+ } else {
+ tmp.SetPixelIndex(x,y,GetPixelIndex((int32_t)nx,(int32_t)ny));
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ tmp.AlphaSet(x,y,AlphaGet((int32_t)nx,(int32_t)ny));
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Expands the borders.
+ * \param left, top, right, bottom = additional dimensions, should be greater than 0.
+ * \param canvascolor = border color. canvascolor.rgbReserved will set the alpha channel (if any) in the border.
+ * \param iDst = pointer to destination image (if it's 0, this image is modified)
+ * \return true if everything is ok
+ * \author [Colin Urquhart]; changes [DP]
+ */
+bool CxImage::Expand(int32_t left, int32_t top, int32_t right, int32_t bottom, RGBQUAD canvascolor, CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ if ((left < 0) || (right < 0) || (bottom < 0) || (top < 0)) return false;
+
+ int32_t newWidth = head.biWidth + left + right;
+ int32_t newHeight = head.biHeight + top + bottom;
+
+ right = left + head.biWidth - 1;
+ top = bottom + head.biHeight - 1;
+
+ CxImage tmp;
+ tmp.CopyInfo(*this);
+ if (!tmp.Create(newWidth, newHeight, head.biBitCount, info.dwType)){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ tmp.SetPalette(GetPalette(),head.biClrUsed);
+
+ switch (head.biBitCount) {
+ case 1:
+ case 4:
+ {
+ uint8_t pixel = tmp.GetNearestIndex(canvascolor);
+ for(int32_t y=0; y < newHeight; y++){
+ info.nProgress = (int32_t)(100*y/newHeight);
+ for(int32_t x=0; x < newWidth; x++){
+ if ((y < bottom) || (y > top) || (x < left) || (x > right)) {
+ tmp.SetPixelIndex(x,y, pixel);
+ } else {
+ tmp.SetPixelIndex(x,y,GetPixelIndex(x-left,y-bottom));
+ }
+ }
+ }
+ break;
+ }
+ case 8:
+ case 24:
+ {
+ if (head.biBitCount == 8) {
+ uint8_t pixel = tmp.GetNearestIndex( canvascolor);
+ memset(tmp.info.pImage, pixel, + (tmp.info.dwEffWidth * newHeight));
+ } else {
+ for (int32_t y = 0; y < newHeight; ++y) {
+ uint8_t *pDest = tmp.info.pImage + (y * tmp.info.dwEffWidth);
+ for (int32_t x = 0; x < newWidth; ++x) {
+ *pDest++ = canvascolor.rgbBlue;
+ *pDest++ = canvascolor.rgbGreen;
+ *pDest++ = canvascolor.rgbRed;
+ }
+ }
+ }
+
+ uint8_t* pDest = tmp.info.pImage + (tmp.info.dwEffWidth * bottom) + (left*(head.biBitCount >> 3));
+ uint8_t* pSrc = info.pImage;
+ for(int32_t y=bottom; y <= top; y++){
+ info.nProgress = (int32_t)(100*y/(1 + top - bottom));
+ memcpy(pDest,pSrc,(head.biBitCount >> 3) * (right - left + 1));
+ pDest+=tmp.info.dwEffWidth;
+ pSrc+=info.dwEffWidth;
+ }
+ }
+ }
+
+#if CXIMAGE_SUPPORT_SELECTION
+ if (SelectionIsValid()){
+ if (!tmp.SelectionCreate())
+ return false;
+ uint8_t* pSrc = SelectionGetPointer();
+ uint8_t* pDst = tmp.SelectionGetPointer(left,bottom);
+ for(int32_t y=bottom; y <= top; y++){
+ memcpy(pDst,pSrc, (right - left + 1));
+ pSrc+=head.biWidth;
+ pDst+=tmp.head.biWidth;
+ }
+ tmp.info.rSelectionBox.left = info.rSelectionBox.left + left;
+ tmp.info.rSelectionBox.right = info.rSelectionBox.right + left;
+ tmp.info.rSelectionBox.top = info.rSelectionBox.top + bottom;
+ tmp.info.rSelectionBox.bottom = info.rSelectionBox.bottom + bottom;
+ }
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()){
+ if (!tmp.AlphaCreate())
+ return false;
+ tmp.AlphaSet(canvascolor.rgbReserved);
+ uint8_t* pSrc = AlphaGetPointer();
+ uint8_t* pDst = tmp.AlphaGetPointer(left,bottom);
+ for(int32_t y=bottom; y <= top; y++){
+ memcpy(pDst,pSrc, (right - left + 1));
+ pSrc+=head.biWidth;
+ pDst+=tmp.head.biWidth;
+ }
+ }
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ //select the destination
+ if (iDst) iDst->Transfer(tmp);
+ else Transfer(tmp);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::Expand(int32_t newx, int32_t newy, RGBQUAD canvascolor, CxImage* iDst)
+{
+ //thanks to <Colin Urquhart>
+
+ if (!pDib) return false;
+
+ if ((newx < head.biWidth) || (newy < head.biHeight)) return false;
+
+ int32_t nAddLeft = (newx - head.biWidth) / 2;
+ int32_t nAddTop = (newy - head.biHeight) / 2;
+
+ return Expand(nAddLeft, nAddTop, newx - (head.biWidth + nAddLeft), newy - (head.biHeight + nAddTop), canvascolor, iDst);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Resamples the image with the correct aspect ratio, and fills the borders.
+ * \param newx, newy = thumbnail size.
+ * \param canvascolor = border color.
+ * \param iDst = pointer to destination image (if it's 0, this image is modified).
+ * \return true if everything is ok.
+ * \author [Colin Urquhart]
+ */
+bool CxImage::Thumbnail(int32_t newx, int32_t newy, RGBQUAD canvascolor, CxImage* iDst)
+{
+ if (!pDib) return false;
+
+ if ((newx <= 0) || (newy <= 0)) return false;
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ // determine whether we need to shrink the image
+ if ((head.biWidth > newx) || (head.biHeight > newy)) {
+ float fScale;
+ float fAspect = (float) newx / (float) newy;
+ if (fAspect * head.biHeight > head.biWidth) {
+ fScale = (float) newy / head.biHeight;
+ } else {
+ fScale = (float) newx / head.biWidth;
+ }
+ tmp.Resample((int32_t) (fScale * head.biWidth), (int32_t) (fScale * head.biHeight), 0);
+ }
+
+ // expand the frame
+ tmp.Expand(newx, newy, canvascolor);
+
+ //select the destination
+ if (iDst) iDst->Transfer(tmp);
+ else Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Perform circle_based transformations.
+ * \param type - for different transformations
+ * - 0 for normal (proturberant) FishEye
+ * - 1 for reverse (concave) FishEye
+ * - 2 for Swirle
+ * - 3 for Cilinder mirror
+ * - 4 for bathroom
+ *
+ * \param rmax - effect radius. If 0, the whole image is processed
+ * \param Koeff - only for swirle
+ * \author Arkadiy Olovyannikov ark(at)msun(dot)ru
+ */
+bool CxImage::CircleTransform(int32_t type,int32_t rmax,float Koeff)
+{
+ if (!pDib) return false;
+
+ int32_t nx,ny;
+ double angle,radius,rnew;
+
+ CxImage tmp(*this);
+ if (!tmp.IsValid()){
+ strcpy(info.szLastError,tmp.GetLastError());
+ return false;
+ }
+
+ int32_t xmin,xmax,ymin,ymax,xmid,ymid;
+ if (pSelection){
+ xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;
+ ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;
+ } else {
+ xmin = ymin = 0;
+ xmax = head.biWidth; ymax=head.biHeight;
+ }
+
+ xmid = (int32_t) (tmp.GetWidth()/2);
+ ymid = (int32_t) (tmp.GetHeight()/2);
+
+ if (!rmax) rmax=(int32_t)sqrt((float)((xmid-xmin)*(xmid-xmin)+(ymid-ymin)*(ymid-ymin)));
+ if (Koeff==0.0f) Koeff=1.0f;
+
+ for(int32_t y=ymin; y<ymax; y++){
+ info.nProgress = (int32_t)(100*(y-ymin)/(ymax-ymin));
+ if (info.nEscape) break;
+ for(int32_t x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+ if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+ {
+ nx=xmid-x;
+ ny=ymid-y;
+ radius=sqrt((float)(nx*nx+ny*ny));
+ if (radius<rmax) {
+ angle=atan2((double)ny,(double)nx);
+ if (type==0) rnew=radius*radius/rmax;
+ else if (type==1) rnew=sqrt(radius*rmax);
+ else if (type==2) {rnew=radius;angle += radius / Koeff;}
+ else rnew = 1; // potentially uninitialized
+ if (type<3){
+ nx = xmid + (int32_t)(rnew * cos(angle));
+ ny = ymid - (int32_t)(rnew * sin(angle));
+ }
+ else if (type==3){
+ nx = (int32_t)fabs((angle*xmax/6.2831852));
+ ny = (int32_t)fabs((radius*ymax/rmax));
+ }
+ else {
+ nx=x+(x%32)-16;
+ ny=y;
+ }
+// nx=max(xmin,min(nx,xmax));
+// ny=max(ymin,min(ny,ymax));
+ }
+ else { nx=-1;ny=-1;}
+ if (head.biClrUsed==0){
+ tmp.SetPixelColor(x,y,GetPixelColor(nx,ny));
+ } else {
+ tmp.SetPixelIndex(x,y,GetPixelIndex(nx,ny));
+ }
+#if CXIMAGE_SUPPORT_ALPHA
+ tmp.AlphaSet(x,y,AlphaGet(nx,ny));
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+ }
+ Transfer(tmp);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Faster way to almost properly shrink image. Algorithm produces results comparable with "high resoultion shrink"
+ * when resulting image is much smaller (that would be 3 times or more) than original. When
+ * resulting image is only slightly smaller, results are closer to nearest pixel.
+ * This algorithm works by averaging, but it does not calculate fractions of pixels. It adds whole
+ * source pixels to the best destionation. It is not geometrically "correct".
+ * It's main advantage over "high" resulution shrink is speed, so it's useful, when speed is most
+ * important (preview thumbnails, "map" view, ...).
+ * Method is optimized for RGB24 images.
+ *
+ * \param newx, newy - size of destination image (must be smaller than original!)
+ * \param iDst - pointer to destination image (if it's 0, this image is modified)
+ * \param bChangeBpp - flag points to change result image bpp (if it's true, this result image bpp = 24 (useful for B/W image thumbnails))
+ *
+ * \return true if everything is ok
+ * \author [bd], 9.2004; changes [Artiom Mirolubov], 1.2005
+ */
+bool CxImage::QIShrink(int32_t newx, int32_t newy, CxImage* const iDst, bool bChangeBpp)
+{
+ if (!pDib) return false;
+
+ if (newx>head.biWidth || newy>head.biHeight) {
+ //let me repeat... this method can't enlarge image
+ strcpy(info.szLastError,"QIShrink can't enlarge image");
+ return false;
+ }
+
+ if (newx==head.biWidth && newy==head.biHeight) {
+ //image already correct size (just copy and return)
+ if (iDst) iDst->Copy(*this);
+ return true;
+ }//if
+
+ //create temporary destination image
+ CxImage newImage;
+ newImage.CopyInfo(*this);
+ newImage.Create(newx,newy,(bChangeBpp)?24:head.biBitCount,GetType());
+ newImage.SetPalette(GetPalette());
+ if (!newImage.IsValid()){
+ strcpy(info.szLastError,newImage.GetLastError());
+ return false;
+ }
+
+ //and alpha channel if required
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid()) newImage.AlphaCreate();
+#endif
+
+ const int32_t oldx = head.biWidth;
+ const int32_t oldy = head.biHeight;
+
+ int32_t accuCellSize = 4;
+#if CXIMAGE_SUPPORT_ALPHA
+ uint8_t *alphaPtr;
+ if (AlphaIsValid()) accuCellSize=5;
+#endif
+
+ uint32_t *accu = new uint32_t[newx*accuCellSize]; //array for suming pixels... one pixel for every destination column
+ uint32_t *accuPtr; //pointer for walking through accu
+ //each cell consists of blue, red, green component and count of pixels summed in this cell
+ memset(accu, 0, newx * accuCellSize * sizeof(uint32_t)); //clear accu
+
+ if (!IsIndexed()) {
+ //RGB24 version with pointers
+ uint8_t *destPtr, *srcPtr, *destPtrS, *srcPtrS; //destination and source pixel, and beginnings of current row
+ srcPtrS=(uint8_t*)BlindGetPixelPointer(0,0);
+ destPtrS=(uint8_t*)newImage.BlindGetPixelPointer(0,0);
+ int32_t ex=0, ey=0; //ex and ey replace division...
+ int32_t dy=0;
+ //(we just add pixels, until by adding newx or newy we get a number greater than old size... then
+ // it's time to move to next pixel)
+
+ for(int32_t y=0; y<oldy; y++){ //for all source rows
+ info.nProgress = (int32_t)(100*y/oldy); if (info.nEscape) break;
+ ey += newy;
+ ex = 0; //restart with ex = 0
+ accuPtr=accu; //restart from beginning of accu
+ srcPtr=srcPtrS; //and from new source line
+#if CXIMAGE_SUPPORT_ALPHA
+ alphaPtr = AlphaGetPointer(0, y);
+#endif
+
+ for(int32_t x=0; x<oldx; x++){ //for all source columns
+ ex += newx;
+ *accuPtr += *(srcPtr++); //add current pixel to current accu slot
+ *(accuPtr+1) += *(srcPtr++);
+ *(accuPtr+2) += *(srcPtr++);
+ (*(accuPtr+3)) ++;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (alphaPtr) *(accuPtr+4) += *(alphaPtr++);
+#endif
+ if (ex>oldx) { //when we reach oldx, it's time to move to new slot
+ accuPtr += accuCellSize;
+ ex -= oldx; //(substract oldx from ex and resume from there on)
+ }//if (ex overflow)
+ }//for x
+
+ if (ey>=oldy) { //now when this happens
+ ey -= oldy; //it's time to move to new destination row
+ destPtr = destPtrS; //reset pointers to proper initial values
+ accuPtr = accu;
+#if CXIMAGE_SUPPORT_ALPHA
+ alphaPtr = newImage.AlphaGetPointer(0, dy++);
+#endif
+ for (int32_t k=0; k<newx; k++) { //copy accu to destination row (divided by number of pixels in each slot)
+ *(destPtr++) = (uint8_t)(*(accuPtr) / *(accuPtr+3));
+ *(destPtr++) = (uint8_t)(*(accuPtr+1) / *(accuPtr+3));
+ *(destPtr++) = (uint8_t)(*(accuPtr+2) / *(accuPtr+3));
+#if CXIMAGE_SUPPORT_ALPHA
+ if (alphaPtr) *(alphaPtr++) = (uint8_t)(*(accuPtr+4) / *(accuPtr+3));
+#endif
+ accuPtr += accuCellSize;
+ }//for k
+ memset(accu, 0, newx * accuCellSize * sizeof(uint32_t)); //clear accu
+ destPtrS += newImage.info.dwEffWidth;
+ }//if (ey overflow)
+
+ srcPtrS += info.dwEffWidth; //next round we start from new source row
+ }//for y
+ } else {
+ //standard version with GetPixelColor...
+ int32_t ex=0, ey=0; //ex and ey replace division...
+ int32_t dy=0;
+ //(we just add pixels, until by adding newx or newy we get a number greater than old size... then
+ // it's time to move to next pixel)
+ RGBQUAD rgb;
+
+ for(int32_t y=0; y<oldy; y++){ //for all source rows
+ info.nProgress = (int32_t)(100*y/oldy); if (info.nEscape) break;
+ ey += newy;
+ ex = 0; //restart with ex = 0
+ accuPtr=accu; //restart from beginning of accu
+ for(int32_t x=0; x<oldx; x++){ //for all source columns
+ ex += newx;
+ rgb = GetPixelColor(x, y, true);
+ *accuPtr += rgb.rgbBlue; //add current pixel to current accu slot
+ *(accuPtr+1) += rgb.rgbRed;
+ *(accuPtr+2) += rgb.rgbGreen;
+ (*(accuPtr+3)) ++;
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pAlpha) *(accuPtr+4) += rgb.rgbReserved;
+#endif
+ if (ex>oldx) { //when we reach oldx, it's time to move to new slot
+ accuPtr += accuCellSize;
+ ex -= oldx; //(substract oldx from ex and resume from there on)
+ }//if (ex overflow)
+ }//for x
+
+ if (ey>=oldy) { //now when this happens
+ ey -= oldy; //it's time to move to new destination row
+ accuPtr = accu;
+ for (int32_t dx=0; dx<newx; dx++) { //copy accu to destination row (divided by number of pixels in each slot)
+ rgb.rgbBlue = (uint8_t)(*(accuPtr) / *(accuPtr+3));
+ rgb.rgbRed = (uint8_t)(*(accuPtr+1) / *(accuPtr+3));
+ rgb.rgbGreen= (uint8_t)(*(accuPtr+2) / *(accuPtr+3));
+#if CXIMAGE_SUPPORT_ALPHA
+ if (pAlpha) rgb.rgbReserved = (uint8_t)(*(accuPtr+4) / *(accuPtr+3));
+#endif
+ newImage.SetPixelColor(dx, dy, rgb, pAlpha!=0);
+ accuPtr += accuCellSize;
+ }//for dx
+ memset(accu, 0, newx * accuCellSize * sizeof(uint32_t)); //clear accu
+ dy++;
+ }//if (ey overflow)
+ }//for y
+ }//if
+
+ delete [] accu; //delete helper array
+
+ //copy new image to the destination
+ if (iDst)
+ iDst->Transfer(newImage);
+ else
+ Transfer(newImage);
+ return true;
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_TRANSFORMATION
diff --git a/archive/hge/CxImage/ximawbmp.cpp b/archive/hge/CxImage/ximawbmp.cpp new file mode 100644 index 0000000..7ba5d00 --- /dev/null +++ b/archive/hge/CxImage/ximawbmp.cpp @@ -0,0 +1,134 @@ +/*
+ * File: ximawbmp.cpp
+ * Purpose: Platform Independent WBMP Image Class Loader and Writer
+ * 12/Jul/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximawbmp.h"
+
+#if CXIMAGE_SUPPORT_WBMP
+
+#include "ximaiter.h"
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageWBMP::Decode(CxFile *hFile)
+{
+ if (hFile == NULL) return false;
+
+ WBMPHEADER wbmpHead;
+
+ cx_try
+ {
+ ReadOctet(hFile, &wbmpHead.Type);
+
+ uint32_t dat;
+ ReadOctet(hFile, &dat);
+ wbmpHead.FixHeader = (uint8_t)dat;
+
+ ReadOctet(hFile, &wbmpHead.ImageWidth);
+ ReadOctet(hFile, &wbmpHead.ImageHeight);
+
+ if (hFile->Eof())
+ cx_throw("Not a WBMP");
+
+ if (wbmpHead.Type != 0)
+ cx_throw("Unsupported WBMP type");
+
+ head.biWidth = wbmpHead.ImageWidth;
+ head.biHeight= wbmpHead.ImageHeight;
+
+ if (head.biWidth<=0 || head.biHeight<=0)
+ cx_throw("Corrupted WBMP");
+
+ if (info.nEscape == -1){
+ info.dwType = CXIMAGE_FORMAT_WBMP;
+ return true;
+ }
+
+ Create(head.biWidth, head.biHeight, 1, CXIMAGE_FORMAT_WBMP);
+ if (!IsValid()) cx_throw("WBMP Create failed");
+ SetGrayPalette();
+
+ int32_t linewidth=(head.biWidth+7)/8;
+ CImageIterator iter(this);
+ iter.Upset();
+ for (int32_t y=0; y < head.biHeight; y++){
+ hFile->Read(iter.GetRow(),linewidth,1);
+ iter.PrevRow();
+ }
+
+ } cx_catch {
+ if (strcmp(message,"")) strncpy(info.szLastError,message,255);
+ return FALSE;
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageWBMP::ReadOctet(CxFile * hFile, uint32_t *data)
+{
+ uint8_t c;
+ *data = 0;
+ do {
+ if (hFile->Eof()) return false;
+ c = (uint8_t)hFile->GetC();
+ *data <<= 7;
+ *data |= (c & 0x7F);
+ } while ((c&0x80)!=0);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageWBMP::Encode(CxFile * hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ //check format limits
+ if (head.biBitCount!=1){
+ strcpy(info.szLastError,"Can't save this image as WBMP");
+ return false;
+ }
+
+ WBMPHEADER wbmpHead;
+ wbmpHead.Type=0;
+ wbmpHead.FixHeader=0;
+ wbmpHead.ImageWidth=head.biWidth;
+ wbmpHead.ImageHeight=head.biHeight;
+
+ // Write the file header
+ hFile->PutC('\0');
+ hFile->PutC('\0');
+ WriteOctet(hFile,wbmpHead.ImageWidth);
+ WriteOctet(hFile,wbmpHead.ImageHeight);
+ // Write the pixels
+ int32_t linewidth=(wbmpHead.ImageWidth+7)/8;
+ CImageIterator iter(this);
+ iter.Upset();
+ for (uint32_t y=0; y < wbmpHead.ImageHeight; y++){
+ hFile->Write(iter.GetRow(),linewidth,1);
+ iter.PrevRow();
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageWBMP::WriteOctet(CxFile * hFile, const uint32_t data)
+{
+ int32_t ns = 0;
+ while (data>>(ns+7)) ns+=7;
+ while (ns>0){
+ if (!hFile->PutC(0x80 | (uint8_t)(data>>ns))) return false;
+ ns-=7;
+ }
+ if (!(hFile->PutC((uint8_t)(0x7F & data)))) return false;
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_WBMP
+
diff --git a/archive/hge/CxImage/ximawbmp.h b/archive/hge/CxImage/ximawbmp.h new file mode 100644 index 0000000..9a7837e --- /dev/null +++ b/archive/hge/CxImage/ximawbmp.h @@ -0,0 +1,49 @@ +/*
+ * File: ximawbmp.h
+ * Purpose: WBMP Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageWBMP (c) 12/Jul/2002 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ * ==========================================================
+ */
+#if !defined(__ximaWBMP_h)
+#define __ximaWBMP_h
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_WBMP
+
+class CxImageWBMP: public CxImage
+{
+#pragma pack(1)
+typedef struct tagWbmpHeader
+{
+ uint32_t Type; // 0
+ uint8_t FixHeader; // 0
+ uint32_t ImageWidth; // Image Width
+ uint32_t ImageHeight; // Image Height
+} WBMPHEADER;
+#pragma pack()
+public:
+ CxImageWBMP(): CxImage(CXIMAGE_FORMAT_WBMP) {}
+
+// bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_WBMP);}
+// bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_WBMP);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+protected:
+ bool ReadOctet(CxFile * hFile, uint32_t *data);
+
+public:
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+protected:
+ bool WriteOctet(CxFile * hFile, const uint32_t data);
+#endif // CXIMAGE_SUPPORT_ENCODE
+};
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximawmf.cpp b/archive/hge/CxImage/ximawmf.cpp new file mode 100644 index 0000000..a1057f5 --- /dev/null +++ b/archive/hge/CxImage/ximawmf.cpp @@ -0,0 +1,483 @@ +/*
+*********************************************************************
+ * File: ximawmf.cpp
+ * Purpose: Windows Metafile Class Loader and Writer
+ * Author: Volker Horch - vhorch@gmx.de
+ * created: 13-Jun-2002
+ *
+ * Note: If the code below works, i wrote it.
+ * If it doesn't work, i don't know who wrote it.
+*********************************************************************
+ */
+
+/*
+*********************************************************************
+ Note by Author:
+*********************************************************************
+
+ Metafile Formats:
+ =================
+
+ There are 2 kinds of Windows Metafiles:
+ - Standard Windows Metafile
+ - Placeable Windows Metafile
+
+ A StandardWindows Metafile looks like:
+ - Metafile Header (MEATAHEADER)
+ - Metafile Records
+
+ A Placeable Metafile looks like:
+ - Aldus Header (METAFILEHEADER)
+ - Metafile Header (METAHEADER)
+ - Metafile Records
+
+ The "Metafile Header" and the "Metafile Records" are the same
+ for both formats. However, the Standard Metafile does not contain any
+ information about the original dimensions or x/y ratio of the Metafile.
+
+ I decided, to allow only placeable Metafiles here. If you also want to
+ enable Standard Metafiles, you will have to guess the dimensions of
+ the image.
+
+*********************************************************************
+ Limitations: see ximawmf.h
+ you may configure some stuff there
+*********************************************************************
+*/
+
+#include "ximawmf.h"
+
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageWMF::Decode(CxFile *hFile, int32_t nForceWidth, int32_t nForceHeight)
+{
+ if (hFile == NULL) return false;
+
+ HENHMETAFILE hMeta;
+ HDC hDC;
+ int32_t cx,cy;
+
+ //save the current position of the file
+ int32_t pos = hFile->Tell();
+
+ // Read the Metafile and convert to an Enhanced Metafile
+ METAFILEHEADER mfh;
+ hMeta = ConvertWmfFiletoEmf(hFile, &mfh);
+ if (hMeta) { // ok, it's a WMF
+
+/////////////////////////////////////////////////////////////////////
+// We use the original WMF size information, because conversion to
+// EMF adjusts the Metafile to Full Screen or does not set rclBounds at all
+// ENHMETAHEADER emh;
+// uint32_t uRet;
+// uRet = GetEnhMetaFileHeader(hMeta, // handle of enhanced metafile
+// sizeof(ENHMETAHEADER), // size of buffer, in bytes
+// &emh); // address of buffer to receive data
+// if (!uRet){
+// DeleteEnhMetaFile(hMeta);
+// return false;
+// }
+// // calculate size
+// cx = emh.rclBounds.right - emh.rclBounds.left;
+// cy = emh.rclBounds.bottom - emh.rclBounds.top;
+/////////////////////////////////////////////////////////////////////
+
+ // calculate size
+ // scale the metafile (pixels/inch of metafile => pixels/inch of display)
+ // mfh.inch already checked to be <> 0
+
+ hDC = ::GetDC(0);
+ int32_t cx1 = ::GetDeviceCaps(hDC, LOGPIXELSX);
+ int32_t cy1 = ::GetDeviceCaps(hDC, LOGPIXELSY);
+ ::ReleaseDC(0, hDC);
+
+ cx = (mfh.inch/2 + (mfh.bbox.right - mfh.bbox.left) * cx1) / mfh.inch;
+ cy = (mfh.inch/2 + (mfh.bbox.bottom - mfh.bbox.top) * cy1) / mfh.inch;
+
+ } else { // maybe it's an EMF...
+
+ hFile->Seek(pos,SEEK_SET);
+
+ ENHMETAHEADER emh;
+ hMeta = ConvertEmfFiletoEmf(hFile, &emh);
+
+ if (!hMeta){
+ strcpy(info.szLastError,"corrupted WMF");
+ return false; // definitively give up
+ }
+
+ // ok, it's an EMF; calculate canvas size
+ cx = emh.rclBounds.right - emh.rclBounds.left;
+ cy = emh.rclBounds.bottom - emh.rclBounds.top;
+
+ // alternative methods, sometime not so reliable... [DP]
+ //cx = emh.szlDevice.cx;
+ //cy = emh.szlDevice.cy;
+ //
+ //hDC = ::GetDC(0);
+ //float hscale = (float)GetDeviceCaps(hDC, HORZRES)/(100.0f * GetDeviceCaps(hDC, HORZSIZE));
+ //float vscale = (float)GetDeviceCaps(hDC, VERTRES)/(100.0f * GetDeviceCaps(hDC, VERTSIZE));
+ //::ReleaseDC(0, hDC);
+ //cx = (int32_t)((emh.rclFrame.right - emh.rclFrame.left) * hscale);
+ //cy = (int32_t)((emh.rclFrame.bottom - emh.rclFrame.top) * vscale);
+ }
+
+ if (info.nEscape == -1) { // Check if cancelled
+ head.biWidth = cx;
+ head.biHeight= cy;
+ info.dwType = CXIMAGE_FORMAT_WMF;
+ DeleteEnhMetaFile(hMeta);
+ strcpy(info.szLastError,"output dimensions returned");
+ return true;
+ }
+
+ if (!cx || !cy) {
+ DeleteEnhMetaFile(hMeta);
+ strcpy(info.szLastError,"empty WMF");
+ return false;
+ }
+
+ if (nForceWidth) cx=nForceWidth;
+ if (nForceHeight) cy=nForceHeight;
+ ShrinkMetafile(cx, cy); // !! Otherwise Bitmap may have bombastic size
+
+ HDC hDC0 = ::GetDC(0); // DC of screen
+ HBITMAP hBitmap = CreateCompatibleBitmap(hDC0, cx, cy); // has # colors of display
+ hDC = CreateCompatibleDC(hDC0); // memory dc compatible with screen
+ ::ReleaseDC(0, hDC0); // don't need anymore. get rid of it.
+
+ if (hDC){
+ if (hBitmap){
+ RECT rc = {0,0,cx,cy};
+ int32_t bpp = ::GetDeviceCaps(hDC, BITSPIXEL);
+
+ HBITMAP hBitmapOld = (HBITMAP)SelectObject(hDC, hBitmap);
+
+ // clear out the entire bitmap with windows background
+ // because the MetaFile may not contain background information
+ uint32_t dwBack = XMF_COLOR_BACK;
+#if XMF_SUPPORT_TRANSPARENCY
+ if (bpp == 24) dwBack = XMF_COLOR_TRANSPARENT;
+#endif
+ uint32_t OldColor = SetBkColor(hDC, dwBack);
+ ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
+ SetBkColor(hDC, OldColor);
+
+ //retrieves optional palette entries from the specified enhanced metafile
+ PLOGPALETTE plogPal;
+ PBYTE pjTmp;
+ HPALETTE hPal;
+ int32_t iEntries = GetEnhMetaFilePaletteEntries(hMeta, 0, NULL);
+ if (iEntries) {
+ if ((plogPal = (PLOGPALETTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
+ sizeof(uint32_t) + sizeof(PALETTEENTRY)*iEntries )) == NULL) {
+ DeleteObject(hBitmap);
+ DeleteDC(hDC);
+ DeleteEnhMetaFile(hMeta);
+ strcpy(info.szLastError,"Cancelled");
+ return false;
+ }
+
+ plogPal->palVersion = 0x300;
+ plogPal->palNumEntries = (uint16_t) iEntries;
+ pjTmp = (PBYTE) plogPal;
+ pjTmp += 4;
+
+ GetEnhMetaFilePaletteEntries(hMeta, iEntries, (PPALETTEENTRY)pjTmp);
+ hPal = CreatePalette(plogPal);
+ GlobalFree(plogPal);
+
+ SelectPalette(hDC, hPal, FALSE);
+ RealizePalette(hDC);
+ }
+
+ // Play the Metafile into Memory DC
+ BOOL bRet = PlayEnhMetaFile(hDC, // handle to a device context
+ hMeta, // handle to an enhanced metafile
+ &rc); // pointer to bounding rectangle
+
+ SelectObject(hDC, hBitmapOld);
+ DeleteEnhMetaFile(hMeta); // we are done with this one
+
+ if (info.nEscape) { // Check if cancelled
+ DeleteObject(hBitmap);
+ DeleteDC(hDC);
+ strcpy(info.szLastError,"Cancelled");
+ return false;
+ }
+
+ // the Bitmap now has the image.
+ // Create our DIB and convert the DDB into DIB
+ if (!Create(cx, cy, bpp, CXIMAGE_FORMAT_WMF)) {
+ DeleteObject(hBitmap);
+ DeleteDC(hDC);
+ return false;
+ }
+
+#if XMF_SUPPORT_TRANSPARENCY
+ if (bpp == 24) {
+ RGBQUAD rgbTrans = { XMF_RGBQUAD_TRANSPARENT };
+ SetTransColor(rgbTrans);
+ }
+#endif
+ // We're finally ready to get the DIB. Call the driver and let
+ // it party on our bitmap. It will fill in the color table,
+ // and bitmap bits of our global memory block.
+ bRet = GetDIBits(hDC, hBitmap, 0,
+ (uint32_t)cy, GetBits(), (LPBITMAPINFO)pDib, DIB_RGB_COLORS);
+
+ DeleteObject(hBitmap);
+ DeleteDC(hDC);
+
+ return (bRet!=0);
+ } else {
+ DeleteDC(hDC);
+ }
+ } else {
+ if (hBitmap) DeleteObject(hBitmap);
+ }
+
+ DeleteEnhMetaFile(hMeta);
+
+ return false;
+}
+
+/**********************************************************************
+ Function: CheckMetafileHeader
+ Purpose: Check if the Metafileheader of a file is valid
+**********************************************************************/
+BOOL CxImageWMF::CheckMetafileHeader(METAFILEHEADER *metafileheader)
+{
+ uint16_t *pw;
+ uint16_t cs;
+ int32_t i;
+
+ // check magic #
+ if (metafileheader->key != 0x9ac6cdd7L) return false;
+
+ // test checksum of header
+ pw = (uint16_t *)metafileheader;
+ cs = *pw;
+ pw++;
+ for (i = 0; i < 9; i++) {
+ cs ^= *pw;
+ pw++;
+ }
+
+ if (cs != metafileheader->checksum) return false;
+
+ // check resolution
+ if ((metafileheader->inch <= 0) || (metafileheader->inch > 2540)) return false;
+
+ return true;
+}
+
+/**********************************************************************
+ Function: ConvertWmfFiletoEmf
+ Purpose: Converts a Windows Metafile into an Enhanced Metafile
+**********************************************************************/
+HENHMETAFILE CxImageWMF::ConvertWmfFiletoEmf(CxFile *fp, METAFILEHEADER *metafileheader)
+{
+ HENHMETAFILE hMeta;
+ uint32_t lenFile;
+ uint32_t len;
+ uint8_t *p;
+ METAHEADER mfHeader;
+ uint32_t seekpos;
+
+ hMeta = 0;
+
+ // get length of the file
+ lenFile = fp->Size();
+
+ // a placeable metafile starts with a METAFILEHEADER
+ // read it and check metafileheader
+ len = fp->Read(metafileheader, 1, sizeof(METAFILEHEADER));
+ if (len < sizeof(METAFILEHEADER)) return (hMeta);
+
+ if (CheckMetafileHeader(metafileheader)) {
+ // This is a placeable metafile
+ // Convert the placeable format into something that can
+ // be used with GDI metafile functions
+ seekpos = sizeof(METAFILEHEADER);
+ } else {
+ // Not a placeable wmf. A windows metafile?
+ // at least not scaleable.
+ // we could try to convert, but would loose ratio. don't allow this
+ return (hMeta);
+
+ //metafileheader->bbox.right = ?;
+ //metafileheader->bbox.left = ?;
+ //metafileheader->bbox.bottom = ?;
+ //metafileheader->bbox.top = ?;
+ //metafileheader->inch = ?;
+ //
+ //seekpos = 0;
+ // fp->Seek(0, SEEK_SET); // rewind
+ }
+
+ // At this point we have a metaheader regardless of whether
+ // the metafile was a windows metafile or a placeable metafile
+ // so check to see if it is valid. There is really no good
+ // way to do this so just make sure that the mtType is either
+ // 1 or 2 (memory or disk file)
+ // in addition we compare the length of the METAHEADER against
+ // the length of the file. if filelength < len => no Metafile
+
+ len = fp->Read(&mfHeader, 1, sizeof(METAHEADER));
+ if (len < sizeof(METAHEADER)) return (hMeta);
+
+ if ((mfHeader.mtType != 1) && (mfHeader.mtType != 2)) return (hMeta);
+
+ // Length in Bytes from METAHEADER
+ len = mfHeader.mtSize * 2;
+ if (len > lenFile) return (hMeta);
+
+ // Allocate memory for the metafile bits
+ p = (uint8_t *)malloc(len);
+ if (!p) return (hMeta);
+
+ // seek back to METAHEADER and read all the stuff at once
+ fp->Seek(seekpos, SEEK_SET);
+ lenFile = fp->Read(p, 1, len);
+ if (lenFile != len) {
+ free(p);
+ return (hMeta);
+ }
+
+ // the following (commented code) works, but adjusts rclBound of the
+ // Enhanced Metafile to full screen.
+ // the METAFILEHEADER from above is needed to scale the image
+
+// hMeta = SetWinMetaFileBits(len, p, NULL, NULL);
+
+ // scale the metafile (pixels/inch of metafile => pixels/inch of display)
+
+ METAFILEPICT mfp;
+ int32_t cx1, cy1;
+ HDC hDC;
+
+ hDC = ::GetDC(0);
+ cx1 = ::GetDeviceCaps(hDC, LOGPIXELSX);
+ cy1 = ::GetDeviceCaps(hDC, LOGPIXELSY);
+
+ memset(&mfp, 0, sizeof(mfp));
+
+ mfp.mm = MM_ANISOTROPIC;
+ mfp.xExt = 10000; //(metafileheader->bbox.right - metafileheader->bbox.left) * cx1 / metafileheader->inch;
+ mfp.yExt = 10000; //(metafileheader->bbox.bottom - metafileheader->bbox.top) * cy1 / metafileheader->inch;
+ mfp.hMF = 0;
+
+ // in MM_ANISOTROPIC mode xExt and yExt are in MM_HIENGLISH
+ // MM_HIENGLISH means: Each logical unit is converted to 0.001 inch
+ //mfp.xExt *= 1000;
+ //mfp.yExt *= 1000;
+ // ????
+ //int32_t k = 332800 / ::GetSystemMetrics(SM_CXSCREEN);
+ //mfp.xExt *= k; mfp.yExt *= k;
+
+ // fix for Win9x
+ while ((mfp.xExt < 6554) && (mfp.yExt < 6554))
+ {
+ mfp.xExt *= 10;
+ mfp.yExt *= 10;
+ }
+
+ hMeta = SetWinMetaFileBits(len, p, hDC, &mfp);
+
+ if (!hMeta){ //try 2nd conversion using a different mapping
+ mfp.mm = MM_TEXT;
+ hMeta = SetWinMetaFileBits(len, p, hDC, &mfp);
+ }
+
+ ::ReleaseDC(0, hDC);
+
+ // Free Memory
+ free(p);
+
+ return (hMeta);
+}
+/////////////////////////////////////////////////////////////////////
+HENHMETAFILE CxImageWMF::ConvertEmfFiletoEmf(CxFile *pFile, ENHMETAHEADER *pemfh)
+{
+ HENHMETAFILE hMeta;
+ int32_t iLen = pFile->Size();
+
+ // Check the header first: <km>
+ int32_t pos = pFile->Tell();
+ int32_t iLenRead = pFile->Read(pemfh, 1, sizeof(ENHMETAHEADER));
+ if (iLenRead < sizeof(ENHMETAHEADER)) return NULL;
+ if (pemfh->iType != EMR_HEADER) return NULL;
+ if (pemfh->dSignature != ENHMETA_SIGNATURE) return NULL;
+ //if (pemfh->nBytes != (uint32_t)iLen) return NULL;
+ pFile->Seek(pos,SEEK_SET);
+
+ uint8_t* pBuff = (uint8_t *)malloc(iLen);
+ if (!pBuff) return (FALSE);
+
+ // Read the Enhanced Metafile
+ iLenRead = pFile->Read(pBuff, 1, iLen);
+ if (iLenRead != iLen) {
+ free(pBuff);
+ return NULL;
+ }
+
+ // Make it a Memory Metafile
+ hMeta = SetEnhMetaFileBits(iLen, pBuff);
+
+ free(pBuff); // finished with this one
+
+ if (!hMeta) return NULL; // oops.
+
+ // Get the Enhanced Metafile Header
+ uint32_t uRet = GetEnhMetaFileHeader(hMeta, // handle of enhanced metafile
+ sizeof(ENHMETAHEADER), // size of buffer, in bytes
+ pemfh); // address of buffer to receive data
+
+ if (!uRet) {
+ DeleteEnhMetaFile(hMeta);
+ return NULL;
+ }
+
+ return (hMeta);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+/////////////////////////////////////////////////////////////////////
+bool CxImageWMF::Encode(CxFile * hFile)
+{
+ if (hFile == NULL) return false;
+ strcpy(info.szLastError, "Save WMF not supported");
+ return false;
+}
+#endif // CXIMAGE_SUPPORT_ENCODE
+/////////////////////////////////////////////////////////////////////
+
+/**********************************************************************
+Function: ShrinkMetafile
+Purpose: Shrink the size of a metafile to be not larger than
+ the definition
+**********************************************************************/
+void CxImageWMF::ShrinkMetafile(int32_t &cx, int32_t &cy)
+{
+ int32_t xScreen = XMF_MAXSIZE_CX;
+ int32_t yScreen = XMF_MAXSIZE_CY;
+
+ if (cx > xScreen){
+ cy = cy * xScreen / cx;
+ cx = xScreen;
+ }
+
+ if (cy > yScreen){
+ cx = cx * yScreen / cy;
+ cy = yScreen;
+ }
+}
+
+#endif // CIMAGE_SUPPORT_WMF
+
diff --git a/archive/hge/CxImage/ximawmf.h b/archive/hge/CxImage/ximawmf.h new file mode 100644 index 0000000..94fb168 --- /dev/null +++ b/archive/hge/CxImage/ximawmf.h @@ -0,0 +1,154 @@ +/*
+*********************************************************************
+ * File: ximawmf.h
+ * Purpose: Windows Metafile Class Loader and Writer
+ * Author: Volker Horch - vhorch@gmx.de
+ * created: 13-Jun-2002
+*********************************************************************
+ */
+
+/*
+*********************************************************************
+ Notes by Author:
+*********************************************************************
+
+ Limitations:
+ ============
+
+ a) Transparency:
+
+ A Metafile is vector graphics, which has transparency by design.
+ This class always converts into a Bitmap format. Transparency is
+ supported, but there is no good way to find out, which parts
+ of the Metafile are transparent. There are two ways how we can
+ handle this:
+
+ - Clear the Background of the Bitmap with the background color
+ you like (i have used COLOR_WINDOW) and don't support transparency.
+
+ below #define XMF_SUPPORT_TRANSPARENCY 0
+ #define XMF_COLOR_BACK RGB(Background color you like)
+
+ - Clear the Background of the Bitmap with a very unusual color
+ (which one ?) and use this color as the transparent color
+
+ below #define XMF_SUPPORT_TRANSPARENCY 1
+ #define XMF_COLOR_TRANSPARENT_R ...
+ #define XMF_COLOR_TRANSPARENT_G ...
+ #define XMF_COLOR_TRANSPARENT_B ...
+
+ b) Resolution
+
+ Once we have converted the Metafile into a Bitmap and we zoom in
+ or out, the image may not look very good. If we still had the
+ original Metafile, zooming would produce good results always.
+
+ c) Size
+
+ Although the filesize of a Metafile may be very small, it might
+ produce a Bitmap with a bombastic size. Assume you have a Metafile
+ with an image size of 6000*4000, which contains just one Metafile
+ record ((e.g. a line from (0,0) to (6000, 4000)). The filesize
+ of this Metafile would be let's say 100kB. If we convert it to
+ a 6000*4000 Bitmap with 24 Bits/Pixes, the Bitmap would consume
+ about 68MB of memory.
+
+ I have choosen, to limit the size of the Bitmap to max.
+ screensize, to avoid memory problems.
+
+ If you want something else,
+ modify #define XMF_MAXSIZE_CX / XMF_MAXSIZE_CY below
+
+*********************************************************************
+*/
+
+#ifndef _XIMAWMF_H
+#define _XIMAWMF_H
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS
+
+class CxImageWMF: public CxImage
+{
+
+#pragma pack(1)
+
+typedef struct tagRECT16
+{
+ int16_t left;
+ int16_t top;
+ int16_t right;
+ int16_t bottom;
+} RECT16;
+
+// taken from Windos 3.11 SDK Documentation (Programmer's Reference Volume 4: Resources)
+typedef struct tagMETAFILEHEADER
+{
+ uint32_t key; // always 0x9ac6cdd7
+ uint16_t reserved1; // reserved = 0
+ RECT16 bbox; // bounding rectangle in metafile units as defined in "inch"
+ uint16_t inch; // number of metafile units per inch (should be < 1440)
+ uint32_t reserved2; // reserved = 0
+ uint16_t checksum; // sum of the first 10 WORDS (using XOR operator)
+} METAFILEHEADER;
+
+#pragma pack()
+
+public:
+ CxImageWMF(): CxImage(CXIMAGE_FORMAT_WMF) { }
+
+ bool Decode(CxFile * hFile, int32_t nForceWidth=0, int32_t nForceHeight=0);
+ bool Decode(FILE *hFile, int32_t nForceWidth=0, int32_t nForceHeight=0)
+ { CxIOFile file(hFile); return Decode(&file,nForceWidth,nForceHeight); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+protected:
+ void ShrinkMetafile(int32_t &cx, int32_t &cy);
+ BOOL CheckMetafileHeader(METAFILEHEADER *pmetafileheader);
+ HENHMETAFILE ConvertWmfFiletoEmf(CxFile *pFile, METAFILEHEADER *pmetafileheader);
+ HENHMETAFILE ConvertEmfFiletoEmf(CxFile *pFile, ENHMETAHEADER *pemfh);
+
+};
+
+#define METAFILEKEY 0x9ac6cdd7L
+
+// Background color definition (if no transparency). see Notes above
+#define XMF_COLOR_BACK GetSysColor(COLOR_WINDOW)
+// alternatives
+//#define XMF_COLOR_BACK RGB(192, 192, 192) // lite gray
+//#define XMF_COLOR_BACK RGB( 0, 0, 0) // black
+//#define XMF_COLOR_BACK RGB(255, 255, 255) // white
+
+
+// transparency support. see Notes above
+#define XMF_SUPPORT_TRANSPARENCY 0
+#define XMF_COLOR_TRANSPARENT_R 211
+#define XMF_COLOR_TRANSPARENT_G 121
+#define XMF_COLOR_TRANSPARENT_B 112
+// don't change
+#define XMF_COLOR_TRANSPARENT RGB (XMF_COLOR_TRANSPARENT_R, \
+ XMF_COLOR_TRANSPARENT_G, \
+ XMF_COLOR_TRANSPARENT_B)
+// don't change
+#define XMF_RGBQUAD_TRANSPARENT XMF_COLOR_TRANSPARENT_B, \
+ XMF_COLOR_TRANSPARENT_G, \
+ XMF_COLOR_TRANSPARENT_R, \
+ 0
+// max. size. see Notes above
+// alternatives
+//#define XMF_MAXSIZE_CX (GetSystemMetrics(SM_CXSCREEN)-10)
+//#define XMF_MAXSIZE_CY (GetSystemMetrics(SM_CYSCREEN)-50)
+//#define XMF_MAXSIZE_CX (2*GetSystemMetrics(SM_CXSCREEN)/3)
+//#define XMF_MAXSIZE_CY (2*GetSystemMetrics(SM_CYSCREEN)/3)
+#define XMF_MAXSIZE_CX 4000
+#define XMF_MAXSIZE_CY 4000
+
+
+#endif
+
+#endif
diff --git a/archive/hge/CxImage/ximawnd.cpp b/archive/hge/CxImage/ximawnd.cpp new file mode 100644 index 0000000..7f23f8f --- /dev/null +++ b/archive/hge/CxImage/ximawnd.cpp @@ -0,0 +1,1900 @@ +// xImaWnd.cpp : Windows functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 7.0.0 31/Dec/2010
+ */
+
+#include "ximage.h"
+
+#include "ximaiter.h"
+#include "ximabmp.h"
+
+////////////////////////////////////////////////////////////////////////////////
+#if defined (_WIN32_WCE)
+
+#ifndef DEFAULT_GUI_FONT
+#define DEFAULT_GUI_FONT 17
+#endif
+
+#ifndef PROOF_QUALITY
+#define PROOF_QUALITY 2
+#endif
+
+struct DIBINFO : public BITMAPINFO
+{
+ RGBQUAD arColors[255]; // Color table info - adds an extra 255 entries to palette
+ operator LPBITMAPINFO() { return (LPBITMAPINFO) this; }
+ operator LPBITMAPINFOHEADER() { return &bmiHeader; }
+ RGBQUAD* ColorTable() { return bmiColors; }
+};
+
+int32_t BytesPerLine(int32_t nWidth, int32_t nBitsPerPixel)
+{
+ return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8;
+}
+
+int32_t NumColorEntries(int32_t nBitsPerPixel, int32_t nCompression, uint32_t biClrUsed)
+{
+ int32_t nColors = 0;
+ switch (nBitsPerPixel)
+ {
+ case 1:
+ nColors = 2; break;
+ case 2:
+ nColors = 4; break; // winCE only
+ case 4:
+ nColors = 16; break;
+ case 8:
+ nColors =256; break;
+ case 24:
+ nColors = 0; break;
+ case 16:
+ case 32:
+ nColors = 3; break; // I've found that PocketPCs need this regardless of BI_RGB or BI_BITFIELDS
+ default:
+ ASSERT(FALSE);
+ }
+ // If biClrUsed is provided, and it is a legal value, use it
+ if (biClrUsed > 0 && biClrUsed <= (uint32_t)nColors)
+ return biClrUsed;
+
+ return nColors;
+}
+
+int32_t GetDIBits(
+ HDC hdc, // handle to DC
+ HBITMAP hbmp, // handle to bitmap
+ uint32_t uStartScan, // first scan line to set
+ uint32_t cScanLines, // number of scan lines to copy
+ LPVOID lpvBits, // array for bitmap bits
+ LPBITMAPINFO lpbi, // bitmap data buffer
+ uint32_t uUsage // RGB or palette index
+)
+{
+ uint32_t iColorTableSize = 0;
+
+ if (!hbmp)
+ return 0;
+
+ // Get dimensions of bitmap
+ BITMAP bm;
+ if (!::GetObject(hbmp, sizeof(bm),(LPVOID)&bm))
+ return 0;
+
+ //3. Creating new bitmap and receive pointer to it's bits.
+ HBITMAP hTargetBitmap;
+ void *pBuffer;
+
+ //3.1 Initilize DIBINFO structure
+ DIBINFO dibInfo;
+ dibInfo.bmiHeader.biBitCount = 24;
+ dibInfo.bmiHeader.biClrImportant = 0;
+ dibInfo.bmiHeader.biClrUsed = 0;
+ dibInfo.bmiHeader.biCompression = 0;
+ dibInfo.bmiHeader.biHeight = bm.bmHeight;
+ dibInfo.bmiHeader.biPlanes = 1;
+ dibInfo.bmiHeader.biSize = 40;
+ dibInfo.bmiHeader.biSizeImage = bm.bmHeight*BytesPerLine(bm.bmWidth,24);
+ dibInfo.bmiHeader.biWidth = bm.bmWidth;
+ dibInfo.bmiHeader.biXPelsPerMeter = 3780;
+ dibInfo.bmiHeader.biYPelsPerMeter = 3780;
+ dibInfo.bmiColors[0].rgbBlue = 0;
+ dibInfo.bmiColors[0].rgbGreen = 0;
+ dibInfo.bmiColors[0].rgbRed = 0;
+ dibInfo.bmiColors[0].rgbReserved = 0;
+
+ //3.2 Create bitmap and receive pointer to points into pBuffer
+ HDC hDC = ::GetDC(NULL);
+ ASSERT(hDC);
+ hTargetBitmap = CreateDIBSection(
+ hDC,
+ (const BITMAPINFO*)dibInfo,
+ DIB_RGB_COLORS,
+ (void**)&pBuffer,
+ NULL,
+ 0);
+
+ ::ReleaseDC(NULL, hDC);
+
+ //4. Copy source bitmap into the target bitmap.
+
+ //4.1 Create 2 device contexts
+ HDC memDc = CreateCompatibleDC(NULL);
+ if (!memDc) {
+ ASSERT(FALSE);
+ }
+
+ HDC targetDc = CreateCompatibleDC(NULL);
+ if (!targetDc) {
+ ASSERT(FALSE);
+ }
+
+ //4.2 Select source bitmap into one DC, target into another
+ HBITMAP hOldBitmap1 = (HBITMAP)::SelectObject(memDc, hbmp);
+ HBITMAP hOldBitmap2 = (HBITMAP)::SelectObject(targetDc, hTargetBitmap);
+
+ //4.3 Copy source bitmap into the target one
+ BitBlt(targetDc, 0, 0, bm.bmWidth, bm.bmHeight, memDc, 0, 0, SRCCOPY);
+
+ //4.4 Restore device contexts
+ ::SelectObject(memDc, hOldBitmap1);
+ ::SelectObject(targetDc, hOldBitmap2);
+ DeleteDC(memDc);
+ DeleteDC(targetDc);
+
+ //Here we can bitmap bits: pBuffer. Note:
+ // 1. pBuffer contains 3 bytes per point
+ // 2. Lines ane from the bottom to the top!
+ // 3. Points in the line are from the left to the right
+ // 4. Bytes in one point are BGR (blue, green, red) not RGB
+ // 5. Don't delete pBuffer, it will be automatically deleted
+ // when delete hTargetBitmap
+ lpvBits = pBuffer;
+
+ DeleteObject(hbmp);
+ //DeleteObject(hTargetBitmap);
+
+ return 1;
+}
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_WINDOWS
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImage::Blt(HDC pDC, int32_t x, int32_t y)
+{
+ if((pDib==0)||(pDC==0)||(!info.bEnabled)) return 0;
+
+ HBRUSH brImage = CreateDIBPatternBrushPt(pDib, DIB_RGB_COLORS);
+ POINT pt;
+ SetBrushOrgEx(pDC,x,y,&pt); //<RT>
+ HBRUSH brOld = (HBRUSH) SelectObject(pDC, brImage);
+ PatBlt(pDC, x, y, head.biWidth, head.biHeight, PATCOPY);
+ SelectObject(pDC, brOld);
+ SetBrushOrgEx(pDC,pt.x,pt.y,NULL);
+ DeleteObject(brImage);
+ return 1;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Transfer the image in a global bitmap handle (clipboard copy)
+ */
+HANDLE CxImage::CopyToHandle()
+{
+ HANDLE hMem=NULL;
+ if (pDib){
+ hMem= GlobalAlloc(GHND, GetSize());
+ if (hMem){
+ uint8_t* pDst=(uint8_t*)GlobalLock(hMem);
+ if (pDst){
+ memcpy(pDst,pDib,GetSize());
+ }
+ GlobalUnlock(hMem);
+ }
+ }
+ return hMem;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Global object (clipboard paste) constructor
+ * \param hMem: source bitmap object, the clipboard format must be CF_DIB
+ * \return true if everything is ok
+ */
+bool CxImage::CreateFromHANDLE(HANDLE hMem)
+{
+ if (!Destroy())
+ return false;
+
+ uint32_t dwSize = GlobalSize(hMem);
+ if (!dwSize) return false;
+
+ uint8_t *lpVoid; //pointer to the bitmap
+ lpVoid = (uint8_t *)GlobalLock(hMem);
+ BITMAPINFOHEADER *pHead; //pointer to the bitmap header
+ pHead = (BITMAPINFOHEADER *)lpVoid;
+ if (lpVoid){
+
+ //CxMemFile hFile(lpVoid,dwSize);
+
+ //copy the bitmap header
+ memcpy(&head,pHead,sizeof(BITMAPINFOHEADER));
+ //check if it's a top-down bitmap
+ bool bTopDownDib = head.biHeight<0;
+ if (bTopDownDib) head.biHeight=-head.biHeight;
+ //create the image
+ if(!Create(head.biWidth,head.biHeight,head.biBitCount)){
+ GlobalUnlock(hMem);
+ return false;
+ }
+ //preserve DPI
+ SetXDPI((int32_t)floor(head.biXPelsPerMeter * 254.0 / 10000.0 + 0.5));
+ SetYDPI((int32_t)floor(head.biYPelsPerMeter * 254.0 / 10000.0 + 0.5));
+
+ /*//copy the pixels (old way)
+ if((pHead->biCompression != BI_RGB) || (pHead->biBitCount == 32)){ //<Jörgen Alfredsson>
+ // BITFIELD case
+ // set the internal header in the dib
+ memcpy(pDib,&head,sizeof(head));
+ // get the bitfield masks
+ uint32_t bf[3];
+ memcpy(bf,lpVoid+pHead->biSize,12);
+ // transform into RGB
+ Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(uint8_t)pHead->biBitCount);
+ } else { //normal bitmap
+ memcpy(pDib,lpVoid,GetSize());
+ }*/
+
+ // <Michael Gandyra>
+ // fill in color map
+ bool bIsOldBmp = (head.biSize == sizeof(BITMAPCOREHEADER));
+ RGBQUAD *pRgb = GetPalette();
+ if (pRgb) {
+ // number of colors to fill in
+ int32_t nColors = DibNumColors(pHead);
+ if (bIsOldBmp) {
+ /* get pointer to BITMAPCOREINFO (old style 1.x) */
+ LPBITMAPCOREINFO lpbmc = (LPBITMAPCOREINFO)lpVoid;
+ for (int32_t i = nColors - 1; i >= 0; i--) {
+ pRgb[i].rgbRed = lpbmc->bmciColors[i].rgbtRed;
+ pRgb[i].rgbGreen = lpbmc->bmciColors[i].rgbtGreen;
+ pRgb[i].rgbBlue = lpbmc->bmciColors[i].rgbtBlue;
+ pRgb[i].rgbReserved = (uint8_t)0;
+ }
+ } else {
+ /* get pointer to BITMAPINFO (new style 3.x) */
+ LPBITMAPINFO lpbmi = (LPBITMAPINFO)lpVoid;
+ for (int32_t i = nColors - 1; i >= 0; i--) {
+ pRgb[i].rgbRed = lpbmi->bmiColors[i].rgbRed;
+ pRgb[i].rgbGreen = lpbmi->bmiColors[i].rgbGreen;
+ pRgb[i].rgbBlue = lpbmi->bmiColors[i].rgbBlue;
+ pRgb[i].rgbReserved = (uint8_t)0;
+ }
+ }
+ }
+
+ // <Michael Gandyra>
+ uint32_t dwCompression = pHead->biCompression;
+ // compressed bitmap ?
+ if(dwCompression!=BI_RGB || pHead->biBitCount==32 || pHead->biBitCount ==16) {
+ // get the bitmap bits
+ LPSTR lpDIBBits = (LPSTR)((uint8_t*)pHead + *(uint32_t*)pHead + (uint16_t)(GetNumColors() * sizeof(RGBQUAD)));
+ // decode and copy them to our image
+ switch (pHead->biBitCount) {
+ case 32 :
+ {
+ // BITFIELD case
+ if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB) {
+ // get the bitfield masks
+ uint32_t bf[3];
+ memcpy(bf,lpVoid+pHead->biSize,12);
+ // transform into RGB
+ Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(uint8_t)pHead->biBitCount);
+ } else {
+ // "unknown compression";
+ GlobalUnlock(hMem);
+ return false;
+ }
+ }
+ break;
+ case 16 :
+ {
+ // get the bitfield masks
+ int32_t offset=0;
+ uint32_t bf[3];
+ if (dwCompression == BI_BITFIELDS) {
+ memcpy(bf,lpVoid+pHead->biSize,12);
+ offset= 12;
+ } else {
+ bf[0] = 0x7C00;
+ bf[1] = 0x3E0;
+ bf[2] = 0x1F; // RGB555
+ }
+ // copy the pixels
+ memcpy(info.pImage, lpDIBBits + offset, head.biHeight*((head.biWidth+1)/2)*4);
+ // transform into RGB
+ Bitfield2RGB(info.pImage, bf[0], bf[1], bf[2], 16);
+ }
+ break;
+ case 8 :
+ case 4 :
+ case 1 :
+ {
+ switch (dwCompression) {
+ case BI_RLE4:
+ {
+ uint8_t status_byte = 0;
+ uint8_t second_byte = 0;
+ int32_t scanline = 0;
+ int32_t bits = 0;
+ BOOL low_nibble = FALSE;
+ CImageIterator iter(this);
+
+ for (BOOL bContinue = TRUE; bContinue; ) {
+ status_byte = *(lpDIBBits++);
+ switch (status_byte) {
+ case RLE_COMMAND :
+ status_byte = *(lpDIBBits++);
+ switch (status_byte) {
+ case RLE_ENDOFLINE :
+ bits = 0;
+ scanline++;
+ low_nibble = FALSE;
+ break;
+ case RLE_ENDOFBITMAP :
+ bContinue = FALSE;
+ break;
+ case RLE_DELTA :
+ {
+ // read the delta values
+ uint8_t delta_x;
+ uint8_t delta_y;
+ delta_x = *(lpDIBBits++);
+ delta_y = *(lpDIBBits++);
+ // apply them
+ bits += delta_x / 2;
+ scanline += delta_y;
+ break;
+ }
+ default :
+ second_byte = *(lpDIBBits++);
+ uint8_t* sline = iter.GetRow(scanline);
+ for (int32_t i = 0; i < status_byte; i++) {
+ if ((uint8_t*)(sline+bits) < (uint8_t*)(info.pImage+head.biSizeImage)){
+ if (low_nibble) {
+ if (i&1)
+ *(sline + bits) |= (second_byte & 0x0f);
+ else
+ *(sline + bits) |= (second_byte & 0xf0)>>4;
+ bits++;
+ } else {
+ if (i&1)
+ *(sline + bits) = (uint8_t)(second_byte & 0x0f)<<4;
+ else
+ *(sline + bits) = (uint8_t)(second_byte & 0xf0);
+ }
+ }
+
+ if ((i & 1) && (i != (status_byte - 1)))
+ second_byte = *(lpDIBBits++);
+
+ low_nibble = !low_nibble;
+ }
+ if ((((status_byte+1) >> 1) & 1 ) == 1)
+ second_byte = *(lpDIBBits++);
+ break;
+ };
+ break;
+ default :
+ {
+ uint8_t* sline = iter.GetRow(scanline);
+ second_byte = *(lpDIBBits++);
+ for (unsigned i = 0; i < status_byte; i++) {
+ if ((uint8_t*)(sline+bits) < (uint8_t*)(info.pImage+head.biSizeImage)){
+ if (low_nibble) {
+ if (i&1)
+ *(sline + bits) |= (second_byte & 0x0f);
+ else
+ *(sline + bits) |= (second_byte & 0xf0)>>4;
+ bits++;
+ } else {
+ if (i&1)
+ *(sline + bits) = (uint8_t)(second_byte & 0x0f)<<4;
+ else
+ *(sline + bits) = (uint8_t)(second_byte & 0xf0);
+ }
+ }
+ low_nibble = !low_nibble;
+ }
+ }
+ break;
+ };
+ }
+ }
+ break;
+ case BI_RLE8 :
+ {
+ uint8_t status_byte = 0;
+ uint8_t second_byte = 0;
+ int32_t scanline = 0;
+ int32_t bits = 0;
+ CImageIterator iter(this);
+
+ for (BOOL bContinue = TRUE; bContinue; ) {
+ status_byte = *(lpDIBBits++);
+ if (status_byte==RLE_COMMAND) {
+ status_byte = *(lpDIBBits++);
+ switch (status_byte) {
+ case RLE_ENDOFLINE :
+ bits = 0;
+ scanline++;
+ break;
+ case RLE_ENDOFBITMAP :
+ bContinue = FALSE;
+ break;
+ case RLE_DELTA :
+ {
+ // read the delta values
+ uint8_t delta_x;
+ uint8_t delta_y;
+ delta_x = *(lpDIBBits++);
+ delta_y = *(lpDIBBits++);
+ // apply them
+ bits += delta_x;
+ scanline += delta_y;
+ }
+ break;
+ default :
+ int32_t nNumBytes = sizeof(uint8_t) * status_byte;
+ memcpy((void *)(iter.GetRow(scanline) + bits), lpDIBBits, nNumBytes);
+ lpDIBBits += nNumBytes;
+ // align run length to even number of bytes
+ if ((status_byte & 1) == 1)
+ second_byte = *(lpDIBBits++);
+ bits += status_byte;
+ break;
+ };
+ } else {
+ uint8_t *sline = iter.GetRow(scanline);
+ second_byte = *(lpDIBBits++);
+ for (unsigned i = 0; i < status_byte; i++) {
+ if ((uint8_t*)(sline+bits) < (uint8_t*)(info.pImage+head.biSizeImage)){
+ *(sline + bits) = second_byte;
+ bits++;
+ } else {
+ bContinue = FALSE; //don't delete: we are in memory, it is not as with files
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default :
+ {
+ // "compression type not supported";
+ GlobalUnlock(hMem);
+ return false;
+ }
+ }
+ }
+ }
+ } else {
+ //normal bitmap (not compressed)
+ memcpy(pDib,lpVoid,GetSize());
+ }
+
+ GlobalUnlock(hMem);
+
+ if (bTopDownDib) Flip();
+
+ return true;
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Transfer the image in a icon handle, with transparency.
+ * \param hdc: target device context (the screen, usually)
+ * \param bTransparency : (optional) exports trancparency
+ * \return icon handle, or NULL if an error occurs.
+ * \sa MakeBitmap
+ * \author [brunom]
+ */
+HICON CxImage::MakeIcon(HDC hdc, bool bTransparency)
+{
+ HICON hDestIcon = 0;
+
+ ICONINFO csDest;
+
+ csDest.fIcon = TRUE;
+ csDest.xHotspot = 0;
+ csDest.yHotspot = 0;
+
+ // Assign HBITMAP with Transparency to ICON Info structure
+ csDest.hbmColor = MakeBitmap( hdc, bTransparency );
+
+ // Create Mask just in case we need a Mask for the Icons
+ CxImage a_Mask;
+ GetTransparentMask(&a_Mask);
+
+ // Assign Mask
+ csDest.hbmMask = a_Mask.MakeBitmap();
+
+ // Create Icon
+ hDestIcon = ::CreateIconIndirect(&csDest);
+
+ return hDestIcon;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Transfer the image in a bitmap handle
+ * \param hdc: target device context (the screen, usually)
+ * \param bTransparency : (optional) exports trancparency
+ * \return bitmap handle, or NULL if an error occurs.
+ * \sa Draw2HBITMAP, MakeIcon
+ * \author []; changes [brunom]
+ */
+HBITMAP CxImage::MakeBitmap(HDC hdc, bool bTransparency)
+{
+ if (!pDib)
+ return NULL;
+
+ // Create HBITMAP with Trancparency
+ if( (pAlpha!=0) && bTransparency )
+ {
+ HDC hMemDC;
+ if (hdc)
+ hMemDC = hdc;
+ else
+ hMemDC = CreateCompatibleDC(NULL);
+
+ BITMAPINFO bi;
+
+ // Fill in the BITMAPINFOHEADER
+ bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bi.bmiHeader.biWidth = GetWidth();
+ bi.bmiHeader.biHeight = GetHeight();
+ bi.bmiHeader.biPlanes = 1;
+ bi.bmiHeader.biBitCount = 32;
+ bi.bmiHeader.biCompression = BI_RGB;
+ bi.bmiHeader.biSizeImage = 4 * GetWidth() * GetHeight();
+ bi.bmiHeader.biXPelsPerMeter = 0;
+ bi.bmiHeader.biYPelsPerMeter = 0;
+ bi.bmiHeader.biClrUsed = 0;
+ bi.bmiHeader.biClrImportant = 0;
+
+ COLORREF* pCrBits = NULL;
+ HBITMAP hbmp = CreateDIBSection (
+ hMemDC, &bi, DIB_RGB_COLORS, (void **)&pCrBits,
+ NULL, NULL);
+
+ if (!hdc)
+ DeleteDC(hMemDC);
+
+ DIBSECTION ds;
+ if (::GetObject (hbmp, sizeof (DIBSECTION), &ds) == 0)
+ {
+ return 0;
+ }
+
+ // transfer Pixels from CxImage to Bitmap
+ RGBQUAD* pBit = (RGBQUAD*) ds.dsBm.bmBits;
+ int32_t lPx,lPy;
+ for( lPy=0 ; lPy < bi.bmiHeader.biHeight ; ++lPy )
+ {
+ for( lPx=0 ; lPx < bi.bmiHeader.biWidth ; ++lPx )
+ {
+ RGBQUAD lPixel = GetPixelColor(lPx,lPy,true);
+ *pBit = lPixel;
+ pBit++;
+ }
+ }
+
+ return hbmp;
+ }
+
+ // Create HBITMAP without Trancparency
+ if (!hdc){
+ // this call to CreateBitmap doesn't create a DIB <jaslet>
+ // // Create a device-independent bitmap <CSC>
+ // return CreateBitmap(head.biWidth,head.biHeight, 1, head.biBitCount, GetBits());
+ // use instead this code
+ HDC hMemDC = CreateCompatibleDC(NULL);
+ LPVOID pBit32;
+ HBITMAP bmp = CreateDIBSection(hMemDC,(LPBITMAPINFO)pDib,DIB_RGB_COLORS, &pBit32, NULL, 0);
+ if (pBit32) memcpy(pBit32, GetBits(), head.biSizeImage);
+ DeleteDC(hMemDC);
+ return bmp;
+ }
+
+ // this single line seems to work very well
+ //HBITMAP bmp = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)pDib, CBM_INIT,
+ // GetBits(), (LPBITMAPINFO)pDib, DIB_RGB_COLORS);
+ // this alternative works also with _WIN32_WCE
+ LPVOID pBit32;
+ HBITMAP bmp = CreateDIBSection(hdc, (LPBITMAPINFO)pDib, DIB_RGB_COLORS, &pBit32, NULL, 0);
+ if (pBit32) memcpy(pBit32, GetBits(), head.biSizeImage);
+
+ return bmp;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * check if the bitmap contains transparency data
+ * \param hbmp : bitmap resource handle
+ * \return true the bitmap has transparency
+ * \author [brunom]
+ */
+bool CxImage::IsHBITMAPAlphaValid( HBITMAP hbmp )
+{
+ bool lbAlphaValid = false;
+ if (hbmp)
+ {
+ BITMAP bm;
+ // get informations about the bitmap
+ GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm);
+
+ // for alpha there must bee 32 Bit's per Pixel ??
+ if( bm.bmBitsPixel == 32 )
+ {
+ BITMAPINFO l_BitmapInfo;
+ l_BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ l_BitmapInfo.bmiHeader.biWidth = bm.bmWidth;
+ l_BitmapInfo.bmiHeader.biHeight = bm.bmHeight;
+ l_BitmapInfo.bmiHeader.biPlanes = bm.bmPlanes;
+ l_BitmapInfo.bmiHeader.biBitCount = bm.bmBitsPixel;
+ l_BitmapInfo.bmiHeader.biCompression = BI_RGB;
+
+ // create Buffer for Image
+ RGBQUAD * l_pRawBytes = new RGBQUAD[bm.bmWidth * bm.bmHeight];
+
+ HDC dc = ::GetDC(NULL);
+
+ if(dc)
+ {
+ // Get Pixel Data from Image
+ if(GetDIBits(dc, hbmp, 0, bm.bmHeight, l_pRawBytes, &l_BitmapInfo, DIB_RGB_COLORS))
+ {
+ RGBQUAD * lpArray = l_pRawBytes;
+ RGBQUAD * lpArrayEnd = l_pRawBytes + (bm.bmWidth * bm.bmHeight);
+
+ // check if Alpha Channel is realy valid (anny value not zero)
+ for( ;lpArray != lpArrayEnd ; ++lpArray )
+ {
+ // any alpha value not zero
+ if( lpArray->rgbReserved != 0 )
+ {
+ // must be vaid alph channel
+ lbAlphaValid = true;
+ break;
+ }
+ }
+ }
+ ::ReleaseDC(NULL, dc);
+ }
+ // free temporary Memory
+ delete [] l_pRawBytes;
+ }
+ }
+
+ return lbAlphaValid;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Bitmap resource constructor
+ * \param hbmp : bitmap resource handle
+ * \param hpal : (optional) palette, useful for 8bpp DC
+ * \param bTransparency : (optional) for 32bpp images only, imports trancparency
+ * \return true if everything is ok
+ * \author []; changes [brunom]
+ */
+bool CxImage::CreateFromHBITMAP(HBITMAP hbmp, HPALETTE hpal, bool bTransparency)
+{
+ if (!Destroy())
+ return false;
+
+ if (hbmp) {
+ BITMAP bm;
+ // get informations about the bitmap
+ GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm);
+
+ // Transparency in HBITMAP
+ if(bTransparency && IsHBITMAPAlphaValid(hbmp))
+ {
+ bool l_bResult = true;
+
+ BITMAPINFO l_BitmapInfo;
+ l_BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ l_BitmapInfo.bmiHeader.biWidth = bm.bmWidth;
+ l_BitmapInfo.bmiHeader.biHeight = bm.bmHeight;
+ l_BitmapInfo.bmiHeader.biPlanes = bm.bmPlanes;
+ l_BitmapInfo.bmiHeader.biBitCount = bm.bmBitsPixel;
+ l_BitmapInfo.bmiHeader.biCompression = BI_RGB;
+
+ RGBQUAD *l_pRawBytes = new RGBQUAD[bm.bmWidth * bm.bmHeight];
+
+ HDC dc = ::GetDC(NULL);
+
+ if(dc)
+ {
+ if(GetDIBits(dc, hbmp, 0, bm.bmHeight, l_pRawBytes, &l_BitmapInfo, DIB_RGB_COLORS))
+ l_bResult = CreateFromArray((uint8_t*)l_pRawBytes, bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, bm.bmWidthBytes, false);
+ else
+ l_bResult = false;
+
+ ::ReleaseDC(NULL, dc);
+ }
+ else
+ l_bResult = false;
+
+ delete [] l_pRawBytes;
+
+ return l_bResult;
+ }
+ else
+ {
+ // create the image
+ if (!Create(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, 0))
+ return false;
+ // create a device context for the bitmap
+ HDC dc = ::GetDC(NULL);
+ if (!dc)
+ return false;
+
+ if (hpal){
+ SelectObject(dc,hpal); //the palette you should get from the user or have a stock one
+ RealizePalette(dc);
+ }
+
+ // copy the pixels
+ if (GetDIBits(dc, hbmp, 0, head.biHeight, info.pImage,
+ (LPBITMAPINFO)pDib, DIB_RGB_COLORS) == 0){ //replace &head with pDib <Wil Stark>
+ strcpy(info.szLastError,"GetDIBits failed");
+ ::ReleaseDC(NULL, dc);
+ return false;
+ }
+ ::ReleaseDC(NULL, dc);
+ return true;
+ }
+ }
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * icon resource constructor
+ * \param hico : icon resource handle
+ * \param bTransparency : (optional) for 32bpp images only, imports trancparency
+ * \return true if everything is ok
+ * \author []; changes [Arlen Albert Keshabian], [brunom]
+ */
+#if !defined (_WIN32_WCE)
+bool CxImage::CreateFromHICON(HICON hico, bool bTransparency)
+{
+ if (!Destroy() || !hico)
+ return false;
+
+ bool l_bResult = true;
+
+ ICONINFO iinfo;
+ GetIconInfo(hico,&iinfo);
+
+ //BITMAP l_Bitmap;
+ //GetObject(iinfo.hbmColor, sizeof(BITMAP), &l_Bitmap);
+
+ l_bResult = CreateFromHBITMAP( iinfo.hbmColor, NULL, bTransparency );
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if(l_bResult && ((!IsHBITMAPAlphaValid(iinfo.hbmColor)) || (!bTransparency)) )
+ {
+ CxImage mask;
+ mask.CreateFromHBITMAP(iinfo.hbmMask);
+ mask.GrayScale();
+ mask.Negative();
+ AlphaSet(mask);
+ }
+#endif
+
+ DeleteObject(iinfo.hbmColor); //<Sims>
+ DeleteObject(iinfo.hbmMask); //<Sims>
+
+ return l_bResult;
+}
+#endif //_WIN32_WCE
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImage::Draw(HDC hdc, const RECT& rect, RECT* pClipRect, bool bSmooth, bool bFlipY)
+{
+ return Draw(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pClipRect,bSmooth, bFlipY);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Draws the image in the specified device context, with support for alpha channel, alpha palette, transparency, opacity.
+ * \param hdc : destination device context
+ * \param x,y : (optional) offset
+ * \param cx,cy : (optional) size.
+ * - If cx or cy are not specified (or less than 0), the normal width or height will be used
+ * - If cx or cy are different than width or height, the image will be stretched
+ *
+ * \param pClipRect : limit the drawing operations inside a given rectangle in the output device context.
+ * \param bSmooth : activates a bilinear filter that will enhance the appearence for zommed pictures.
+ * Quite slow. Needs CXIMAGE_SUPPORT_INTERPOLATION.
+ * \param bFlipY : draws a mirror image along the y-axis
+ * \return true if everything is ok
+ */
+int32_t CxImage::Draw(HDC hdc, int32_t x, int32_t y, int32_t cx, int32_t cy, RECT* pClipRect, bool bSmooth, bool bFlipY)
+{
+ if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;
+
+ if (cx < 0) cx = head.biWidth;
+ if (cy < 0) cy = head.biHeight;
+ bool bTransparent = info.nBkgndIndex >= 0;
+ bool bAlpha = pAlpha != 0;
+
+ //required for MM_ANISOTROPIC, MM_HIENGLISH, and similar modes [Greg Peatfield]
+ int32_t hdc_Restore = ::SaveDC(hdc);
+ if (!hdc_Restore)
+ return 0;
+
+#if !defined (_WIN32_WCE)
+ RECT mainbox; // (experimental)
+ if (pClipRect){
+ GetClipBox(hdc,&mainbox);
+ HRGN rgn = CreateRectRgnIndirect(pClipRect);
+ ExtSelectClipRgn(hdc,rgn,RGN_AND);
+ DeleteObject(rgn);
+ }
+#endif
+
+ //find the smallest area to paint
+ RECT clipbox,paintbox;
+ GetClipBox(hdc,&clipbox);
+
+ paintbox.top = min(clipbox.bottom,max(clipbox.top,y));
+ paintbox.left = min(clipbox.right,max(clipbox.left,x));
+ paintbox.right = max(clipbox.left,min(clipbox.right,x+cx));
+ paintbox.bottom = max(clipbox.top,min(clipbox.bottom,y+cy));
+
+ int32_t destw = paintbox.right - paintbox.left;
+ int32_t desth = paintbox.bottom - paintbox.top;
+
+ if (!(bTransparent || bAlpha || info.bAlphaPaletteEnabled)){
+ if (cx==head.biWidth && cy==head.biHeight){ //NORMAL
+#if !defined (_WIN32_WCE)
+ SetStretchBltMode(hdc,COLORONCOLOR);
+#endif
+ if (bFlipY){
+ StretchDIBits(hdc, x, y+cy-1,
+ cx, -cy, 0, 0, cx, cy,
+ info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS,SRCCOPY);
+ } else {
+ SetDIBitsToDevice(hdc, x, y, cx, cy, 0, 0, 0, cy,
+ info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS);
+ }
+ } else { //STRETCH
+ //pixel informations
+ RGBQUAD c={0,0,0,0};
+ //Preparing Bitmap Info
+ BITMAPINFO bmInfo;
+ memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ bmInfo.bmiHeader.biWidth=destw;
+ bmInfo.bmiHeader.biHeight=desth;
+ bmInfo.bmiHeader.biPlanes=1;
+ bmInfo.bmiHeader.biBitCount=24;
+ uint8_t *pbase; //points to the final dib
+ uint8_t *pdst; //current pixel from pbase
+ uint8_t *ppix; //current pixel from image
+ //get the background
+ HDC TmpDC=CreateCompatibleDC(hdc);
+ HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
+ HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
+
+ if (pbase){
+ int32_t xx,yy;
+ int32_t sx,sy;
+ float dx,dy;
+ uint8_t *psrc;
+
+ int32_t ew = ((((24 * destw) + 31) / 32) * 4);
+ int32_t ymax = paintbox.bottom;
+ int32_t xmin = paintbox.left;
+ float fx=(float)head.biWidth/(float)cx;
+ float fy=(float)head.biHeight/(float)cy;
+
+ for(yy=0;yy<desth;yy++){
+ dy = head.biHeight-(ymax-yy-y)*fy;
+ sy = max(0L,(int32_t)floor(dy));
+ psrc = info.pImage+sy*info.dwEffWidth;
+ if (bFlipY){
+ pdst = pbase+(desth-1-yy)*ew;
+ } else {
+ pdst = pbase+yy*ew;
+ }
+ for(xx=0;xx<destw;xx++){
+ dx = (xx+xmin-x)*fx;
+ sx = max(0L,(int32_t)floor(dx));
+#if CXIMAGE_SUPPORT_INTERPOLATION
+ if (bSmooth){
+ if (fx > 1 && fy > 1) {
+ c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ } else {
+ c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ }
+ } else
+#endif //CXIMAGE_SUPPORT_INTERPOLATION
+ {
+ if (head.biClrUsed){
+ c=GetPaletteColor(GetPixelIndex(sx,sy));
+ } else {
+ ppix = psrc + sx*3;
+ c.rgbBlue = *ppix++;
+ c.rgbGreen= *ppix++;
+ c.rgbRed = *ppix;
+ }
+ }
+ *pdst++=c.rgbBlue;
+ *pdst++=c.rgbGreen;
+ *pdst++=c.rgbRed;
+ }
+ }
+ }
+ //paint the image & cleanup
+ SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0);
+ DeleteObject(SelectObject(TmpDC,TmpObj));
+ DeleteDC(TmpDC);
+ }
+ } else { // draw image with transparent/alpha blending
+ //////////////////////////////////////////////////////////////////
+ //Alpha blend - Thanks to Florian Egel
+
+ //pixel informations
+ RGBQUAD c={0,0,0,0};
+ RGBQUAD ct = GetTransColor();
+ int32_t* pc = (int32_t*)&c;
+ int32_t* pct= (int32_t*)&ct;
+ int32_t cit = GetTransIndex();
+ int32_t ci = 0;
+
+ //Preparing Bitmap Info
+ BITMAPINFO bmInfo;
+ memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ bmInfo.bmiHeader.biWidth=destw;
+ bmInfo.bmiHeader.biHeight=desth;
+ bmInfo.bmiHeader.biPlanes=1;
+ bmInfo.bmiHeader.biBitCount=24;
+
+ uint8_t *pbase; //points to the final dib
+ uint8_t *pdst; //current pixel from pbase
+ uint8_t *ppix; //current pixel from image
+
+ //get the background
+ HDC TmpDC=CreateCompatibleDC(hdc);
+ HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
+ HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
+ BitBlt(TmpDC,0,0,destw,desth,hdc,paintbox.left,paintbox.top,SRCCOPY);
+
+ if (pbase){
+ int32_t xx,yy,alphaoffset,ix,iy;
+ uint8_t a,a1,*psrc;
+ int32_t ew = ((((24 * destw) + 31) / 32) * 4);
+ int32_t ymax = paintbox.bottom;
+ int32_t xmin = paintbox.left;
+
+ if (cx!=head.biWidth || cy!=head.biHeight){
+ //STRETCH
+ float fx=(float)head.biWidth/(float)cx;
+ float fy=(float)head.biHeight/(float)cy;
+ float dx,dy;
+ int32_t sx,sy;
+
+ for(yy=0;yy<desth;yy++){
+ dy = head.biHeight-(ymax-yy-y)*fy;
+ sy = max(0L,(int32_t)floor(dy));
+
+ alphaoffset = sy*head.biWidth;
+ if (bFlipY){
+ pdst = pbase+(desth-1-yy)*ew;
+ } else {
+ pdst = pbase + yy*ew;
+ }
+ psrc = info.pImage + sy*info.dwEffWidth;
+
+ for(xx=0;xx<destw;xx++){
+ dx = (xx+xmin-x)*fx;
+ sx = max(0L,(int32_t)floor(dx));
+
+ if (bAlpha) a=pAlpha[alphaoffset+sx]; else a=255;
+ a =(uint8_t)((a*(1+info.nAlphaMax))>>8);
+
+ if (head.biClrUsed){
+ ci = GetPixelIndex(sx,sy);
+#if CXIMAGE_SUPPORT_INTERPOLATION
+ if (bSmooth){
+ if (fx > 1 && fy > 1) {
+ c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ } else {
+ c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ }
+ } else
+#endif //CXIMAGE_SUPPORT_INTERPOLATION
+ {
+ c = GetPaletteColor(GetPixelIndex(sx,sy));
+ }
+ if (info.bAlphaPaletteEnabled){
+ a = (uint8_t)((a*(1+c.rgbReserved))>>8);
+ }
+ } else {
+#if CXIMAGE_SUPPORT_INTERPOLATION
+ if (bSmooth){
+ if (fx > 1 && fy > 1) {
+ c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ } else {
+ c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ }
+ } else
+#endif //CXIMAGE_SUPPORT_INTERPOLATION
+ {
+ ppix = psrc + sx*3;
+ c.rgbBlue = *ppix++;
+ c.rgbGreen= *ppix++;
+ c.rgbRed = *ppix;
+ }
+ }
+ //if (*pc!=*pct || !bTransparent){
+ //if ((head.biClrUsed && ci!=cit) || ((!head.biClrUsed||bSmooth) && *pc!=*pct) || !bTransparent){
+ if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){
+ // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication
+ if (a == 0) { // Transparent, retain dest
+ pdst+=3;
+ } else if (a == 255) { // opaque, ignore dest
+ *pdst++= c.rgbBlue;
+ *pdst++= c.rgbGreen;
+ *pdst++= c.rgbRed;
+ } else { // semi transparent
+ a1=(uint8_t)~a;
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbBlue)>>8);
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbGreen)>>8);
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbRed)>>8);
+ }
+ } else {
+ pdst+=3;
+ }
+ }
+ }
+ } else {
+ //NORMAL
+ iy=head.biHeight-ymax+y;
+ for(yy=0;yy<desth;yy++,iy++){
+ alphaoffset=iy*head.biWidth;
+ ix=xmin-x;
+ if (bFlipY){
+ pdst = pbase+(desth-1-yy)*ew;
+ } else {
+ pdst = pbase+yy*ew;
+ }
+ ppix=info.pImage+iy*info.dwEffWidth+ix*3;
+ for(xx=0;xx<destw;xx++,ix++){
+
+ if (bAlpha) a=pAlpha[alphaoffset+ix]; else a=255;
+ a = (uint8_t)((a*(1+info.nAlphaMax))>>8);
+
+ if (head.biClrUsed){
+ ci = GetPixelIndex(ix,iy);
+ c = GetPaletteColor((uint8_t)ci);
+ if (info.bAlphaPaletteEnabled){
+ a = (uint8_t)((a*(1+c.rgbReserved))>>8);
+ }
+ } else {
+ c.rgbBlue = *ppix++;
+ c.rgbGreen= *ppix++;
+ c.rgbRed = *ppix++;
+ }
+
+ //if (*pc!=*pct || !bTransparent){
+ if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){
+ // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication
+ if (a == 0) { // Transparent, retain dest
+ pdst+=3;
+ } else if (a == 255) { // opaque, ignore dest
+ *pdst++= c.rgbBlue;
+ *pdst++= c.rgbGreen;
+ *pdst++= c.rgbRed;
+ } else { // semi transparent
+ a1=(uint8_t)~a;
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbBlue)>>8);
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbGreen)>>8);
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbRed)>>8);
+ }
+ } else {
+ pdst+=3;
+ }
+ }
+ }
+ }
+ }
+ //paint the image & cleanup
+ SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0);
+ DeleteObject(SelectObject(TmpDC,TmpObj));
+ DeleteDC(TmpDC);
+ }
+
+#if !defined (_WIN32_WCE)
+ if (pClipRect){ // (experimental)
+ HRGN rgn = CreateRectRgnIndirect(&mainbox);
+ ExtSelectClipRgn(hdc,rgn,RGN_OR);
+ DeleteObject(rgn);
+ }
+#endif
+
+ ::RestoreDC(hdc,hdc_Restore);
+ return 1;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * renders the image into a HBITMAP handle
+ * \param hdc : destination device context
+ * \param x,y : (optional) offset
+ * \param cx,cy : (optional) size.
+ * - If cx or cy are not specified (or less than 0), the normal width or height will be used
+ * - If cx or cy are different than width or height, the image will be stretched
+ * \param pClipRect : limit the drawing operations inside a given rectangle in the output device context.
+ * \param bSmooth : activates a bilinear filter that will enhance the appearence for zommed pictures.
+ * Quite slow. Needs CXIMAGE_SUPPORT_INTERPOLATION.
+ * \return HBITMAP handle, NULL in case of error
+ * \sa MakeBitmap
+ */
+HBITMAP CxImage::Draw2HBITMAP(HDC hdc, int32_t x, int32_t y, int32_t cx, int32_t cy, RECT* pClipRect, bool bSmooth)
+{
+ if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;
+
+ if (cx < 0) cx = head.biWidth;
+ if (cy < 0) cy = head.biHeight;
+ bool bTransparent = info.nBkgndIndex >= 0;
+ bool bAlpha = pAlpha != 0;
+
+ //required for MM_ANISOTROPIC, MM_HIENGLISH, and similar modes [Greg Peatfield]
+ int32_t hdc_Restore = ::SaveDC(hdc);
+ if (!hdc_Restore)
+ return 0;
+
+#if !defined (_WIN32_WCE)
+ RECT mainbox; // (experimental)
+ if (pClipRect){
+ GetClipBox(hdc,&mainbox);
+ HRGN rgn = CreateRectRgnIndirect(pClipRect);
+ ExtSelectClipRgn(hdc,rgn,RGN_AND);
+ DeleteObject(rgn);
+ }
+#endif
+
+ HBITMAP TmpBmp;
+
+ //find the smallest area to paint
+ RECT clipbox,paintbox;
+ GetClipBox(hdc,&clipbox);
+
+ paintbox.top = min(clipbox.bottom,max(clipbox.top,y));
+ paintbox.left = min(clipbox.right,max(clipbox.left,x));
+ paintbox.right = max(clipbox.left,min(clipbox.right,x+cx));
+ paintbox.bottom = max(clipbox.top,min(clipbox.bottom,y+cy));
+
+ int32_t destw = paintbox.right - paintbox.left;
+ int32_t desth = paintbox.bottom - paintbox.top;
+
+ if (!(bTransparent || bAlpha || info.bAlphaPaletteEnabled)){
+ if (cx==head.biWidth && cy==head.biHeight){ //NORMAL
+#if !defined (_WIN32_WCE)
+ SetStretchBltMode(hdc,COLORONCOLOR);
+#endif
+ SetDIBitsToDevice(hdc, x, y, cx, cy, 0, 0, 0, cy,
+ info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS);
+ } else { //STRETCH
+ //pixel informations
+ RGBQUAD c={0,0,0,0};
+ //Preparing Bitmap Info
+ BITMAPINFO bmInfo;
+ memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ bmInfo.bmiHeader.biWidth=destw;
+ bmInfo.bmiHeader.biHeight=desth;
+ bmInfo.bmiHeader.biPlanes=1;
+ bmInfo.bmiHeader.biBitCount=24;
+ uint8_t *pbase; //points to the final dib
+ uint8_t *pdst; //current pixel from pbase
+ uint8_t *ppix; //current pixel from image
+ //get the background
+ HDC TmpDC=CreateCompatibleDC(hdc);
+ TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
+ HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
+
+ if (pbase){
+ int32_t xx,yy;
+ int32_t sx,sy;
+ float dx,dy;
+ uint8_t *psrc;
+
+ int32_t ew = ((((24 * destw) + 31) / 32) * 4);
+ int32_t ymax = paintbox.bottom;
+ int32_t xmin = paintbox.left;
+ float fx=(float)head.biWidth/(float)cx;
+ float fy=(float)head.biHeight/(float)cy;
+
+ for(yy=0;yy<desth;yy++){
+ dy = head.biHeight-(ymax-yy-y)*fy;
+ sy = max(0L,(int32_t)floor(dy));
+ psrc = info.pImage+sy*info.dwEffWidth;
+ pdst = pbase+yy*ew;
+ for(xx=0;xx<destw;xx++){
+ dx = (xx+xmin-x)*fx;
+ sx = max(0L,(int32_t)floor(dx));
+#if CXIMAGE_SUPPORT_INTERPOLATION
+ if (bSmooth){
+ if (fx > 1 && fy > 1) {
+ c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ } else {
+ c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ }
+ } else
+#endif //CXIMAGE_SUPPORT_INTERPOLATION
+ {
+ if (head.biClrUsed){
+ c=GetPaletteColor(GetPixelIndex(sx,sy));
+ } else {
+ ppix = psrc + sx*3;
+ c.rgbBlue = *ppix++;
+ c.rgbGreen= *ppix++;
+ c.rgbRed = *ppix;
+ }
+ }
+ *pdst++=c.rgbBlue;
+ *pdst++=c.rgbGreen;
+ *pdst++=c.rgbRed;
+ }
+ }
+ }
+ //cleanup
+ SelectObject(TmpDC,TmpObj);
+ DeleteDC(TmpDC);
+ }
+ } else { // draw image with transparent/alpha blending
+ //////////////////////////////////////////////////////////////////
+ //Alpha blend - Thanks to Florian Egel
+
+ //pixel informations
+ RGBQUAD c={0,0,0,0};
+ RGBQUAD ct = GetTransColor();
+ int32_t* pc = (int32_t*)&c;
+ int32_t* pct= (int32_t*)&ct;
+ int32_t cit = GetTransIndex();
+ int32_t ci = 0;
+
+ //Preparing Bitmap Info
+ BITMAPINFO bmInfo;
+ memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ bmInfo.bmiHeader.biWidth=destw;
+ bmInfo.bmiHeader.biHeight=desth;
+ bmInfo.bmiHeader.biPlanes=1;
+ bmInfo.bmiHeader.biBitCount=24;
+
+ uint8_t *pbase; //points to the final dib
+ uint8_t *pdst; //current pixel from pbase
+ uint8_t *ppix; //current pixel from image
+
+ //get the background
+ HDC TmpDC=CreateCompatibleDC(hdc);
+ TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
+ HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
+ BitBlt(TmpDC,0,0,destw,desth,hdc,paintbox.left,paintbox.top,SRCCOPY);
+
+ if (pbase){
+ int32_t xx,yy,alphaoffset,ix,iy;
+ uint8_t a,a1,*psrc;
+ int32_t ew = ((((24 * destw) + 31) / 32) * 4);
+ int32_t ymax = paintbox.bottom;
+ int32_t xmin = paintbox.left;
+
+ if (cx!=head.biWidth || cy!=head.biHeight){
+ //STRETCH
+ float fx=(float)head.biWidth/(float)cx;
+ float fy=(float)head.biHeight/(float)cy;
+ float dx,dy;
+ int32_t sx,sy;
+
+ for(yy=0;yy<desth;yy++){
+ dy = head.biHeight-(ymax-yy-y)*fy;
+ sy = max(0L,(int32_t)floor(dy));
+
+ alphaoffset = sy*head.biWidth;
+ pdst = pbase + yy*ew;
+ psrc = info.pImage + sy*info.dwEffWidth;
+
+ for(xx=0;xx<destw;xx++){
+ dx = (xx+xmin-x)*fx;
+ sx = max(0L,(int32_t)floor(dx));
+
+ if (bAlpha) a=pAlpha[alphaoffset+sx]; else a=255;
+ a =(uint8_t)((a*(1+info.nAlphaMax))>>8);
+
+ if (head.biClrUsed){
+ ci = GetPixelIndex(sx,sy);
+#if CXIMAGE_SUPPORT_INTERPOLATION
+ if (bSmooth){
+ if (fx > 1 && fy > 1) {
+ c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ } else {
+ c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ }
+ } else
+#endif //CXIMAGE_SUPPORT_INTERPOLATION
+ {
+ c = GetPaletteColor(GetPixelIndex(sx,sy));
+ }
+ if (info.bAlphaPaletteEnabled){
+ a = (uint8_t)((a*(1+c.rgbReserved))>>8);
+ }
+ } else {
+#if CXIMAGE_SUPPORT_INTERPOLATION
+ if (bSmooth){
+ if (fx > 1 && fy > 1) {
+ c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ } else {
+ c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT);
+ }
+ } else
+#endif //CXIMAGE_SUPPORT_INTERPOLATION
+ {
+ ppix = psrc + sx*3;
+ c.rgbBlue = *ppix++;
+ c.rgbGreen= *ppix++;
+ c.rgbRed = *ppix;
+ }
+ }
+ //if (*pc!=*pct || !bTransparent){
+ //if ((head.biClrUsed && ci!=cit) || ((!head.biClrUsed||bSmooth) && *pc!=*pct) || !bTransparent){
+ if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){
+ // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication
+ if (a == 0) { // Transparent, retain dest
+ pdst+=3;
+ } else if (a == 255) { // opaque, ignore dest
+ *pdst++= c.rgbBlue;
+ *pdst++= c.rgbGreen;
+ *pdst++= c.rgbRed;
+ } else { // semi transparent
+ a1=(uint8_t)~a;
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbBlue)>>8);
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbGreen)>>8);
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbRed)>>8);
+ }
+ } else {
+ pdst+=3;
+ }
+ }
+ }
+ } else {
+ //NORMAL
+ iy=head.biHeight-ymax+y;
+ for(yy=0;yy<desth;yy++,iy++){
+ alphaoffset=iy*head.biWidth;
+ ix=xmin-x;
+ pdst=pbase+yy*ew;
+ ppix=info.pImage+iy*info.dwEffWidth+ix*3;
+ for(xx=0;xx<destw;xx++,ix++){
+
+ if (bAlpha) a=pAlpha[alphaoffset+ix]; else a=255;
+ a = (uint8_t)((a*(1+info.nAlphaMax))>>8);
+
+ if (head.biClrUsed){
+ ci = GetPixelIndex(ix,iy);
+ c = GetPaletteColor((uint8_t)ci);
+ if (info.bAlphaPaletteEnabled){
+ a = (uint8_t)((a*(1+c.rgbReserved))>>8);
+ }
+ } else {
+ c.rgbBlue = *ppix++;
+ c.rgbGreen= *ppix++;
+ c.rgbRed = *ppix++;
+ }
+
+ //if (*pc!=*pct || !bTransparent){
+ if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){
+ // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication
+ if (a == 0) { // Transparent, retain dest
+ pdst+=3;
+ } else if (a == 255) { // opaque, ignore dest
+ *pdst++= c.rgbBlue;
+ *pdst++= c.rgbGreen;
+ *pdst++= c.rgbRed;
+ } else { // semi transparent
+ a1=(uint8_t)~a;
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbBlue)>>8);
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbGreen)>>8);
+ *pdst++=(uint8_t)((*pdst * a1 + a * c.rgbRed)>>8);
+ }
+ } else {
+ pdst+=3;
+ }
+ }
+ }
+ }
+ }
+ //cleanup
+ SelectObject(TmpDC,TmpObj);
+ DeleteDC(TmpDC);
+ }
+
+#if !defined (_WIN32_WCE)
+ if (pClipRect){ // (experimental)
+ HRGN rgn = CreateRectRgnIndirect(&mainbox);
+ ExtSelectClipRgn(hdc,rgn,RGN_OR);
+ DeleteObject(rgn);
+ }
+#endif
+
+ ::RestoreDC(hdc,hdc_Restore);
+ return TmpBmp;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImage::Draw2(HDC hdc, const RECT& rect)
+{
+ return Draw2(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Draws (stretch) the image with single transparency support
+ * \param hdc : destination device context
+ * \param x,y : (optional) offset
+ * \param cx,cy : (optional) size.
+ * - If cx or cy are not specified (or less than 0), the normal width or height will be used
+ * - If cx or cy are different than width or height, the image will be stretched
+ *
+ * \return true if everything is ok
+ */
+int32_t CxImage::Draw2(HDC hdc, int32_t x, int32_t y, int32_t cx, int32_t cy)
+{
+ if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;
+ if (cx < 0) cx = head.biWidth;
+ if (cy < 0) cy = head.biHeight;
+ bool bTransparent = (info.nBkgndIndex >= 0);
+
+ //required for MM_ANISOTROPIC, MM_HIENGLISH, and similar modes [Greg Peatfield]
+ int32_t hdc_Restore = ::SaveDC(hdc);
+ if (!hdc_Restore)
+ return 0;
+
+ if (!bTransparent){
+#if !defined (_WIN32_WCE)
+ SetStretchBltMode(hdc,COLORONCOLOR);
+#endif
+ StretchDIBits(hdc, x, y, cx, cy, 0, 0, head.biWidth, head.biHeight,
+ info.pImage,(BITMAPINFO*)pDib, DIB_RGB_COLORS,SRCCOPY);
+ } else {
+ // draw image with transparent background
+ const int32_t safe = 0; // or else GDI fails in the following - sometimes
+ RECT rcDst = {x+safe, y+safe, x+cx, y+cy};
+ if (RectVisible(hdc, &rcDst)){
+ /////////////////////////////////////////////////////////////////
+ // True Mask Method - Thanks to Paul Reynolds and Ron Gery
+ int32_t nWidth = head.biWidth;
+ int32_t nHeight = head.biHeight;
+ // Create two memory dcs for the image and the mask
+ HDC dcImage=CreateCompatibleDC(hdc);
+ HDC dcTrans=CreateCompatibleDC(hdc);
+ // Select the image into the appropriate dc
+ HBITMAP bm = CreateCompatibleBitmap(hdc, nWidth, nHeight);
+ HBITMAP pOldBitmapImage = (HBITMAP)SelectObject(dcImage,bm);
+#if !defined (_WIN32_WCE)
+ SetStretchBltMode(dcImage,COLORONCOLOR);
+#endif
+ StretchDIBits(dcImage, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
+ info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS,SRCCOPY);
+
+ // Create the mask bitmap
+ HBITMAP bitmapTrans = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
+ // Select the mask bitmap into the appropriate dc
+ HBITMAP pOldBitmapTrans = (HBITMAP)SelectObject(dcTrans, bitmapTrans);
+ // Build mask based on transparent colour
+ RGBQUAD rgbBG;
+ if (head.biBitCount<24) rgbBG = GetPaletteColor((uint8_t)info.nBkgndIndex);
+ else rgbBG = info.nBkgndColor;
+ COLORREF crColour = RGB(rgbBG.rgbRed, rgbBG.rgbGreen, rgbBG.rgbBlue);
+ COLORREF crOldBack = SetBkColor(dcImage,crColour);
+ BitBlt(dcTrans,0, 0, nWidth, nHeight, dcImage, 0, 0, SRCCOPY);
+
+ // Do the work - True Mask method - cool if not actual display
+ StretchBlt(hdc,x, y,cx,cy, dcImage, 0, 0, nWidth, nHeight, SRCINVERT);
+ StretchBlt(hdc,x, y,cx,cy, dcTrans, 0, 0, nWidth, nHeight, SRCAND);
+ StretchBlt(hdc,x, y,cx,cy, dcImage, 0, 0, nWidth, nHeight, SRCINVERT);
+
+ // Restore settings
+ SelectObject(dcImage,pOldBitmapImage);
+ SelectObject(dcTrans,pOldBitmapTrans);
+ SetBkColor(hdc,crOldBack);
+ DeleteObject( bitmapTrans ); // RG 29/01/2002
+ DeleteDC(dcImage);
+ DeleteDC(dcTrans);
+ DeleteObject(bm);
+ }
+ }
+ ::RestoreDC(hdc,hdc_Restore);
+ return 1;
+}
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImage::Stretch(HDC hdc, const RECT& rect, uint32_t dwRop)
+{
+ return Stretch(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, dwRop);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Stretch the image. Obsolete: use Draw() or Draw2()
+ * \param hdc : destination device context
+ * \param xoffset,yoffset : (optional) offset
+ * \param xsize,ysize : size.
+ * \param dwRop : raster operation code (see BitBlt documentation)
+ * \return true if everything is ok
+ */
+int32_t CxImage::Stretch(HDC hdc, int32_t xoffset, int32_t yoffset, int32_t xsize, int32_t ysize, uint32_t dwRop)
+{
+ if((pDib)&&(hdc)) {
+ //palette must be correctly filled
+#if !defined (_WIN32_WCE)
+ SetStretchBltMode(hdc,COLORONCOLOR);
+#endif
+ StretchDIBits(hdc, xoffset, yoffset,
+ xsize, ysize, 0, 0, head.biWidth, head.biHeight,
+ info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS,dwRop);
+ return 1;
+ }
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Tiles the device context in the specified rectangle with the image.
+ * \param hdc : destination device context
+ * \param rc : tiled rectangle in the output device context
+ * \return true if everything is ok
+ */
+int32_t CxImage::Tile(HDC hdc, RECT *rc)
+{
+ if((pDib)&&(hdc)&&(rc)) {
+ int32_t w = rc->right - rc->left;
+ int32_t h = rc->bottom - rc->top;
+ int32_t x,y,z;
+ int32_t bx=head.biWidth;
+ int32_t by=head.biHeight;
+ for (y = 0 ; y < h ; y += by){
+ if ((y+by)>h) by=h-y;
+ z=bx;
+ for (x = 0 ; x < w ; x += z){
+ if ((x+z)>w) z=w-x;
+ RECT r = {rc->left + x,rc->top + y,rc->left + x + z,rc->top + y + by};
+ Draw(hdc,rc->left + x, rc->top + y,-1,-1,&r);
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+// For UNICODE support: char -> TCHAR
+int32_t CxImage::DrawString(HDC hdc, int32_t x, int32_t y, const TCHAR* text, RGBQUAD color, const TCHAR* font, int32_t lSize, int32_t lWeight, uint8_t bItalic, uint8_t bUnderline, bool bSetAlpha)
+//int32_t CxImage::DrawString(HDC hdc, int32_t x, int32_t y, const char* text, RGBQUAD color, const char* font, int32_t lSize, int32_t lWeight, uint8_t bItalic, uint8_t bUnderline, bool bSetAlpha)
+{
+ if (IsValid()){
+ //get the background
+ HDC pDC;
+ if (hdc) pDC=hdc; else pDC = ::GetDC(0);
+ if (pDC==NULL) return 0;
+ HDC TmpDC=CreateCompatibleDC(pDC);
+ if (hdc==NULL) ::ReleaseDC(0, pDC);
+ if (TmpDC==NULL) return 0;
+ //choose the font
+ HFONT m_Font;
+ LOGFONT* m_pLF;
+ m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));
+ _tcsncpy(m_pLF->lfFaceName,font,31); // For UNICODE support
+ //strncpy(m_pLF->lfFaceName,font,31);
+ m_pLF->lfHeight=lSize;
+ m_pLF->lfWeight=lWeight;
+ m_pLF->lfItalic=bItalic;
+ m_pLF->lfUnderline=bUnderline;
+ m_Font=CreateFontIndirect(m_pLF);
+ //select the font in the dc
+ HFONT pOldFont=NULL;
+ if (m_Font)
+ pOldFont = (HFONT)SelectObject(TmpDC,m_Font);
+ else
+ pOldFont = (HFONT)SelectObject(TmpDC,GetStockObject(DEFAULT_GUI_FONT));
+
+ //Set text color
+ SetTextColor(TmpDC,RGB(255,255,255));
+ SetBkColor(TmpDC,RGB(0,0,0));
+ //draw the text
+ SetBkMode(TmpDC,OPAQUE);
+ //Set text position;
+ RECT pos = {0,0,0,0};
+ //int32_t len = (int32_t)strlen(text);
+ int32_t len = (int32_t)_tcslen(text); // For UNICODE support
+ ::DrawText(TmpDC,text,len,&pos,DT_CALCRECT);
+ pos.right+=pos.bottom; //for italics
+
+ //Preparing Bitmap Info
+ int32_t width=pos.right;
+ int32_t height=pos.bottom;
+ BITMAPINFO bmInfo;
+ memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ bmInfo.bmiHeader.biWidth=width;
+ bmInfo.bmiHeader.biHeight=height;
+ bmInfo.bmiHeader.biPlanes=1;
+ bmInfo.bmiHeader.biBitCount=24;
+ uint8_t *pbase; //points to the final dib
+
+ HBITMAP TmpBmp=CreateDIBSection(TmpDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
+ HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
+ memset(pbase,0,height*((((24 * width) + 31) / 32) * 4));
+
+ ::DrawText(TmpDC,text,len,&pos,0);
+
+ CxImage itext;
+ itext.CreateFromHBITMAP(TmpBmp);
+
+ y=head.biHeight-y-1;
+ for (int32_t ix=0;ix<width;ix++){
+ for (int32_t iy=0;iy<height;iy++){
+ if (itext.GetPixelColor(ix,iy).rgbBlue) SetPixelColor(x+ix,y+iy,color,bSetAlpha);
+ }
+ }
+
+ //cleanup
+ if (pOldFont) SelectObject(TmpDC,pOldFont);
+ DeleteObject(m_Font);
+ free(m_pLF);
+ DeleteObject(SelectObject(TmpDC,TmpObj));
+ DeleteDC(TmpDC);
+ }
+
+ return 1;
+}
+////////////////////////////////////////////////////////////////////////////////
+// <VATI>
+int32_t CxImage::DrawStringEx(HDC hdc, int32_t x, int32_t y, CXTEXTINFO *pTextType, bool bSetAlpha )
+{
+ if (!IsValid())
+ return -1;
+
+ //get the background
+ HDC pDC;
+ if (hdc) pDC=hdc; else pDC = ::GetDC(0);
+ if (pDC==NULL) return 0;
+ HDC TmpDC=CreateCompatibleDC(pDC);
+ if (hdc==NULL) ::ReleaseDC(0, pDC);
+ if (TmpDC==NULL) return 0;
+
+ //choose the font
+ HFONT m_Font;
+ m_Font=CreateFontIndirect( &pTextType->lfont );
+
+ // get colors in RGBQUAD
+ RGBQUAD p_forecolor = RGBtoRGBQUAD(pTextType->fcolor);
+ RGBQUAD p_backcolor = RGBtoRGBQUAD(pTextType->bcolor);
+
+ // check alignment and re-set default if necessary
+ if ( pTextType->align != DT_CENTER &&
+ pTextType->align != DT_LEFT &&
+ pTextType->align != DT_RIGHT )
+ pTextType->align = DT_CENTER;
+
+ // check rounding radius and re-set default if necessary
+ if ( pTextType->b_round > 50 )
+ pTextType->b_round = 10;
+
+ // check opacity and re-set default if necessary
+ if ( pTextType->b_opacity > 1. || pTextType->b_opacity < .0 )
+ pTextType->b_opacity = 0.;
+
+ //select the font in the dc
+ HFONT pOldFont=NULL;
+ if (m_Font)
+ pOldFont = (HFONT)SelectObject(TmpDC,m_Font);
+ else
+ pOldFont = (HFONT)SelectObject(TmpDC,GetStockObject(DEFAULT_GUI_FONT));
+
+ //Set text color
+ SetTextColor(TmpDC,RGB(255,255,255));
+ SetBkColor(TmpDC,RGB(0,0,0));
+ SetBkMode(TmpDC,OPAQUE);
+ //Set text position;
+ RECT pos = {0,0,0,0};
+
+ // get text length and number of lines
+ int32_t i=0, numlines=1, len=(int32_t)_tcsclen(pTextType->text);
+ while (i<len)
+ {
+ if ( pTextType->text[i++]==13 )
+ numlines++;
+ }
+
+ ::DrawText(TmpDC, pTextType->text, len, &pos, /*DT_EDITCONTROL|DT_EXTERNALLEADING|*/DT_NOPREFIX | DT_CALCRECT );
+
+ // increase only if it's really italics, and only one line height
+ if ( pTextType->lfont.lfItalic )
+ pos.right += pos.bottom/2/numlines;
+
+ // background frame and rounding radius
+ int32_t frame = 0, roundR = 0;
+ if ( pTextType->opaque )
+ {
+ roundR= (int32_t)(pos.bottom/numlines * pTextType->b_round / 100 ) ;
+ frame = (int32_t)(/*3.5 + */0.29289*roundR ) ;
+ pos.right += pos.bottom/numlines/3 ; // JUST FOR BEAUTY
+ }
+
+ //Preparing Bitmap Info
+ int32_t width=pos.right +frame*2;
+ int32_t height=pos.bottom +frame*2;
+ BITMAPINFO bmInfo;
+ memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ bmInfo.bmiHeader.biWidth=width;
+ bmInfo.bmiHeader.biHeight=height;
+ bmInfo.bmiHeader.biPlanes=1;
+ bmInfo.bmiHeader.biBitCount=24;
+ uint8_t *pbase; //points to the final dib
+
+ HBITMAP TmpBmp=CreateDIBSection(TmpDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
+ HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
+ memset(pbase,0,height*((((24 * width) + 31) / 32) * 4));
+
+ ::DrawText(TmpDC,pTextType->text,len, &pos, /*DT_EDITCONTROL|DT_EXTERNALLEADING|*/DT_NOPREFIX| pTextType->align );
+
+ CxImage itext;
+ itext.CreateFromHBITMAP(TmpBmp);
+ y=head.biHeight-y-1;
+
+ itext.Negative();
+
+#if CXIMAGE_SUPPORT_DSP
+ if (pTextType->smooth==FALSE){
+ itext.Threshold(128);
+ } else {
+ //itext.TextBlur();
+ }
+#endif
+
+ //move the insertion point according to alignment type
+ // DT_CENTER: cursor points to the center of text rectangle
+ // DT_RIGHT: cursor points to right side end of text rectangle
+ // DT_LEFT: cursor points to left end of text rectangle
+ if ( pTextType->align == DT_CENTER )
+ x -= width/2;
+ else if ( pTextType->align == DT_RIGHT )
+ x -= width;
+ if (x<0) x=0;
+
+ //draw the background first, if it exists
+ int32_t ix,iy;
+ if ( pTextType->opaque )
+ {
+ int32_t ixf=0;
+ for (ix=0;ix<width;ix++)
+ {
+ if ( ix<=roundR )
+ ixf = (int32_t)(.5+roundR-sqrt((float)(roundR*roundR-(ix-roundR)*(ix-roundR))));
+ else if ( ix>=width-roundR-1 )
+ ixf = (int32_t)(.5+roundR-sqrt((float)(roundR*roundR-(width-1-ix-roundR)*(width-1-ix-roundR))));
+ else
+ ixf=0;
+
+ for (iy=0;iy<height;iy++)
+ {
+ if ( (ix<=roundR && ( iy > height-ixf-1 || iy < ixf )) ||
+ (ix>=width-roundR-1 && ( iy > height-ixf-1 || iy < ixf )) )
+ continue;
+ else
+ if ( pTextType->b_opacity > 0.0 && pTextType->b_opacity < 1.0 )
+ {
+ RGBQUAD bcolor, pcolor;
+ // calculate a transition color from original image to background color:
+ pcolor = GetPixelColor(x+ix,y+iy);
+ bcolor.rgbBlue = (uint8_t)(pTextType->b_opacity * pcolor.rgbBlue + (1.0-pTextType->b_opacity) * p_backcolor.rgbBlue );
+ bcolor.rgbRed = (uint8_t)(pTextType->b_opacity * pcolor.rgbRed + (1.0-pTextType->b_opacity) * p_backcolor.rgbRed ) ;
+ bcolor.rgbGreen = (uint8_t)(pTextType->b_opacity * pcolor.rgbGreen + (1.0-pTextType->b_opacity) * p_backcolor.rgbGreen ) ;
+ bcolor.rgbReserved = 0;
+ SetPixelColor(x+ix,y+iy,bcolor,bSetAlpha);
+ }
+ else
+ SetPixelColor(x+ix,y+iy,p_backcolor,bSetAlpha);
+ }
+ }
+ }
+
+ // draw the text itself
+ for (ix=0;ix<width;ix++)
+ {
+ for (iy=0;iy<height;iy++)
+ {
+ RGBQUAD pcolor = GetPixelColor(x+ix,y+iy);
+ RGBQUAD tcolor = itext.GetPixelColor(ix,iy);
+ if (tcolor.rgbBlue!=255){
+ float a = tcolor.rgbBlue/255.0f;
+ pcolor.rgbBlue = (uint8_t)(a * (pcolor.rgbBlue - p_forecolor.rgbBlue) + p_forecolor.rgbBlue );
+ pcolor.rgbRed = (uint8_t)(a * (pcolor.rgbRed - p_forecolor.rgbRed) + p_forecolor.rgbRed ) ;
+ pcolor.rgbGreen = (uint8_t)(a * (pcolor.rgbGreen - p_forecolor.rgbGreen) + p_forecolor.rgbGreen );
+ pcolor.rgbReserved = 0;
+ SetPixelColor(x+ix+frame,y+iy-frame,pcolor,bSetAlpha);
+ //SetPixelColor(x+ix+frame,y+iy-frame,p_forecolor,bSetAlpha);
+ }
+ }
+ }
+
+ //cleanup
+ if (pOldFont) SelectObject(TmpDC,pOldFont);
+ DeleteObject(m_Font);
+ DeleteObject(SelectObject(TmpDC,TmpObj));
+ DeleteDC(TmpDC);
+ return 1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+void CxImage::InitTextInfo( CXTEXTINFO *txt )
+{
+
+ memset( txt, 0, sizeof(CXTEXTINFO));
+
+ // LOGFONT defaults
+ txt->lfont.lfHeight = -36;
+ txt->lfont.lfCharSet = EASTEUROPE_CHARSET; // just for Central-European users
+ txt->lfont.lfWeight = FW_NORMAL;
+ txt->lfont.lfWidth = 0;
+ txt->lfont.lfEscapement = 0;
+ txt->lfont.lfOrientation = 0;
+ txt->lfont.lfItalic = FALSE;
+ txt->lfont.lfUnderline = FALSE;
+ txt->lfont.lfStrikeOut = FALSE;
+ txt->lfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ txt->lfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ txt->lfont.lfQuality = PROOF_QUALITY;
+ txt->lfont.lfPitchAndFamily= DEFAULT_PITCH | FF_DONTCARE ;
+ _stprintf( txt->lfont.lfFaceName, _T("Arial")); //use TCHAR mappings <Cesar M>
+
+ // initial colors
+ txt->fcolor = RGB( 255,255,160 ); // default foreground: light goldyellow
+ txt->bcolor = RGB( 0, 80,160 ); // default background: light blue
+
+ // background
+ txt->opaque = TRUE; // text has a non-transparent background;
+ txt->smooth = TRUE;
+ txt->b_opacity = 0.0; // default: opaque background
+ txt->b_outline = 0; // default: no outline (OUTLINE NOT IMPLEMENTED AT THIS TIME)
+ txt->b_round = 20; // default: rounding radius is 20% of the rectangle height
+ // the text
+ _stprintf( txt->text, _T("Sample Text 01234õû")); // text use TCHAR mappings <Cesar M>
+ txt->align = DT_CENTER;
+ return;
+}
+
+#if CXIMAGE_SUPPORT_LAYERS
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImage::LayerDrawAll(HDC hdc, const RECT& rect, RECT* pClipRect, bool bSmooth)
+{
+ return LayerDrawAll(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pClipRect,bSmooth);
+}
+////////////////////////////////////////////////////////////////////////////////
+int32_t CxImage::LayerDrawAll(HDC hdc, int32_t x, int32_t y, int32_t cx, int32_t cy, RECT* pClipRect, bool bSmooth)
+{
+ int32_t n=0;
+ CxImage* pLayer;
+ while(pLayer=GetLayer(n++)){
+ if (pLayer->Draw(hdc,x+pLayer->info.xOffset,y+pLayer->info.yOffset,cx,cy,pClipRect,bSmooth)==0)
+ return 0;
+ if (pLayer->LayerDrawAll(hdc,x+pLayer->info.xOffset,y+pLayer->info.yOffset,cx,cy,pClipRect,bSmooth)==0)
+ return 0;
+ }
+ return 1;
+}
+#endif //CXIMAGE_SUPPORT_LAYERS
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_WINDOWS
+////////////////////////////////////////////////////////////////////////////////
diff --git a/archive/hge/CxImage/xiofile.h b/archive/hge/CxImage/xiofile.h new file mode 100644 index 0000000..e05811e --- /dev/null +++ b/archive/hge/CxImage/xiofile.h @@ -0,0 +1,125 @@ +#if !defined(__xiofile_h)
+#define __xiofile_h
+
+#include "xfile.h"
+//#include <TCHAR.h>
+
+class DLL_EXP CxIOFile : public CxFile
+ {
+public:
+ CxIOFile(FILE* fp = NULL)
+ {
+ m_fp = fp;
+ m_bCloseFile = (bool)(fp==0);
+ }
+
+ ~CxIOFile()
+ {
+ Close();
+ }
+//////////////////////////////////////////////////////////
+ bool Open(const TCHAR * filename, const TCHAR * mode)
+ {
+ if (m_fp) return false; // Can't re-open without closing first
+
+ m_fp = fopen(filename, mode);
+ if (!m_fp) return false;
+
+ m_bCloseFile = true;
+
+ return true;
+ }
+//////////////////////////////////////////////////////////
+ virtual bool Close()
+ {
+ int32_t iErr = 0;
+ if ( (m_fp) && (m_bCloseFile) ){
+ iErr = fclose(m_fp);
+ m_fp = NULL;
+ }
+ return (bool)(iErr==0);
+ }
+//////////////////////////////////////////////////////////
+ virtual size_t Read(void *buffer, size_t size, size_t count)
+ {
+ if (!m_fp) return 0;
+ return fread(buffer, size, count, m_fp);
+ }
+//////////////////////////////////////////////////////////
+ virtual size_t Write(const void *buffer, size_t size, size_t count)
+ {
+ if (!m_fp) return 0;
+ return fwrite(buffer, size, count, m_fp);
+ }
+//////////////////////////////////////////////////////////
+ virtual bool Seek(int32_t offset, int32_t origin)
+ {
+ if (!m_fp) return false;
+ return (bool)(fseek(m_fp, offset, origin) == 0);
+ }
+//////////////////////////////////////////////////////////
+ virtual int32_t Tell()
+ {
+ if (!m_fp) return 0;
+ return ftell(m_fp);
+ }
+//////////////////////////////////////////////////////////
+ virtual int32_t Size()
+ {
+ if (!m_fp) return -1;
+ int32_t pos,size;
+ pos = ftell(m_fp);
+ fseek(m_fp, 0, SEEK_END);
+ size = ftell(m_fp);
+ fseek(m_fp, pos,SEEK_SET);
+ return size;
+ }
+//////////////////////////////////////////////////////////
+ virtual bool Flush()
+ {
+ if (!m_fp) return false;
+ return (bool)(fflush(m_fp) == 0);
+ }
+//////////////////////////////////////////////////////////
+ virtual bool Eof()
+ {
+ if (!m_fp) return true;
+ return (bool)(feof(m_fp) != 0);
+ }
+//////////////////////////////////////////////////////////
+ virtual int32_t Error()
+ {
+ if (!m_fp) return -1;
+ return ferror(m_fp);
+ }
+//////////////////////////////////////////////////////////
+ virtual bool PutC(uint8_t c)
+ {
+ if (!m_fp) return false;
+ return (bool)(fputc(c, m_fp) == c);
+ }
+//////////////////////////////////////////////////////////
+ virtual int32_t GetC()
+ {
+ if (!m_fp) return EOF;
+ return getc(m_fp);
+ }
+//////////////////////////////////////////////////////////
+ virtual char * GetS(char *string, int32_t n)
+ {
+ if (!m_fp) return NULL;
+ return fgets(string,n,m_fp);
+ }
+//////////////////////////////////////////////////////////
+ virtual int32_t Scanf(const char *format, void* output)
+ {
+ if (!m_fp) return EOF;
+ return fscanf(m_fp, format, output);
+ }
+//////////////////////////////////////////////////////////
+protected:
+ FILE *m_fp;
+ bool m_bCloseFile;
+ };
+
+#endif
diff --git a/archive/hge/CxImage/xmemfile.cpp b/archive/hge/CxImage/xmemfile.cpp new file mode 100644 index 0000000..f235899 --- /dev/null +++ b/archive/hge/CxImage/xmemfile.cpp @@ -0,0 +1,213 @@ +#include "xmemfile.h"
+
+//////////////////////////////////////////////////////////
+CxMemFile::CxMemFile(uint8_t* pBuffer, uint32_t size)
+{
+ m_pBuffer = pBuffer;
+ m_Position = 0;
+ m_Size = m_Edge = size;
+ m_bFreeOnClose = (bool)(pBuffer==0);
+ m_bEOF = false;
+}
+//////////////////////////////////////////////////////////
+CxMemFile::~CxMemFile()
+{
+ Close();
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::Close()
+{
+ if ( (m_pBuffer) && (m_bFreeOnClose) ){
+ free(m_pBuffer);
+ m_pBuffer = NULL;
+ m_Size = 0;
+ }
+ return true;
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::Open()
+{
+ if (m_pBuffer) return false; // Can't re-open without closing first
+
+ m_Position = m_Size = m_Edge = 0;
+ m_pBuffer=(uint8_t*)malloc(1);
+ m_bFreeOnClose = true;
+
+ return (m_pBuffer!=0);
+}
+//////////////////////////////////////////////////////////
+uint8_t* CxMemFile::GetBuffer(bool bDetachBuffer)
+{
+ //can only detach, avoid inadvertantly attaching to
+ // memory that may not be ours [Jason De Arte]
+ if( bDetachBuffer )
+ m_bFreeOnClose = false;
+ return m_pBuffer;
+}
+//////////////////////////////////////////////////////////
+size_t CxMemFile::Read(void *buffer, size_t size, size_t count)
+{
+ if (buffer==NULL) return 0;
+
+ if (m_pBuffer==NULL) return 0;
+ if (m_Position >= (int32_t)m_Size){
+ m_bEOF = true;
+ return 0;
+ }
+
+ int32_t nCount = (int32_t)(count*size);
+ if (nCount == 0) return 0;
+
+ int32_t nRead;
+ if (m_Position + nCount > (int32_t)m_Size){
+ m_bEOF = true;
+ nRead = (m_Size - m_Position);
+ } else
+ nRead = nCount;
+
+ memcpy(buffer, m_pBuffer + m_Position, nRead);
+ m_Position += nRead;
+
+ return (size_t)(nRead/size);
+}
+//////////////////////////////////////////////////////////
+size_t CxMemFile::Write(const void *buffer, size_t size, size_t count)
+{
+ m_bEOF = false;
+ if (m_pBuffer==NULL) return 0;
+ if (buffer==NULL) return 0;
+
+ int32_t nCount = (int32_t)(count*size);
+ if (nCount == 0) return 0;
+
+ if (m_Position + nCount > m_Edge){
+ if (!Alloc(m_Position + nCount)){
+ return false;
+ }
+ }
+
+ memcpy(m_pBuffer + m_Position, buffer, nCount);
+
+ m_Position += nCount;
+
+ if (m_Position > (int32_t)m_Size) m_Size = m_Position;
+
+ return count;
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::Seek(int32_t offset, int32_t origin)
+{
+ m_bEOF = false;
+ if (m_pBuffer==NULL) return false;
+ int32_t lNewPos = m_Position;
+
+ if (origin == SEEK_SET) lNewPos = offset;
+ else if (origin == SEEK_CUR) lNewPos += offset;
+ else if (origin == SEEK_END) lNewPos = m_Size + offset;
+ else return false;
+
+ if (lNewPos < 0) lNewPos = 0;
+
+ m_Position = lNewPos;
+ return true;
+}
+//////////////////////////////////////////////////////////
+int32_t CxMemFile::Tell()
+{
+ if (m_pBuffer==NULL) return -1;
+ return m_Position;
+}
+//////////////////////////////////////////////////////////
+int32_t CxMemFile::Size()
+{
+ if (m_pBuffer==NULL) return -1;
+ return m_Size;
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::Flush()
+{
+ if (m_pBuffer==NULL) return false;
+ return true;
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::Eof()
+{
+ if (m_pBuffer==NULL) return true;
+ return m_bEOF;
+}
+//////////////////////////////////////////////////////////
+int32_t CxMemFile::Error()
+{
+ if (m_pBuffer==NULL) return -1;
+ return (m_Position > (int32_t)m_Size);
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::PutC(uint8_t c)
+{
+ m_bEOF = false;
+ if (m_pBuffer==NULL) return false;
+
+ if (m_Position >= m_Edge){
+ if (!Alloc(m_Position + 1)){
+ return false;
+ }
+ }
+
+ m_pBuffer[m_Position++] = c;
+
+ if (m_Position > (int32_t)m_Size) m_Size = m_Position;
+
+ return true;
+}
+//////////////////////////////////////////////////////////
+int32_t CxMemFile::GetC()
+{
+ if (m_pBuffer==NULL || m_Position >= (int32_t)m_Size){
+ m_bEOF = true;
+ return EOF;
+ }
+ return *(uint8_t*)((uint8_t*)m_pBuffer + m_Position++);
+}
+//////////////////////////////////////////////////////////
+char * CxMemFile::GetS(char *string, int32_t n)
+{
+ n--;
+ int32_t c,i=0;
+ while (i<n){
+ c = GetC();
+ if (c == EOF) return 0;
+ string[i++] = (char)c;
+ if (c == '\n') break;
+ }
+ string[i] = 0;
+ return string;
+}
+//////////////////////////////////////////////////////////
+int32_t CxMemFile::Scanf(const char *format, void* output)
+{
+ return 0;
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::Alloc(uint32_t dwNewLen)
+{
+ if (dwNewLen > (uint32_t)m_Edge)
+ {
+ // find new buffer size
+ uint32_t dwNewBufferSize = (uint32_t)(((dwNewLen>>16)+1)<<16);
+
+ // allocate new buffer
+ if (m_pBuffer == NULL) m_pBuffer = (uint8_t*)malloc(dwNewBufferSize);
+ else m_pBuffer = (uint8_t*)realloc(m_pBuffer, dwNewBufferSize);
+ // I own this buffer now (caller knows nothing about it)
+ m_bFreeOnClose = true;
+
+ m_Edge = dwNewBufferSize;
+ }
+ return (m_pBuffer!=0);
+}
+//////////////////////////////////////////////////////////
+void CxMemFile::Free()
+{
+ Close();
+}
+//////////////////////////////////////////////////////////
diff --git a/archive/hge/CxImage/xmemfile.h b/archive/hge/CxImage/xmemfile.h new file mode 100644 index 0000000..e132db3 --- /dev/null +++ b/archive/hge/CxImage/xmemfile.h @@ -0,0 +1,42 @@ +#if !defined(__xmemfile_h)
+#define __xmemfile_h
+
+#include "xfile.h"
+
+//////////////////////////////////////////////////////////
+class DLL_EXP CxMemFile : public CxFile
+{
+public:
+ CxMemFile(uint8_t* pBuffer = NULL, uint32_t size = 0);
+ ~CxMemFile();
+
+ bool Open();
+ uint8_t* GetBuffer(bool bDetachBuffer = true);
+
+ virtual bool Close();
+ virtual size_t Read(void *buffer, size_t size, size_t count);
+ virtual size_t Write(const void *buffer, size_t size, size_t count);
+ virtual bool Seek(int32_t offset, int32_t origin);
+ virtual int32_t Tell();
+ virtual int32_t Size();
+ virtual bool Flush();
+ virtual bool Eof();
+ virtual int32_t Error();
+ virtual bool PutC(uint8_t c);
+ virtual int32_t GetC();
+ virtual char * GetS(char *string, int32_t n);
+ virtual int32_t Scanf(const char *format, void* output);
+
+protected:
+ bool Alloc(uint32_t nBytes);
+ void Free();
+
+ uint8_t* m_pBuffer;
+ uint32_t m_Size;
+ bool m_bFreeOnClose;
+ int32_t m_Position; //current position
+ int32_t m_Edge; //buffer size
+ bool m_bEOF;
+};
+
+#endif
diff --git a/archive/hge/ZLIB/adler32.c b/archive/hge/ZLIB/adler32.c new file mode 100644 index 0000000..65ad6a5 --- /dev/null +++ b/archive/hge/ZLIB/adler32.c @@ -0,0 +1,169 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2007 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#define local static + +local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); + +#define BASE 65521UL /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware */ +#ifdef NO_DIVIDE +# define MOD(a) \ + do { \ + if (a >= (BASE << 16)) a -= (BASE << 16); \ + if (a >= (BASE << 15)) a -= (BASE << 15); \ + if (a >= (BASE << 14)) a -= (BASE << 14); \ + if (a >= (BASE << 13)) a -= (BASE << 13); \ + if (a >= (BASE << 12)) a -= (BASE << 12); \ + if (a >= (BASE << 11)) a -= (BASE << 11); \ + if (a >= (BASE << 10)) a -= (BASE << 10); \ + if (a >= (BASE << 9)) a -= (BASE << 9); \ + if (a >= (BASE << 8)) a -= (BASE << 8); \ + if (a >= (BASE << 7)) a -= (BASE << 7); \ + if (a >= (BASE << 6)) a -= (BASE << 6); \ + if (a >= (BASE << 5)) a -= (BASE << 5); \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD4(a) \ + do { \ + if (a >= (BASE << 4)) a -= (BASE << 4); \ + if (a >= (BASE << 3)) a -= (BASE << 3); \ + if (a >= (BASE << 2)) a -= (BASE << 2); \ + if (a >= (BASE << 1)) a -= (BASE << 1); \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD4(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD4(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* the derivation of this formula is left as an exercise for the reader */ + rem = (unsigned)(len2 % BASE); + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/archive/hge/ZLIB/crc32.c b/archive/hge/ZLIB/crc32.c new file mode 100644 index 0000000..91be372 --- /dev/null +++ b/archive/hge/ZLIB/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + */ + +#ifdef MAKECRCH +# include <stdio.h> +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +#define local static + +/* Find a four-byte integer type for crc32_little() and crc32_big(). */ +#ifndef NOBYFOUR +# ifdef STDC /* need ANSI C limits.h to determine sizes */ +# include <limits.h> +# define BYFOUR +# if (UINT_MAX == 0xffffffffUL) + typedef unsigned int u4; +# else +# if (ULONG_MAX == 0xffffffffUL) + typedef unsigned long u4; +# else +# if (USHRT_MAX == 0xffffffffUL) + typedef unsigned short u4; +# else +# undef BYFOUR /* can't find a four-byte integer type! */ +# endif +# endif +# endif +# endif /* STDC */ +#endif /* !NOBYFOUR */ + +/* Definitions for doing the crc four data bytes at a time. */ +#ifdef BYFOUR +# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ + (((w)&0xff00)<<8)+(((w)&0xff)<<24)) + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, unsigned)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, unsigned)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local unsigned long FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const unsigned long FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + unsigned long c; + int n, k; + unsigned long poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0UL; + for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) + poly |= 1UL << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (unsigned long)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = REV(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = REV(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const unsigned long FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const unsigned long FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const unsigned long FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const unsigned long FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + u4 endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +#ifdef BYFOUR + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = (u4)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *++buf4; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + unsigned len; +{ + register u4 c; + register const u4 FAR *buf4; + + c = REV((u4)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const u4 FAR *)(const void FAR *)buf; + buf4--; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf4++; + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(REV(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/archive/hge/ZLIB/crc32.h b/archive/hge/ZLIB/crc32.h new file mode 100644 index 0000000..8053b61 --- /dev/null +++ b/archive/hge/ZLIB/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/archive/hge/ZLIB/crypt.h b/archive/hge/ZLIB/crypt.h new file mode 100644 index 0000000..c01e587 --- /dev/null +++ b/archive/hge/ZLIB/crypt.h @@ -0,0 +1,136 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + +Version 1.01, May 8th, 2004 + +Copyright (C) 1998-2004 Gilles Vollant + +This code is a modified version of crypting code in Infozip distribution + +The encryption/decryption parts of this source code (as opposed to the +non-echoing password parts) were originally written in Europe. The +whole source package can be freely distributed, including from the USA. +(Prior to January 2000, re-export from the US was a violation of US law.) + +This encryption code is a direct transcription of the algorithm from +Roger Schlafly, described by Phil Katz in the file appnote.txt. This +file (appnote.txt) is distributed with the PKZIP program (even in the +version without encryption capabilities). + +If you don't need crypting in your application, just define symbols +NOCRYPT and NOUNCRYPT. + +This code support the "Traditional PKWARE Encryption". + +The new AES encryption added on Zip format by Winzip (see the page +http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong +Encryption is not supported. + */ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long *pkeys, const unsigned long *pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys + 2)) &0xffff) | 2; + return (int)(((temp *(temp ^ 1)) >> 8) &0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long *pkeys, const unsigned long *pcrc_32_tab, int c) +{ + (*(pkeys + 0)) = CRC32((*(pkeys + 0)), c); + (*(pkeys + 1)) += (*(pkeys + 0)) &0xff; + (*(pkeys + 1)) = (*(pkeys + 1)) *134775813L + 1; + { + register int keyshift = (int)((*(pkeys + 1)) >> 24); + (*(pkeys + 2)) = CRC32((*(pkeys + 2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char *passwd, unsigned long *pkeys, const unsigned long *pcrc_32_tab) +{ + *(pkeys + 0) = 305419896L; + *(pkeys + 1) = 591751049L; + *(pkeys + 2) = 878082192L; + while (*passwd != '\0') + { + update_keys(pkeys, pcrc_32_tab, (int) *passwd); + passwd++; + } +} + +//------------------------------------------------------------------------- + +#define zdecode(pkeys,pcrc_32_tab,c) \ +(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ +(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + + #define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ + #ifndef ZCR_SEED2 + #define ZCR_SEED2 3141592654UL /* use PI as default pattern */ + #endif + + static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)const char *passwd; /* password string */ + unsigned char *buf; /* where to write header */ + int bufSize; + unsigned long *pkeys; + const unsigned long *pcrc_32_tab; + unsigned long crcForCrypting; + { + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN - 2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize < RAND_HEAD_LEN) + { + return 0; + } + + /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the + * output of rand() to get less predictability, since rand() is + * often poorly implemented. + */ + if (++calls == 1) + { + srand((unsigned)(time(NULL) ^ ZCR_SEED2)); + } + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN - 2; n++) + { + c = (rand() >> 7) &0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN - 2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) &0xff, t); + buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) &0xff, t); + return n; + } + +#endif diff --git a/archive/hge/ZLIB/deflate.h b/archive/hge/ZLIB/deflate.h new file mode 100644 index 0000000..cbf0d1e --- /dev/null +++ b/archive/hge/ZLIB/deflate.h @@ -0,0 +1,342 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2010 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/archive/hge/ZLIB/inffast.c b/archive/hge/ZLIB/inffast.c new file mode 100644 index 0000000..2f1d60b --- /dev/null +++ b/archive/hge/ZLIB/inffast.c @@ -0,0 +1,340 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2008, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifndef ASMINF + +/* Allow machine dependent optimization for post-increment or pre-increment. + Based on testing to date, + Pre-increment preferred for: + - PowerPC G3 (Adler) + - MIPS R5000 (Randers-Pehrson) + Post-increment preferred for: + - none + No measurable difference: + - Pentium III (Anderson) + - M68060 (Nikl) + */ +#ifdef POSTINC +# define OFF 0 +# define PUP(a) *(a)++ +#else +# define OFF 1 +# define PUP(a) *++(a) +#endif + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + unsigned char FAR *in; /* local strm->next_in */ + unsigned char FAR *last; /* while in < last, enough input available */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in - OFF; + last = in + (strm->avail_in - 5); + out = strm->next_out - OFF; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + PUP(out) = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(PUP(in)) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + PUP(out) = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + PUP(out) = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + PUP(out) = PUP(from); + } while (--len); + continue; + } +#endif + } + from = window - OFF; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = window - OFF; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + PUP(out) = PUP(from); + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + PUP(out) = PUP(from); + PUP(out) = PUP(from); + PUP(out) = PUP(from); + len -= 3; + } while (len > 2); + if (len) { + PUP(out) = PUP(from); + if (len > 1) + PUP(out) = PUP(from); + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in + OFF; + strm->next_out = out + OFF; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/archive/hge/ZLIB/inffast.h b/archive/hge/ZLIB/inffast.h new file mode 100644 index 0000000..e5c1aa4 --- /dev/null +++ b/archive/hge/ZLIB/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/archive/hge/ZLIB/inffixed.h b/archive/hge/ZLIB/inffixed.h new file mode 100644 index 0000000..75ed4b5 --- /dev/null +++ b/archive/hge/ZLIB/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/archive/hge/ZLIB/inflate.c b/archive/hge/ZLIB/inflate.c new file mode 100644 index 0000000..a8431ab --- /dev/null +++ b/archive/hge/ZLIB/inflate.c @@ -0,0 +1,1480 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, unsigned out)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, + unsigned len)); + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + strm->adler = 1; /* to support ill-conceived Java test suite */ + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->window = Z_NULL; + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += value << state->bits; + state->bits += bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include <stdio.h> + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, + state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, out) +z_streamp strm; +unsigned out; +{ + struct inflate_state FAR *state; + unsigned copy, dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + copy = out - strm->avail_out; + if (copy >= state->wsize) { + zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, strm->next_out - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Reverse the bytes in a 32-bit value */ +#define REVERSE(q) \ + ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + else if (len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if (state->flags & 0x0200) CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if (state->flags & 0x0200) CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = len; + } while (len && copy < have); + if (state->flags & 0x0200) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if (hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = REVERSE(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if (out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if (( +#ifdef GUNZIP + state->flags ? hold : +#endif + REVERSE(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) + if (updatewindow(strm, out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if (state->wrap && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long id; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary id */ + if (state->mode == DICT) { + id = adler32(0L, Z_NULL, 0); + id = adler32(id, dictionary, dictLength); + if (id != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window */ + if (updatewindow(strm, strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + if (dictLength > state->wsize) { + zmemcpy(state->window, dictionary + dictLength - state->wsize, + state->wsize); + state->whave = state->wsize; + } + else { + zmemcpy(state->window + state->wsize - dictLength, dictionary, + dictLength); + state->whave = dictLength; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || + source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy(dest, source, sizeof(z_stream)); + zmemcpy(copy, state, sizeof(struct inflate_state)); + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->sane = !subvert; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + return Z_OK; +#else + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + state = (struct inflate_state FAR *)strm->state; + return ((long)(state->back) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} diff --git a/archive/hge/ZLIB/inflate.h b/archive/hge/ZLIB/inflate.h new file mode 100644 index 0000000..95f4986 --- /dev/null +++ b/archive/hge/ZLIB/inflate.h @@ -0,0 +1,122 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2009 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 10K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/archive/hge/ZLIB/inftrees.c b/archive/hge/ZLIB/inftrees.c new file mode 100644 index 0000000..11e9c52 --- /dev/null +++ b/archive/hge/ZLIB/inftrees.c @@ -0,0 +1,330 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.5 Copyright 1995-2010 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + here.op = (unsigned char)(extra[work[sym]]); + here.val = base[work[sym]]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + here.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = here; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/archive/hge/ZLIB/inftrees.h b/archive/hge/ZLIB/inftrees.h new file mode 100644 index 0000000..baa53a0 --- /dev/null +++ b/archive/hge/ZLIB/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/archive/hge/ZLIB/ioapi.c b/archive/hge/ZLIB/ioapi.c new file mode 100644 index 0000000..9ac1985 --- /dev/null +++ b/archive/hge/ZLIB/ioapi.c @@ -0,0 +1,107 @@ +/* ioapi.c -- IO base function header for compress/uncompress .zip +files using zlib + zip or unzip API + +Version 1.01, May 8th, 2004 + +Copyright (C) 1998-2004 Gilles Vollant + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "zlib.h" +#include "ioapi.h" + + +void *ZCALLBACK fopen_file_func(void *opaque, const char *filename, int mode) +{ + FILE *file = NULL; + + const char *mode_fopen = NULL; + + if ((mode &ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) + { + mode_fopen = "rb"; + } + else + { + if (mode &ZLIB_FILEFUNC_MODE_EXISTING) + { + mode_fopen = "r+b"; + } + else + { + if (mode &ZLIB_FILEFUNC_MODE_CREATE) + { + mode_fopen = "wb"; + } + } + } + + if ((filename != NULL) && (mode_fopen != NULL)) + { + file = fopen(filename, mode_fopen); + } + return file; +} + +//------------------------------------------------------------------------- + + +DWORD ZCALLBACK fread_file_func(void *opaque, void *stream, void *buf, DWORD size) +{ + return fread(buf, 1, (size_t)size, (FILE*)stream); +} + +//------------------------------------------------------------------------- + + +DWORD ZCALLBACK fwrite_file_func(void *opaque, void *stream, const void *buf, DWORD size) +{ + return fwrite(buf, 1, (size_t)size, (FILE*)stream); +} + +//------------------------------------------------------------------------- + +long ZCALLBACK ftell_file_func(void *opaque, void *stream) +{ + return ftell((FILE*)stream); +} + +//------------------------------------------------------------------------- + +long ZCALLBACK fseek_file_func(void *opaque, void *stream, DWORD offset, int origin) +{ + fseek((FILE*)stream, offset, origin); + + return 0; +} + +//------------------------------------------------------------------------- + +int ZCALLBACK fclose_file_func(void *opaque, void *stream) +{ + return fclose((FILE*)stream); +} + +//------------------------------------------------------------------------- + +int ZCALLBACK ferror_file_func(void *opaque, void *stream) +{ + return ferror((FILE*)stream); +} + +//------------------------------------------------------------------------- + +void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/archive/hge/ZLIB/ioapi.h b/archive/hge/ZLIB/ioapi.h new file mode 100644 index 0000000..b2ffb14 --- /dev/null +++ b/archive/hge/ZLIB/ioapi.h @@ -0,0 +1,79 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip +files using zlib + zip or unzip API + +Version 1.01, May 8th, 2004 + +Copyright (C) 1998-2004 Gilles Vollant + */ + +#ifndef _ZLIBIOAPI_H + #define _ZLIBIOAPI_H + + + #define ZLIB_FILEFUNC_MODE_READ (1) + #define ZLIB_FILEFUNC_MODE_WRITE (2) + #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + + #define ZLIB_FILEFUNC_MODE_EXISTING (4) + #define ZLIB_FILEFUNC_MODE_CREATE (8) + + // begin ryan. + #ifndef DWORD + #define DWORD uInt + #endif + #ifndef BYTE + #define BYTE Byte + #endif + // end ryan. + + #ifndef ZCALLBACK + + #if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) + #define ZCALLBACK CALLBACK + #else + #define ZCALLBACK + #endif + #endif + + #ifdef __cplusplus + extern "C" + { + #endif + + typedef void *(ZCALLBACK *open_file_func)(void *opaque, const char *filename, int mode); + typedef DWORD(ZCALLBACK *read_file_func)(void *opaque, void *stream, void *buf, DWORD size); + typedef DWORD(ZCALLBACK *write_file_func)(void *opaque, void *stream, const void *buf, DWORD size); + typedef DWORD(ZCALLBACK *tell_file_func)(void *opaque, void *stream); + typedef DWORD(ZCALLBACK *seek_file_func)(void *opaque, void *stream, DWORD offset, int origin); + typedef int(ZCALLBACK *close_file_func)(void *opaque, void *stream); + typedef int(ZCALLBACK *testerror_file_func)(void *opaque, void *stream); + + typedef struct zlib_filefunc_def_s + { + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + void *opaque; + } zlib_filefunc_def; + + + + void fill_fopen_filefunc OF((zlib_filefunc_def *pzlib_filefunc_def)); + + #define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) + #define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) + #define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) + #define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) + #define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) + #define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) + + + #ifdef __cplusplus + } + #endif + +#endif diff --git a/archive/hge/ZLIB/trees.c b/archive/hge/ZLIB/trees.c new file mode 100644 index 0000000..56e9bb1 --- /dev/null +++ b/archive/hge/ZLIB/trees.c @@ -0,0 +1,1244 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2010 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include <ctype.h> +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1<<extra_lbits[code]); n++) { + _length_code[length++] = (uch)code; + } + } + Assert (length == 256, "tr_static_init: length != 256"); + /* Note that the length 255 (match length 258) can be represented + * in two different ways: code 284 + 5 bits or code 285, so we + * overwrite length_code[255] to use the best encoding: + */ + _length_code[length-1] = (uch)code; + + /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<<extra_dbits[code]); n++) { + _dist_code[dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: dist != 256"); + dist >>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include <stdio.h> +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, + "inconsistent bit counts"); + Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); + + for (n = 0; n <= max_code; n++) { + int len = tree[n].Len; + if (len == 0) continue; + /* Now reverse the bits */ + tree[n].Code = bi_reverse(next_code[len]++, len); + + Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", + n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); + } +} + +/* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ +local void build_tree(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/archive/hge/ZLIB/trees.h b/archive/hge/ZLIB/trees.h new file mode 100644 index 0000000..d35639d --- /dev/null +++ b/archive/hge/ZLIB/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/archive/hge/ZLIB/uncompr.c b/archive/hge/ZLIB/uncompr.c new file mode 100644 index 0000000..ad98be3 --- /dev/null +++ b/archive/hge/ZLIB/uncompr.c @@ -0,0 +1,59 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) + return Z_DATA_ERROR; + return err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/archive/hge/ZLIB/unzip.c b/archive/hge/ZLIB/unzip.c new file mode 100644 index 0000000..868f035 --- /dev/null +++ b/archive/hge/ZLIB/unzip.c @@ -0,0 +1,1592 @@ +/* unzip.c -- IO for uncompress .zip files using zlib +Version 1.01, May 8th, 2004 + +Copyright (C) 1998-2004 Gilles Vollant + +Read unzip.h for more info + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC + #include <stddef.h> + #include <string.h> + #include <stdlib.h> +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else + #include <errno.h> +#endif + +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO + #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) + #define CASESENSITIVITYDEFAULT_NO + #endif +#endif + + +#ifndef UNZ_BUFSIZE + #define UNZ_BUFSIZE (32768) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP + #define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC + #define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE + #define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ + +typedef struct unz_file_info_internal_s +{ + DWORD offset_curfile; /* relative offset of local header 4 bytes */ +} unz_file_info_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, +when reading and decompress it */ + +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + DWORD pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + DWORD stream_initialised; /* flag set if stream structure is initialised*/ + DWORD offset_local_extrafield; /* offset of the local extra field */ + DWORD size_local_extrafield; /* size of the local extra field */ + DWORD pos_local_extrafield; /* position in the local extra field in read*/ + DWORD crc32; /* crc32 of all data uncompressed */ + DWORD crc32_wait; /* crc32 we must obtain after decompress all */ + DWORD rest_read_compressed; /* number of byte to be decompressed */ + DWORD rest_read_uncompressed; /*number of byte to be obtained after decomp*/ + zlib_filefunc_def z_filefunc; + void *filestream; /* io structore of the zipfile */ + DWORD compression_method; /* compression method (0==store) */ + DWORD byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip_read_info_s; + + +/* unz_s contain internal information about the zipfile + */ +typedef struct +{ + zlib_filefunc_def z_filefunc; + void *filestream; /* io structore of the zipfile */ + unz_global_info gi; /* public global information */ + DWORD byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/ + DWORD num_file; /* number of the current file in the zipfile*/ + DWORD pos_in_central_dir; /* pos of the current file in the central dir*/ + DWORD current_file_ok; /* flag about the usability of the current file*/ + DWORD central_pos; /* position of the beginning of the central dir*/ + DWORD size_central_dir; /* size of the central directory */ + DWORD offset_central_dir; /* offset of start of central directory with respect to the starting disk number */ + unz_file_info cur_file_info; /* public info about the current file in zip*/ + unz_file_info_internal cur_file_info_internal; /* private info about it*/ + file_in_zip_read_info_s *pfile_in_zip_read; /* structure about the current file if we are decompressing it */ + int encrypted; + + #ifndef NOUNCRYPT + DWORD keys[3]; /* keys defining the pseudo-random sequence */ + const DWORD *pcrc_32_tab; + #endif + +} unz_s; + + +#ifndef NOUNCRYPT + #include "crypt.h" +#endif + +/* =========================================================================== +Read a byte from a gz_stream; update next_in and avail_in. Return EOF +for end of file. +IN assertion: the stream s has been sucessfully opened for reading. + */ + + +static int unzlocal_getByte(const zlib_filefunc_def *pzlib_filefunc_def, void *filestream, int *pi) +{ + BYTE c; + int err = (int)ZREAD(*pzlib_filefunc_def, filestream, &c, 1); + + if (err == 1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR(*pzlib_filefunc_def, filestream)) + { + return UNZ_ERRNO; + } + else + { + return UNZ_EOF; + } + } +} + + +/* =========================================================================== +Reads a long in LSB order from the given gz_stream. Sets + */ + +static int unzlocal_getShort(const zlib_filefunc_def *pzlib_filefunc_def, void *filestream, DWORD *pX) +{ + DWORD x; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i); + + x = (DWORD)i; + + if (err == UNZ_OK) + { + err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i); + } + + x += ((DWORD)i) << 8; + + if (err == UNZ_OK) + { + *pX = x; + } + else + { + *pX = 0; + } + + return err; +} + +//------------------------------------------------------------------------- + + +static int unzlocal_getLong(const zlib_filefunc_def *pzlib_filefunc_def, void *filestream, DWORD *pX) +{ + DWORD x; + int i; + int err; + + err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i); + x = (DWORD)i; + + if (err == UNZ_OK) + { + err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i); + } + x += ((DWORD)i) << 8; + + if (err == UNZ_OK) + { + err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i); + } + x += ((DWORD)i) << 16; + + if (err == UNZ_OK) + { + err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i); + } + x += ((DWORD)i) << 24; + + if (err == UNZ_OK) + { + *pX = x; + } + else + { + *pX = 0; + } + return err; +} + + +//------------------------------------------------------------------------- + + +#ifdef CASESENSITIVITYDEFAULT_NO + #define CASESENSITIVITYDEFAULTVALUE 2 +#else + #define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION + #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* +Compare two filename (fileName1,fileName2). +If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) +If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi +or strcasecmp) +If iCaseSenisivity = 0, case sensitivity is defaut of your operating system +(like 1 on Unix, 2 on Windows) +*/ +/* +extern int ZEXPORT unzStringFileNameCompare(const char *fileName1, const char *fileName2, int iCaseSensitivity) +{ + if (iCaseSensitivity == 0) + { + iCaseSensitivity = CASESENSITIVITYDEFAULTVALUE; + } + + if (iCaseSensitivity == 1) + { + return strcmp(fileName1, fileName2); + } + + return stricmp(fileName1, fileName2); +} +*/ +//------------------------------------------------------------------------- + +#ifndef BUFREADCOMMENT + #define BUFREADCOMMENT (0x400) +#endif + +/* +Locate the Central directory of a zipfile (at the end, just before +the global comment) + */ + +static DWORD unzlocal_SearchCentralDir(const zlib_filefunc_def *pzlib_filefunc_def, void *filestream) +{ + BYTE *buf; + DWORD uSizeFile; + DWORD uBackRead; + DWORD uMaxBack = 0xffff; /* maximum size of global comment */ + DWORD uPosFound = 0; + + if (ZSEEK(*pzlib_filefunc_def, filestream, 0, SEEK_END) != 0) + { + return 0; + } + + + uSizeFile = ZTELL(*pzlib_filefunc_def, filestream); + + if (uMaxBack > uSizeFile) + { + uMaxBack = uSizeFile; + } + + buf = (BYTE*)ALLOC(BUFREADCOMMENT + 4); + if (buf == NULL) + { + return 0; + } + + uBackRead = 4; + while (uBackRead < uMaxBack) + { + DWORD uReadSize, uReadPos; + int i; + if (uBackRead + BUFREADCOMMENT > uMaxBack) + { + uBackRead = uMaxBack; + } + else + { + uBackRead += BUFREADCOMMENT; + } + uReadPos = uSizeFile - uBackRead; + + uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ? (BUFREADCOMMENT + 4): (uSizeFile - uReadPos); + if (ZSEEK(*pzlib_filefunc_def, filestream, uReadPos, SEEK_SET) != 0) + { + break; + } + + if (ZREAD(*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize) + { + break; + } + + for (i = (int)uReadSize - 3; (i--) > 0;) + if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) && ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06)) + { + uPosFound = uReadPos + i; + break; + } + + if (uPosFound != 0) + { + break; + } + } + TRYFREE(buf); + return uPosFound; +} + +/* +Open a Zip file. path contain the full pathname (by example, +on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer +"zlib/zlib114.zip". +If the zipfile cannot be opened (file doesn't exist or in not valid), the +return value is NULL. +Else, the return value is a unzFile Handle, usable with other function +of this unzip package. + */ +extern unzFile ZEXPORT unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc_def) +{ + unz_s us; + unz_s *s; + DWORD central_pos, uL; + + DWORD number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + DWORD number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + DWORD number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err = UNZ_OK; + + if (pzlib_filefunc_def == NULL) + { + fill_fopen_filefunc(&us.z_filefunc); + } + else + { + us.z_filefunc = *pzlib_filefunc_def; + } + + us.filestream = (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream == NULL) + { + return NULL; + } + + central_pos = unzlocal_SearchCentralDir(&us.z_filefunc, us.filestream); + if (central_pos == 0) + { + err = UNZ_ERRNO; + } + + if (ZSEEK(us.z_filefunc, us.filestream, central_pos, SEEK_SET) != 0) + { + err = UNZ_ERRNO; + } + + /* the signature, already checked */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + /* number of this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream, &number_disk) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + /* number of the disk with the start of the central directory */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream, &number_disk_with_CD) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + /* total number of entries in the central dir on this disk */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream, &us.gi.number_entry) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + /* total number of entries in the central dir */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream, &number_entry_CD) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if ((number_entry_CD != us.gi.number_entry) || (number_disk_with_CD != 0) || (number_disk != 0)) + { + err = UNZ_BADZIPFILE; + } + + /* size of the central directory */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream, &us.size_central_dir) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + /* offset of start of central directory with respect to the + starting disk number */ + if (unzlocal_getLong(&us.z_filefunc, us.filestream, &us.offset_central_dir) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + /* zipfile comment length */ + if (unzlocal_getShort(&us.z_filefunc, us.filestream, &us.gi.size_comment) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if ((central_pos < us.offset_central_dir + us.size_central_dir) && (err == UNZ_OK)) + { + err = UNZ_BADZIPFILE; + } + + if (err != UNZ_OK) + { + ZCLOSE(us.z_filefunc, us.filestream); + return NULL; + } + + us.byte_before_the_zipfile = central_pos - (us.offset_central_dir + us.size_central_dir); + us.central_pos = central_pos; + us.pfile_in_zip_read = NULL; + us.encrypted = 0; + + + s = (unz_s*)ALLOC(sizeof(unz_s)); + *s = us; + unzGoToFirstFile((unzFile)s); + return (unzFile)s; +} + +//------------------------------------------------------------------------- + + +extern unzFile ZEXPORT unzOpen(const char *path) +{ + return unzOpen2(path, NULL); +} + +/* +Close a ZipFile opened with unzipOpen. +If there is files inside the .Zip opened with unzipOpenCurrentFile (see later), +these files MUST be closed with unzipCloseCurrentFile before call unzipClose. +return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzClose(unzFile file) +{ + unz_s *s; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + s = (unz_s*)file; + + if (s->pfile_in_zip_read != NULL) + { + unzCloseCurrentFile(file); + } + + ZCLOSE(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* +Write info about the ZipFile in the *pglobal_info structure. +No preparation of the structure is needed +return UNZ_OK if there is no problem. */ +/* +extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info) +{ + unz_s *s; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + *pglobal_info = s->gi; + return UNZ_OK; +} +*/ + +/* +Translate date/time from Dos format to tm_unz (readable more easilty) + */ + +static void unzlocal_DosDateToTmuDate(DWORD ulDosDate, tm_unz *ptm) +{ + DWORD uDate; + uDate = (DWORD)(ulDosDate >> 16); + ptm->tm_mday = (DWORD)(uDate &0x1f); + ptm->tm_mon = (DWORD)((((uDate) &0x1E0) / 0x20) - 1); + ptm->tm_year = (DWORD)(((uDate &0x0FE00) / 0x0200) + 1980); + + ptm->tm_hour = (DWORD)((ulDosDate &0xF800) / 0x800); + ptm->tm_min = (DWORD)((ulDosDate &0x7E0) / 0x20); + ptm->tm_sec = (DWORD)(2 *(ulDosDate &0x1f)); +} + +/* +Get Info about the current file in the zipfile, with internal only info + */ + +static int unzlocal_GetCurrentFileInfoInternal(unzFile file, unz_file_info *pfile_info, unz_file_info_internal *pfile_info_internal, char *szFileName, DWORD fileNameBufferSize, void *extraField, DWORD extraFieldBufferSize, char *szComment, DWORD commentBufferSize) +{ + unz_s *s; + unz_file_info file_info; + unz_file_info_internal file_info_internal; + int err = UNZ_OK; + DWORD uMagic; + long lSeek = 0; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + + if (ZSEEK(s->z_filefunc, s->filestream, s->pos_in_central_dir + s->byte_before_the_zipfile, SEEK_SET) != 0) + { + err = UNZ_ERRNO; + } + + /* we check the magic */ + + if (err == UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK) + { + err = UNZ_ERRNO; + } + else if (uMagic != 0x02014b50) + { + err = UNZ_BADZIPFILE; + } + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.version) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.version_needed) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.flag) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.compression_method) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.dosDate) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + unzlocal_DosDateToTmuDate(file_info.dosDate, &file_info.tmu_date); + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.crc) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.compressed_size) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.uncompressed_size) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.size_filename) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.size_file_extra) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.size_file_comment) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.disk_num_start) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.internal_fa) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.external_fa) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info_internal.offset_curfile) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + lSeek += file_info.size_filename; + + if ((err == UNZ_OK) && (szFileName != NULL)) + { + DWORD uSizeRead; + if (file_info.size_filename < fileNameBufferSize) + { + *(szFileName + file_info.size_filename) = '\0'; + uSizeRead = file_info.size_filename; + } + else + { + uSizeRead = fileNameBufferSize; + } + + if ((file_info.size_filename > 0) && (fileNameBufferSize > 0)) + if (ZREAD(s->z_filefunc, s->filestream, szFileName, uSizeRead) != uSizeRead) + { + err = UNZ_ERRNO; + } + lSeek -= uSizeRead; + } + + if ((err == UNZ_OK) && (extraField != NULL)) + { + DWORD uSizeRead; + if (file_info.size_file_extra < extraFieldBufferSize) + { + uSizeRead = file_info.size_file_extra; + } + else + { + uSizeRead = extraFieldBufferSize; + } + + if (lSeek != 0) + { + if (ZSEEK(s->z_filefunc, s->filestream, lSeek, SEEK_CUR) == 0) + { + lSeek = 0; + } + else + { + err = UNZ_ERRNO; + } + } + + if ((file_info.size_file_extra > 0) && (extraFieldBufferSize > 0)) + { + if (ZREAD(s->z_filefunc, s->filestream, extraField, uSizeRead) != uSizeRead) + { + err = UNZ_ERRNO; + } + } + + lSeek += file_info.size_file_extra - uSizeRead; + } + else + { + lSeek += file_info.size_file_extra; + } + + + if ((err == UNZ_OK) && (szComment != NULL)) + { + DWORD uSizeRead; + + if (file_info.size_file_comment < commentBufferSize) + { + *(szComment + file_info.size_file_comment) = '\0'; + uSizeRead = file_info.size_file_comment; + } + else + { + uSizeRead = commentBufferSize; + } + + if (lSeek != 0) + { + if (ZSEEK(s->z_filefunc, s->filestream, lSeek, SEEK_CUR) == 0) + { + lSeek = 0; + } + else + { + err = UNZ_ERRNO; + } + } + + if ((file_info.size_file_comment > 0) && (commentBufferSize > 0)) + { + if (ZREAD(s->z_filefunc, s->filestream, szComment, uSizeRead) != uSizeRead) + { + err = UNZ_ERRNO; + } + } + + lSeek += file_info.size_file_comment - uSizeRead; + } + else + { + lSeek += file_info.size_file_comment; + } + + if ((err == UNZ_OK) && (pfile_info != NULL)) + { + *pfile_info = file_info; + } + + if ((err == UNZ_OK) && (pfile_info_internal != NULL)) + { + *pfile_info_internal = file_info_internal; + } + + return err; +} + + + +/* +Write info about the ZipFile in the *pglobal_info structure. +No preparation of the structure is needed +return UNZ_OK if there is no problem. + */ + +extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *szFileName, DWORD fileNameBufferSize, void *extraField, DWORD extraFieldBufferSize, char *szComment, DWORD commentBufferSize) +{ + return unzlocal_GetCurrentFileInfoInternal(file, pfile_info, NULL, szFileName, fileNameBufferSize, extraField, extraFieldBufferSize, szComment, commentBufferSize); +} + +/* +Set the current file of the zipfile to the first file. +return UNZ_OK if there is no problem + */ + +extern int ZEXPORT unzGoToFirstFile(unzFile file) +{ + int err = UNZ_OK; + unz_s *s; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + s->pos_in_central_dir = s->offset_central_dir; + s->num_file = 0; + err = unzlocal_GetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* +Set the current file of the zipfile to the next file. +return UNZ_OK if there is no problem +return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. + */ + +extern int ZEXPORT unzGoToNextFile(unzFile file) +{ + unz_s *s; + int err; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + + if (!s->current_file_ok) + { + return UNZ_END_OF_LIST_OF_FILE; + } + + if (s->gi.number_entry != 0xffff) + { + /* 2^16 files overflow hack */ + if (s->num_file + 1 == s->gi.number_entry) + { + return UNZ_END_OF_LIST_OF_FILE; + } + } + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment; + s->num_file++; + err = unzlocal_GetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +extern int ZEXPORT unzGetCurrentFileID(unzFile file, DWORD *file_num, DWORD *pos_in_central_dir) +{ + unz_s *s; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + *file_num = s->num_file; + *pos_in_central_dir = s->pos_in_central_dir; + return UNZ_OK; +} + +extern int ZEXPORT unzGoToFileID(unzFile file, DWORD file_num, DWORD pos_in_central_dir) +{ + unz_s *s; + int err; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + s->num_file = file_num; + s->pos_in_central_dir = pos_in_central_dir; + err = unzlocal_GetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* +Try locate the file szFileName in the zipfile. +For the iCaseSensitivity signification, see unzipStringFileNameCompare + +return value : +UNZ_OK if the file is found. It becomes the current file. +UNZ_END_OF_LIST_OF_FILE if the file is not found + */ + + + +//------------------------------------------------------------------------- + + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// + */ + +/* +Read the local header of the current zipfile +Check the coherency of the local header and info in the end of central +directory about this file +store in *piSizeVar the size of extra info in local header +(filename and size of extra field data) + */ + +static int unzlocal_CheckCurrentFileCoherencyHeader(unz_s *s, DWORD *piSizeVar, DWORD *poffset_local_extrafield, DWORD *psize_local_extrafield) +{ + DWORD uMagic, uData, uFlags; + DWORD size_filename; + DWORD size_extra_field; + int err = UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK(s->z_filefunc, s->filestream, s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile, SEEK_SET) != 0) + { + return UNZ_ERRNO; + } + + + if (err == UNZ_OK) + { + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK) + { + err = UNZ_ERRNO; + } + else if (uMagic != 0x04034b50) + { + err = UNZ_BADZIPFILE; + } + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uFlags) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK) + { + err = UNZ_ERRNO; + } + else if ((err == UNZ_OK) && (uData != s->cur_file_info.compression_method)) + { + err = UNZ_BADZIPFILE; + } + + if ((err == UNZ_OK) && (s->cur_file_info.compression_method != 0) && (s->cur_file_info.compression_method != Z_DEFLATED)) + { + err = UNZ_BADZIPFILE; + } + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) != UNZ_OK) + // date/time + { + err = UNZ_ERRNO; + } + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) != UNZ_OK) + // crc + { + err = UNZ_ERRNO; + } + else if ((err == UNZ_OK) && (uData != s->cur_file_info.crc) && ((uFlags &8) == 0)) + { + err = UNZ_BADZIPFILE; + } + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) != UNZ_OK) + // size compr + { + err = UNZ_ERRNO; + } + else if ((err == UNZ_OK) && (uData != s->cur_file_info.compressed_size) && ((uFlags &8) == 0)) + { + err = UNZ_BADZIPFILE; + } + + if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) != UNZ_OK) + // size uncompr + { + err = UNZ_ERRNO; + } + else if ((err == UNZ_OK) && (uData != s->cur_file_info.uncompressed_size) && ((uFlags &8) == 0)) + { + err = UNZ_BADZIPFILE; + } + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_filename) != UNZ_OK) + { + err = UNZ_ERRNO; + } + else if ((err == UNZ_OK) && (size_filename != s->cur_file_info.size_filename)) + { + err = UNZ_BADZIPFILE; + } + + *piSizeVar += (DWORD)size_filename; + + if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_extra_field) != UNZ_OK) + { + err = UNZ_ERRNO; + } + + *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (DWORD)size_extra_field; + + *piSizeVar += (DWORD)size_extra_field; + + return err; +} + +/* +Open for reading data the current file in the zipfile. +If there is no error and the file is opened, the return value is UNZ_OK. + */ + +extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password) +{ + int err = UNZ_OK; + DWORD iSizeVar; + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + DWORD offset_local_extrafield; // offset of the local extra field + DWORD size_local_extrafield; // size of the local extra field + + #ifndef NOUNCRYPT + char source[12]; + #else + if (password != NULL) + { + return UNZ_PARAMERROR; + } + #endif + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + s = (unz_s*)file; + if (!s->current_file_ok) + { + return UNZ_PARAMERROR; + } + + if (s->pfile_in_zip_read != NULL) + { + unzCloseCurrentFile(file); + } + + if (unzlocal_CheckCurrentFileCoherencyHeader(s, &iSizeVar, &offset_local_extrafield, &size_local_extrafield) != UNZ_OK) + { + return UNZ_BADZIPFILE; + } + + pfile_in_zip_read_info = (file_in_zip_read_info_s*)ALLOC(sizeof(file_in_zip_read_info_s)); + + if (pfile_in_zip_read_info == NULL) + { + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->read_buffer = (char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield = 0; + pfile_in_zip_read_info->raw = raw; + + if (pfile_in_zip_read_info->read_buffer == NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised = 0; + + if (method != NULL) + { + *method = (int)s->cur_file_info.compression_method; + } + + if (level != NULL) + { + *level = 6; + switch (s->cur_file_info.flag &0x06) + { + case 6: + *level = 1; + break; + case 4: + *level = 2; + break; + case 2: + *level = 9; + break; + } + } + + if ((s->cur_file_info.compression_method != 0) && (s->cur_file_info.compression_method != Z_DEFLATED)) + { + err = UNZ_BADZIPFILE; + } + + pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc; + pfile_in_zip_read_info->crc32 = 0; + pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream = s->filestream; + pfile_in_zip_read_info->z_filefunc = s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method == Z_DEFLATED) && (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (void*)0; + pfile_in_zip_read_info->stream.next_in = (void*)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err = inflateInit2(&pfile_in_zip_read_info->stream, - MAX_WBITS); + if (err == Z_OK) + { + pfile_in_zip_read_info->stream_initialised = 1; + } + else + { + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + + pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size; + pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size; + + + pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (DWORD)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + + #ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password, s->keys, s->pcrc_32_tab); + if (ZSEEK(s->z_filefunc, s->filestream, s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile, SEEK_SET) != 0) + { + return UNZ_INTERNALERROR; + } + if (ZREAD(s->z_filefunc, s->filestream, source, 12) < 12) + { + return UNZ_INTERNALERROR; + } + + for (i = 0; i < 12; i++) + { + zdecode(s->keys, s->pcrc_32_tab, source[i]); + } + + s->pfile_in_zip_read->pos_in_zipfile += 12; + s->encrypted = 1; + } + #endif + + + return UNZ_OK; +} + +//------------------------------------------------------------------------- + +extern int ZEXPORT unzOpenCurrentFile(unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +//------------------------------------------------------------------------- + +extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char *password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +//------------------------------------------------------------------------- + +/* +Read bytes from the current file. +buf contain buffer where data must be copied +len the size of buf. + +return the number of byte copied if somes bytes are copied +return 0 if the end of file was reached +return <0 with error code if there is an error +(UNZ_ERRNO for IO error, or zLib error for uncompress error) + */ +extern int ZEXPORT unzReadCurrentFile(unzFile file, void *buf, DWORD len) +{ + int err = UNZ_OK; + DWORD iRead = 0; + unz_s *s; + + file_in_zip_read_info_s *pfile_in_zip_read_info; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + { + return UNZ_PARAMERROR; + } + + if ((pfile_in_zip_read_info->read_buffer == NULL)) + { + return UNZ_END_OF_LIST_OF_FILE; + } + + if (len == 0) + { + return 0; + } + + pfile_in_zip_read_info->stream.next_out = (BYTE*)buf; + pfile_in_zip_read_info->stream.avail_out = (DWORD)len; + + if (len > pfile_in_zip_read_info->rest_read_uncompressed) + { + pfile_in_zip_read_info->stream.avail_out = (DWORD)pfile_in_zip_read_info->rest_read_uncompressed; + } + + while (pfile_in_zip_read_info->stream.avail_out > 0) + { + if ((pfile_in_zip_read_info->stream.avail_in == 0) && (pfile_in_zip_read_info->rest_read_compressed > 0)) + { + DWORD uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressed < uReadThis) + { + uReadThis = (DWORD)pfile_in_zip_read_info->rest_read_compressed; + } + if (uReadThis == 0) + { + return UNZ_EOF; + } + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile, SEEK_SET) != 0) + { + return UNZ_ERRNO; + } + if (ZREAD(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->read_buffer, uReadThis) != uReadThis) + { + return UNZ_ERRNO; + } + + #ifndef NOUNCRYPT + if (s->encrypted) + { + DWORD i; + for (i = 0; i < uReadThis; i++) + { + pfile_in_zip_read_info->read_buffer[i] = zdecode(s->keys, s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]); + } + } + #endif + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed -= uReadThis; + + pfile_in_zip_read_info->stream.next_in = (BYTE*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (DWORD)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method == 0) || (pfile_in_zip_read_info->raw)) + { + DWORD uDoCopy, i; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && (pfile_in_zip_read_info->rest_read_compressed == 0)) + { + return (iRead == 0) ? UNZ_EOF : iRead; + } + + if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in) + { + uDoCopy = pfile_in_zip_read_info->stream.avail_out; + } + else + { + uDoCopy = pfile_in_zip_read_info->stream.avail_in; + } + + for (i = 0; i < uDoCopy; i++) + { + *(pfile_in_zip_read_info->stream.next_out + i) = *(pfile_in_zip_read_info->stream.next_in + i); + } + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, pfile_in_zip_read_info->stream.next_out, uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else + { + DWORD uTotalOutBefore, uTotalOutAfter; + const BYTE *bufBefore; + DWORD uOutThis; + int flush = Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + err = inflate(&pfile_in_zip_read_info->stream, flush); + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter - uTotalOutBefore; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, bufBefore, (DWORD)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; + + iRead += (DWORD)(uTotalOutAfter - uTotalOutBefore); + + if (err == Z_STREAM_END) + { + return (iRead == 0) ? UNZ_EOF : iRead; + } + + if (err != Z_OK) + { + break; + } + } + } + + if (err == Z_OK) + { + return iRead; + } + return err; +} + + +/* +Give the current position in uncompressed data + */ +/* +extern z_off_t ZEXPORT unztell(unzFile file) +{ + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + { + return UNZ_PARAMERROR; + } + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} +*/ + +/* +return 1 if the end of file was reached, 0 elsewhere + */ +/* +extern int ZEXPORT unzeof(unzFile file) +{ + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + { + return UNZ_PARAMERROR; + } + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + { + return 1; + } + else + { + return 0; + } +} +*/ + + +/* +Read extra field from the current file (opened by unzOpenCurrentFile) +This is the local-header version of the extra field (sometimes, there is +more info in the local-header version than in the central-header) + +if buf==NULL, it return the size of the local extra field that can be read + +if buf!=NULL, len is the size of the buffer, the extra header is copied in +buf. +the return value is the number of bytes copied in buf, or (if <0) +the error code + */ +/* +extern int ZEXPORT unzGetLocalExtrafield(unzFile file, void *buf, DWORD len) +{ + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + DWORD read_now; + DWORD size_to_read; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + { + return UNZ_PARAMERROR; + } + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - pfile_in_zip_read_info->pos_local_extrafield); + + if (buf == NULL) + { + return (int)size_to_read; + } + + if (len > size_to_read) + { + read_now = (DWORD)size_to_read; + } + else + { + read_now = (DWORD)len; + } + + if (read_now == 0) + { + return 0; + } + + if (ZSEEK(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield, SEEK_SET) != 0) + { + return UNZ_ERRNO; + } + + if (ZREAD(pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, buf, read_now) != read_now) + { + return UNZ_ERRNO; + } + + return (int)read_now; +} +*/ +/* +Close the file in zip opened with unzipOpenCurrentFile +Return UNZ_CRCERROR if all the file was read but the CRC is not good + */ + +extern int ZEXPORT unzCloseCurrentFile(unzFile file) +{ + int err = UNZ_OK; + + unz_s *s; + file_in_zip_read_info_s *pfile_in_zip_read_info; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + pfile_in_zip_read_info = s->pfile_in_zip_read; + + if (pfile_in_zip_read_info == NULL) + { + return UNZ_PARAMERROR; + } + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + { + err = UNZ_CRCERROR; + } + } + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + + if (pfile_in_zip_read_info->stream_initialised) + { + inflateEnd(&pfile_in_zip_read_info->stream); + } + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read = NULL; + + return err; +} + + +/* +Get the global comment string of the ZipFile, in the szComment buffer. +uSizeBuf is the size of the szComment buffer. +return the number of byte copied or an error code <0 + */ +/* +extern int ZEXPORT unzGetGlobalComment(unzFile file, char *szComment, DWORD uSizeBuf) +{ + //int err = UNZ_OK; + unz_s *s; + DWORD uReadThis; + + if (file == NULL) + { + return UNZ_PARAMERROR; + } + + s = (unz_s*)file; + + uReadThis = uSizeBuf; + + if (uReadThis > s->gi.size_comment) + { + uReadThis = s->gi.size_comment; + } + + if (ZSEEK(s->z_filefunc, s->filestream, s->central_pos + 22, SEEK_SET) != 0) + { + return UNZ_ERRNO; + } + + if (uReadThis > 0) + { + *szComment = '\0'; + + if (ZREAD(s->z_filefunc, s->filestream, szComment, uReadThis) != uReadThis) + { + return UNZ_ERRNO; + } + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + { + *(szComment + s->gi.size_comment) = '\0'; + } + return (int)uReadThis; +} +*/
\ No newline at end of file diff --git a/archive/hge/ZLIB/unzip.h b/archive/hge/ZLIB/unzip.h new file mode 100644 index 0000000..2a9f26f --- /dev/null +++ b/archive/hge/ZLIB/unzip.h @@ -0,0 +1,327 @@ +/* unzip.h -- IO for uncompress .zip files using zlib +Version 1.01, May 8th, 2004 + +Copyright (C) 1998-2004 Gilles Vollant + +This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g +WinZip, InfoZip tools and compatible. +Encryption and multi volume ZipFile (span) are not supported. +Old compressions used by old PKZip 1.x are not supported + + +I WAIT FEEDBACK at mail info@winimage.com +Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution + +Condition of use and distribution are the same than zlib : + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + + + */ + +/* for more info about .ZIP format, see +http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip +http://www.info-zip.org/pub/infozip/doc/ +PkWare has also a specification at : +ftp://ftp.pkware.com/probdesc.zip + */ + +#ifndef _unz_H + #define _unz_H + + #ifdef __cplusplus + extern "C" + { + #endif + + #ifndef _ZLIB_H + #include "zlib.h" + #endif + + #ifndef _ZLIBIOAPI_H + #include "ioapi.h" + #endif + + #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) + /* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ + typedef struct TagunzFile__ + { + int unused; + } unzFile__; + typedef unzFile__ *unzFile; + #else + typedef void *unzFile; + #endif + + + #define UNZ_OK (0) + #define UNZ_END_OF_LIST_OF_FILE (-100) + #define UNZ_ERRNO (Z_ERRNO) + #define UNZ_EOF (0) + #define UNZ_PARAMERROR (-102) + #define UNZ_BADZIPFILE (-103) + #define UNZ_INTERNALERROR (-104) + #define UNZ_CRCERROR (-105) + + /* tm_unz contain date/time info */ + typedef struct tm_unz_s + { + DWORD tm_sec; /* seconds after the minute - [0,59] */ + DWORD tm_min; /* minutes after the hour - [0,59] */ + DWORD tm_hour; /* hours since midnight - [0,23] */ + DWORD tm_mday; /* day of the month - [1,31] */ + DWORD tm_mon; /* months since January - [0,11] */ + DWORD tm_year; /* years - [1980..2044] */ + } tm_unz; + + /* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ + typedef struct unz_global_info_s + { + DWORD number_entry; /* total number of entries in + the central dir on this disk */ + DWORD size_comment; /* size of the global comment of the zipfile */ + } unz_global_info; + + + /* unz_file_info contain information about a file in the zipfile */ + typedef struct unz_file_info_s + { + DWORD version; /* version made by 2 bytes */ + DWORD version_needed; /* version needed to extract 2 bytes */ + DWORD flag; /* general purpose bit flag 2 bytes */ + DWORD compression_method; /* compression method 2 bytes */ + DWORD dosDate; /* last mod file date in Dos fmt 4 bytes */ + DWORD crc; /* crc-32 4 bytes */ + DWORD compressed_size; /* compressed size 4 bytes */ + DWORD uncompressed_size; /* uncompressed size 4 bytes */ + DWORD size_filename; /* filename length 2 bytes */ + DWORD size_file_extra; /* extra field length 2 bytes */ + DWORD size_file_comment; /* file comment length 2 bytes */ + + DWORD disk_num_start; /* disk number start 2 bytes */ + DWORD internal_fa; /* internal file attributes 2 bytes */ + DWORD external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; + } unz_file_info; + + extern int ZEXPORT unzStringFileNameCompare OF((const char *fileName1, const char *fileName2, int iCaseSensitivity)); + /* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + */ + + + extern unzFile ZEXPORT unzOpen(const char *path); + /* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. + */ + + extern unzFile ZEXPORT unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc_def); + /* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) + */ + + extern int ZEXPORT unzClose(unzFile file); + /* + Close a ZipFile opened with unzipOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzipCloseCurrentFile before call unzipClose. + return UNZ_OK if there is no problem. */ + + extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info); + /* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + + extern int ZEXPORT unzGetGlobalComment(unzFile file, char *szComment, DWORD uSizeBuf); + /* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 + */ + + + /***************************************************************************/ + /* Unzip package allow you browse the directory of the zipfile */ + + extern int ZEXPORT unzGoToFirstFile(unzFile file); + /* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem + */ + + extern int ZEXPORT unzGoToNextFile(unzFile file); + /* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. + */ + + extern int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity); + /* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found + */ + + extern int ZEXPORT unzGetCurrentFileID(unzFile file, DWORD *file_num, DWORD *pos_in_central_dir); + extern int ZEXPORT unzGoToFileID(unzFile file, DWORD file_num, DWORD pos_in_central_dir); + + /* ****************************************** */ + /* Ryan supplied functions */ + /* unz_file_info contain information about a file in the zipfile */ + typedef struct unz_file_pos_s + { + DWORD pos_in_zip_directory; /* offset in zip file directory */ + DWORD num_of_file; /* # of file */ + } unz_file_pos; + + extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos *file_pos); + + extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos *file_pos); + + /* ****************************************** */ + + extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *szFileName, DWORD fileNameBufferSize, void *extraField, DWORD extraFieldBufferSize, char *szComment, DWORD commentBufferSize); + /* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) + */ + + /***************************************************************************/ + /* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + + extern int ZEXPORT unzOpenCurrentFile(unzFile file); + /* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. + */ + + extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char *password); + /* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. + */ + + extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw); + /* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL + */ + + extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password); + /* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL + */ + + + extern int ZEXPORT unzCloseCurrentFile(unzFile file); + /* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good + */ + + extern int ZEXPORT unzReadCurrentFile(unzFile file, void *buf, DWORD len); + /* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) + */ + + extern z_off_t ZEXPORT unztell(unzFile file); + /* + Give the current position in uncompressed data + */ + + extern int ZEXPORT unzeof(unzFile file); + /* + return 1 if the end of file was reached, 0 elsewhere + */ + + extern int ZEXPORT unzGetLocalExtrafield(unzFile file, void *buf, DWORD len); + /* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code + */ + + /***************************************************************************/ + + /* Get the current file offset */ + extern DWORD ZEXPORT unzGetOffset(unzFile file); + + /* Set the current file offset */ + extern int ZEXPORT unzSetOffset(unzFile file, DWORD pos); + + + + #ifdef __cplusplus + } + #endif + +#endif /* _unz_H */ diff --git a/archive/hge/ZLIB/zconf.h b/archive/hge/ZLIB/zconf.h new file mode 100644 index 0000000..02ce56c --- /dev/null +++ b/archive/hge/ZLIB/zconf.h @@ -0,0 +1,428 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ + +/* all linked symbols */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzgetc z_gzgetc +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzwrite z_gzwrite +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetHeader z_inflateGetHeader +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# define uncompress z_uncompress +# define zError z_zError +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# define gzFile z_gzFile +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include <windows.h> + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef STDC +# include <sys/types.h> /* for off_t */ +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include <unistd.h> /* for SEEK_* and off_t */ +# ifdef VMS +# include <unixio.h> /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define z_off64_t off64_t +#else +# define z_off64_t z_off_t +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/archive/hge/ZLIB/zconf.in.h b/archive/hge/ZLIB/zconf.in.h new file mode 100644 index 0000000..91a0f73 --- /dev/null +++ b/archive/hge/ZLIB/zconf.in.h @@ -0,0 +1,323 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.in.h,v 1.1 2005/11/23 14:29:59 stingerx Exp $ */ + +#ifndef ZCONF_H + #define ZCONF_H + + /* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ + #ifdef Z_PREFIX + #define deflateInit_ z_deflateInit_ + #define deflate z_deflate + #define deflateEnd z_deflateEnd + #define inflateInit_ z_inflateInit_ + #define inflate z_inflate + #define inflateEnd z_inflateEnd + #define deflateInit2_ z_deflateInit2_ + #define deflateSetDictionary z_deflateSetDictionary + #define deflateCopy z_deflateCopy + #define deflateReset z_deflateReset + #define deflatePrime z_deflatePrime + #define deflateParams z_deflateParams + #define deflateBound z_deflateBound + #define inflateInit2_ z_inflateInit2_ + #define inflateSetDictionary z_inflateSetDictionary + #define inflateSync z_inflateSync + #define inflateSyncPoint z_inflateSyncPoint + #define inflateCopy z_inflateCopy + #define inflateReset z_inflateReset + #define compress z_compress + #define compress2 z_compress2 + #define compressBound z_compressBound + #define uncompress z_uncompress + #define adler32 z_adler32 + #define crc32 z_crc32 + #define get_crc_table z_get_crc_table + + #define Byte z_Byte + #define uInt z_uInt + #define uLong z_uLong + #define Bytef z_Bytef + #define charf z_charf + #define intf z_intf + #define uIntf z_uIntf + #define uLongf z_uLongf + #define voidpf z_voidpf + #define voidp z_voidp + #endif + + #if defined(__MSDOS__) && !defined(MSDOS) + #define MSDOS + #endif + #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) + #define OS2 + #endif + #if defined(_WINDOWS) && !defined(WINDOWS) + #define WINDOWS + #endif + #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) + #define WIN32 + #endif + #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) + #if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) + #ifndef SYS16BIT + #define SYS16BIT + #endif + #endif + #endif + + /* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ + #ifdef SYS16BIT + #define MAXSEG_64K + #endif + #ifdef MSDOS + #define UNALIGNED_OK + #endif + + #ifdef __STDC_VERSION__ + #ifndef STDC + #define STDC + #endif + #if __STDC_VERSION__ >= 199901L + #ifndef STDC99 + #define STDC99 + #endif + #endif + #endif + #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) + #define STDC + #endif + #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) + #define STDC + #endif + #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) + #define STDC + #endif + #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) + #define STDC + #endif + + #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ + #define STDC + #endif + + #ifndef STDC + #ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ + #define const /* note: need a more gentle solution here */ + #endif + #endif + + /* Some Mac compilers merge all .h files incorrectly: */ + #if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) + #define NO_DUMMY_DECL + #endif + + /* Maximum value for memLevel in deflateInit2 */ + #ifndef MAX_MEM_LEVEL + #ifdef MAXSEG_64K + #define MAX_MEM_LEVEL 8 + #else + #define MAX_MEM_LEVEL 9 + #endif + #endif + + /* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ + #ifndef MAX_WBITS + #define MAX_WBITS 15 /* 32K LZ77 window */ + #endif + + /* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. + */ + + /* Type declarations */ + + #ifndef OF /* function prototypes */ + #ifdef STDC + #define OF(args) args + #else + #define OF(args) () + #endif + #endif + + /* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ + #ifdef SYS16BIT + #if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ + #define SMALL_MEDIUM + #ifdef _MSC_VER + #define FAR _far + #else + #define FAR far + #endif + #endif + #if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ + #define SMALL_MEDIUM + #ifdef __BORLANDC__ + #define FAR _far + #else + #define FAR far + #endif + #endif + #endif + + #if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ + #ifdef ZLIB_DLL + #if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) + #ifdef ZLIB_INTERNAL + #define ZEXTERN extern __declspec(dllexport) + #else + #define ZEXTERN extern __declspec(dllimport) + #endif + #endif + #endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ + #ifdef ZLIB_WINAPI + #ifdef FAR + #undef FAR + #endif + #include <windows.h> + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ + #define ZEXPORT WINAPI + #ifdef WIN32 + #define ZEXPORTVA WINAPIV + #else + #define ZEXPORTVA FAR CDECL + #endif + #endif + #endif + + #if defined (__BEOS__) + #ifdef ZLIB_DLL + #ifdef ZLIB_INTERNAL + #define ZEXPORT __declspec(dllexport) + #define ZEXPORTVA __declspec(dllexport) + #else + #define ZEXPORT __declspec(dllimport) + #define ZEXPORTVA __declspec(dllimport) + #endif + #endif + #endif + + #ifndef ZEXTERN + #define ZEXTERN extern + #endif + #ifndef ZEXPORT + #define ZEXPORT + #endif + #ifndef ZEXPORTVA + #define ZEXPORTVA + #endif + + #ifndef FAR + #define FAR + #endif + + #if !defined(__MACTYPES__) + typedef unsigned char Byte; /* 8 bits */ + #endif + typedef unsigned int uInt; /* 16 bits or more */ + typedef unsigned long uLong; /* 32 bits or more */ + + #ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ + #define Bytef Byte FAR + #else + typedef Byte FAR Bytef; + #endif + typedef char FAR charf; + typedef int FAR intf; + typedef uInt FAR uIntf; + typedef uLong FAR uLongf; + + #ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; + #else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; + #endif + + #if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ + #include <sys/types.h> /* for off_t */ + #include <unistd.h> /* for SEEK_* and off_t */ + #ifdef VMS + #include <unixio.h> /* for off_t */ + #endif + #define z_off_t off_t + #endif + #ifndef SEEK_SET + #define SEEK_SET 0 /* Seek from beginning of file. */ + #define SEEK_CUR 1 /* Seek from current position. */ + #define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ + #endif + #ifndef z_off_t + #define z_off_t long + #endif + + #if defined(__OS400__) + #define NO_vsnprintf + #endif + + #if defined(__MVS__) + #define NO_vsnprintf + #ifdef FAR + #undef FAR + #endif + #endif + + /* MVS linker does not support external names larger than 8 bytes */ + #if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") + #endif + +#endif /* ZCONF_H */ diff --git a/archive/hge/ZLIB/zip.h b/archive/hge/ZLIB/zip.h new file mode 100644 index 0000000..944ed78 --- /dev/null +++ b/archive/hge/ZLIB/zip.h @@ -0,0 +1,196 @@ +/* zip.h -- IO for compress .zip files using zlib +Version 1.01, May 8th, 2004 + +Copyright (C) 1998-2004 Gilles Vollant + +This unzip package allow creates .ZIP file, compatible with PKZip 2.04g +WinZip, InfoZip tools and compatible. +Encryption and multi volume ZipFile (span) are not supported. +Old compressions used by old PKZip 1.x are not supported + +For uncompress .zip file, look at unzip.h + + +I WAIT FEEDBACK at mail info@winimage.com +Visit also http://www.winimage.com/zLibDll/unzip.html for evolution + +Condition of use and distribution are the same than zlib : + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + + + */ + +/* for more info about .ZIP format, see +http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip +http://www.info-zip.org/pub/infozip/doc/ +PkWare has also a specification at : +ftp://ftp.pkware.com/probdesc.zip + */ + +#ifndef _zip_H + #define _zip_H + + #ifdef __cplusplus + extern "C" + { + #endif + + #ifndef _ZLIB_H + #include "zlib.h" + #endif + + #ifndef _ZLIBIOAPI_H + #include "ioapi.h" + #endif + + #if defined(STRICTZIP) || defined(STRICTZIPUNZIP) + /* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ + typedef struct TagzipFile__ + { + int unused; + } zipFile__; + typedef zipFile__ *zipFile; + #else + typedef voidp zipFile; + #endif + + #define ZIP_OK (0) + #define ZIP_EOF (0) + #define ZIP_ERRNO (Z_ERRNO) + #define ZIP_PARAMERROR (-102) + #define ZIP_BADZIPFILE (-103) + #define ZIP_INTERNALERROR (-104) + + #ifndef DEF_MEM_LEVEL + #if MAX_MEM_LEVEL >= 8 + #define DEF_MEM_LEVEL 8 + #else + #define DEF_MEM_LEVEL MAX_MEM_LEVEL + #endif + #endif + /* default memLevel */ + + /* tm_zip contain date/time info */ + typedef struct tm_zip_s + { + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ + } tm_zip; + + typedef struct + { + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ + /* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + } zip_fileinfo; + + typedef const char *zipcharpc; + + + #define APPEND_STATUS_CREATE (0) + #define APPEND_STATUS_CREATEAFTER (1) + #define APPEND_STATUS_ADDINZIP (2) + + extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); + /* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. + */ + + /* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte + */ + + extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, int append, zipcharpc *globalcomment, zlib_filefunc_def *pzlib_filefunc_def)); + + extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, uInt size_extrafield_global, const char *comment, int method, int level)); + /* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) + */ + + + extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, uInt size_extrafield_global, const char *comment, int method, int level, int raw)); + + /* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + + extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, uInt size_extrafield_local, const void *extrafield_global, uInt size_extrafield_global, const char *comment, int method, int level, int raw, int windowBits, int memLevel, int strategy, const char *password, uLong crcForCtypting)); + + /* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCtypting : crc of file to compress (needed for crypting) + */ + + + extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, const void *buf, unsigned len)); + /* + Write data in the zipfile + */ + + extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); + /* + Close the current file in the zipfile + */ + + extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, uLong uncompressed_size, uLong crc32)); + /* + Close the current file in the zipfile, for fiel opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size + */ + + extern int ZEXPORT zipClose OF((zipFile file, const char *global_comment)); + /* + Close the zipfile + */ + + #ifdef __cplusplus + } + #endif + +#endif /* _zip_H */ diff --git a/archive/hge/ZLIB/zlib.h b/archive/hge/ZLIB/zlib.h new file mode 100644 index 0000000..bfbba83 --- /dev/null +++ b/archive/hge/ZLIB/zlib.h @@ -0,0 +1,1613 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.5, April 19th, 2010 + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.5" +#define ZLIB_VERNUM 0x1250 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 5 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use in the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). Some + output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed code + block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the stream + are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least the + value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect the + compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the + exact value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit() does not process any header information -- that is deferred + until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing will + resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all the uncompressed data. (The size + of the uncompressed data may have been saved by the compressor for this + purpose.) The next operation on this stream must be inflateEnd to deallocate + the decompression state. The use of Z_FINISH is never required, but can be + used to inform inflate that a faster approach may be used for the single + inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK or Z_TREES is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained, so applications that need that information should + instead use raw inflate, see inflateInit2() below, or inflateBack() and + perform their own processing of the gzip header and trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any call + of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. The + stream will keep the same compression level and any other attributes that + may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression level is changed, the input available so far is + compressed with the old level (and may be flushed); the new level will take + effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to be + compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if + strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been + found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the + success case, the application may save the current current value of total_in + which indicates where valid compressed data was found. In the error case, + the application may repeatedly call inflateSync, providing more input each + time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above or -1 << 16 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the normal + behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed buffer. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef voidp gzFile; /* opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) Also "a" + can be used instead of "w" to request that the gzip stream that will be + written be appended to the file. "+" will result in an error, since reading + and writing to the same gzip file is not supported. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Two buffers are allocated, either both of the specified size when + writing, or one of the specified size and the other twice that size when + reading. A larger buffer size of, for example, 64K or 128K bytes will + noticeably increase the speed of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file was not in gzip format, gzread copies the given number of + bytes into the buffer. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream, or failing that, reading the rest + of the input file directly without decompression. The entire input file + will be read if gzread is called until it returns less than the requested + len. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or 0 in case of error. The number of + uncompressed bytes written is limited to 8191, or one less than the buffer + size given to gzbuffer(). The caller should assure that this limit is not + exceeded. If it is exceeded, then gzprintf() will return an error (0) with + nothing written. In this case, there may also be a buffer overflow with + unpredictable consequences, which is possible only if zlib was compiled with + the insecure functions sprintf() or vsprintf() because the secure snprintf() + or vsnprintf() functions were not available. This can be determined using + zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatented gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. This state can change from + false to true while reading the input file if the end of a gzip stream is + reached, but is followed by data that is not another gzip stream. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the for the crc. Pre- and post-conditioning (one's + complement) is performed within this function so it shouldn't be done by the + application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# ifdef _LARGEFILE64_SOURCE + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +/* hack for buggy compilers */ +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; +#endif + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/archive/hge/ZLIB/zutil.c b/archive/hge/ZLIB/zutil.c new file mode 100644 index 0000000..898ed34 --- /dev/null +++ b/archive/hge/ZLIB/zutil.c @@ -0,0 +1,318 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2005, 2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +#ifndef NO_DUMMY_DECL +struct internal_state {int dummy;}; /* for buggy compilers */ +#endif + +const char * const z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#ifdef STDC +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/archive/hge/ZLIB/zutil.h b/archive/hge/ZLIB/zutil.h new file mode 100644 index 0000000..258fa88 --- /dev/null +++ b/archive/hge/ZLIB/zutil.h @@ -0,0 +1,274 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2010 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#ifdef STDC +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include <stddef.h> +# endif +# include <string.h> +# include <stdlib.h> +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include <alloc.h> +# endif +# else /* MSC or DJGPP */ +# include <malloc.h> +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 +# include <malloc.h> +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include <unix.h> /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include <stdio.h> + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); +void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/archive/hge/demo.cpp b/archive/hge/demo.cpp new file mode 100644 index 0000000..a8a2ce3 --- /dev/null +++ b/archive/hge/demo.cpp @@ -0,0 +1,51 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: HGE splash screen +*/ + + +#include "hge_impl.h" +#include "../loading.h" +#include "hgesprite.h" +//#ifdef DEMO +hgeSprite *SprLoad,*SprRot; +HTEXTURE TLoad,TRot; +int px,py; +float dtime,rot; +void DInit() +{ + px=pHGE->System_GetState(HGE_SCREENWIDTH)/2; + py=pHGE->System_GetState(HGE_SCREENHEIGHT)/2; + TLoad=pHGE->Texture_Load((char *)Loading,sizeof(Loading)); + TRot=pHGE->Texture_Load((char *)LoadCircle,sizeof(LoadCircle)); + SprLoad=new hgeSprite(TLoad,0,0,96,32); + SprRot=new hgeSprite(TRot,0,0,48,46); + SprLoad->SetHotSpot(48,16);SprRot->SetHotSpot(24,23); + dtime=0.0f;rot=0.0f; +} +void DDone() +{ + delete SprLoad;delete SprRot; + pHGE->Texture_Free(TLoad);pHGE->Texture_Free(TRot); +} +bool DFrame() +{ + BYTE alpha; + DWORD col=0x00FFFFFF; + dtime+=pHGE->Timer_GetDelta(); + if (dtime<=0.5)alpha=(BYTE)(dtime/0.5f*255.0f);else alpha=255; + if (dtime<=1.5)rot+=((pHGE->Timer_GetDelta())/0.1f)*M_PI*0.3f; + else rot+=((pHGE->Timer_GetDelta())/0.1f)*M_PI*0.3f*((2.0f-dtime)/0.5f); + SprRot->SetColor(SETA(col,alpha)); + if (dtime>=2)return true; + pHGE->Gfx_BeginScene(); + pHGE->Gfx_Clear(0); + SprLoad->Render(px,py); + SprRot->RenderEx(px-75,py,rot); + pHGE->Gfx_EndScene(); + return false; +} +//#endif diff --git a/archive/hge/gl.h b/archive/hge/gl.h new file mode 100644 index 0000000..96fb7d7 --- /dev/null +++ b/archive/hge/gl.h @@ -0,0 +1,2993 @@ +#ifndef __gl_h_ +#define __gl_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +// switches to providing function pointers +//#define GL_GLEXT_FUNCTION_POINTERS 1 + +typedef unsigned long GLenum; +typedef unsigned char GLboolean; +typedef unsigned long GLbitfield; +typedef signed char GLbyte; +typedef short GLshort; +typedef long GLint; +typedef long GLsizei; +typedef unsigned char GLubyte; +typedef unsigned short GLushort; +typedef unsigned long GLuint; +typedef float GLfloat; +typedef float GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void GLvoid; + +typedef long GLintptr; +typedef long GLsizeiptr; + +#ifndef GL_TYPEDEFS_2_0 +#define GL_TYPEDEFS_2_0 + typedef char GLchar; +#endif + +#ifndef GL_GLEXT_LEGACY +#include <OpenGL/glext.h> +#endif + +/* For compatibility with OpenGL v1.0 */ +#define GL_LOGIC_OP GL_INDEX_LOGIC_OP +#define GL_TEXTURE_COMPONENTS GL_TEXTURE_INTERNAL_FORMAT + +/*************************************************************/ + +/* Version */ +#define GL_VERSION_1_1 1 +#define GL_VERSION_1_2 1 +#define GL_VERSION_1_3 1 +#define GL_VERSION_1_4 1 +#define GL_VERSION_1_5 1 +#define GL_VERSION_2_0 1 + +/* AccumOp */ +#define GL_ACCUM 0x0100 +#define GL_LOAD 0x0101 +#define GL_RETURN 0x0102 +#define GL_MULT 0x0103 +#define GL_ADD 0x0104 + +/* AlphaFunction */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 + +/* AttribMask */ +#define GL_CURRENT_BIT 0x00000001 +#define GL_POINT_BIT 0x00000002 +#define GL_LINE_BIT 0x00000004 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_FOG_BIT 0x00000080 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_ENABLE_BIT 0x00002000 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_HINT_BIT 0x00008000 +#define GL_EVAL_BIT 0x00010000 +#define GL_LIST_BIT 0x00020000 +#define GL_TEXTURE_BIT 0x00040000 +#define GL_SCISSOR_BIT 0x00080000 +#define GL_ALL_ATTRIB_BITS 0x000fffff + +/* BeginMode */ +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_QUADS 0x0007 +#define GL_QUAD_STRIP 0x0008 +#define GL_POLYGON 0x0009 + +/* BlendEquationMode */ +/* GL_LOGIC_OP */ +/* GL_FUNC_ADD */ +/* GL_MIN */ +/* GL_MAX */ +/* GL_FUNC_SUBTRACT */ +/* GL_FUNC_REVERSE_SUBTRACT */ + +/* BlendingFactorDest */ +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +/* GL_CONSTANT_COLOR */ +/* GL_ONE_MINUS_CONSTANT_COLOR */ +/* GL_CONSTANT_ALPHA */ +/* GL_ONE_MINUS_CONSTANT_ALPHA */ + +/* BlendingFactorSrc */ +/* GL_ZERO */ +/* GL_ONE */ +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +/* GL_SRC_ALPHA */ +/* GL_ONE_MINUS_SRC_ALPHA */ +/* GL_DST_ALPHA */ +/* GL_ONE_MINUS_DST_ALPHA */ +/* GL_CONSTANT_COLOR */ +/* GL_ONE_MINUS_CONSTANT_COLOR */ +/* GL_CONSTANT_ALPHA */ +/* GL_ONE_MINUS_CONSTANT_ALPHA */ + +/* Boolean */ +#define GL_TRUE 1 +#define GL_FALSE 0 + +/* ClearBufferMask */ +/* GL_COLOR_BUFFER_BIT */ +/* GL_ACCUM_BUFFER_BIT */ +/* GL_STENCIL_BUFFER_BIT */ +/* GL_DEPTH_BUFFER_BIT */ + +/* ClientArrayType */ +/* GL_VERTEX_ARRAY */ +/* GL_NORMAL_ARRAY */ +/* GL_COLOR_ARRAY */ +/* GL_INDEX_ARRAY */ +/* GL_TEXTURE_COORD_ARRAY */ +/* GL_EDGE_FLAG_ARRAY */ + +/* ClipPlaneName */ +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 + +/* ColorMaterialFace */ +/* GL_FRONT */ +/* GL_BACK */ +/* GL_FRONT_AND_BACK */ + +/* ColorMaterialParameter */ +/* GL_AMBIENT */ +/* GL_DIFFUSE */ +/* GL_SPECULAR */ +/* GL_EMISSION */ +/* GL_AMBIENT_AND_DIFFUSE */ + +/* ColorPointerType */ +/* GL_BYTE */ +/* GL_UNSIGNED_BYTE */ +/* GL_SHORT */ +/* GL_UNSIGNED_SHORT */ +/* GL_INT */ +/* GL_UNSIGNED_INT */ +/* GL_FLOAT */ +/* GL_DOUBLE */ + +/* ColorTableParameterPName */ +/* GL_COLOR_TABLE_SCALE */ +/* GL_COLOR_TABLE_BIAS */ + +/* ColorTableTarget */ +/* GL_COLOR_TABLE */ +/* GL_POST_CONVOLUTION_COLOR_TABLE */ +/* GL_POST_COLOR_MATRIX_COLOR_TABLE */ +/* GL_PROXY_COLOR_TABLE */ +/* GL_PROXY_POST_CONVOLUTION_COLOR_TABLE */ +/* GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE */ + +/* ConvolutionBorderMode */ +/* GL_REDUCE */ +/* GL_IGNORE_BORDER */ +/* GL_CONSTANT_BORDER */ + +/* ConvolutionParameter */ +/* GL_CONVOLUTION_BORDER_MODE */ +/* GL_CONVOLUTION_FILTER_SCALE */ +/* GL_CONVOLUTION_FILTER_BIAS */ + +/* ConvolutionTarget */ +/* GL_CONVOLUTION_1D */ +/* GL_CONVOLUTION_2D */ + +/* CullFaceMode */ +/* GL_FRONT */ +/* GL_BACK */ +/* GL_FRONT_AND_BACK */ + +/* DataType */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_2_BYTES 0x1407 +#define GL_3_BYTES 0x1408 +#define GL_4_BYTES 0x1409 +#define GL_DOUBLE 0x140A + +/* DepthFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* DrawBufferMode */ +#define GL_NONE 0 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_AUX0 0x0409 +#define GL_AUX1 0x040A +#define GL_AUX2 0x040B +#define GL_AUX3 0x040C + +/* Enable */ +/* GL_FOG */ +/* GL_LIGHTING */ +/* GL_TEXTURE_1D */ +/* GL_TEXTURE_2D */ +/* GL_LINE_STIPPLE */ +/* GL_POLYGON_STIPPLE */ +/* GL_CULL_FACE */ +/* GL_ALPHA_TEST */ +/* GL_BLEND */ +/* GL_INDEX_LOGIC_OP */ +/* GL_COLOR_LOGIC_OP */ +/* GL_DITHER */ +/* GL_STENCIL_TEST */ +/* GL_DEPTH_TEST */ +/* GL_CLIP_PLANE0 */ +/* GL_CLIP_PLANE1 */ +/* GL_CLIP_PLANE2 */ +/* GL_CLIP_PLANE3 */ +/* GL_CLIP_PLANE4 */ +/* GL_CLIP_PLANE5 */ +/* GL_LIGHT0 */ +/* GL_LIGHT1 */ +/* GL_LIGHT2 */ +/* GL_LIGHT3 */ +/* GL_LIGHT4 */ +/* GL_LIGHT5 */ +/* GL_LIGHT6 */ +/* GL_LIGHT7 */ +/* GL_TEXTURE_GEN_S */ +/* GL_TEXTURE_GEN_T */ +/* GL_TEXTURE_GEN_R */ +/* GL_TEXTURE_GEN_Q */ +/* GL_MAP1_VERTEX_3 */ +/* GL_MAP1_VERTEX_4 */ +/* GL_MAP1_COLOR_4 */ +/* GL_MAP1_INDEX */ +/* GL_MAP1_NORMAL */ +/* GL_MAP1_TEXTURE_COORD_1 */ +/* GL_MAP1_TEXTURE_COORD_2 */ +/* GL_MAP1_TEXTURE_COORD_3 */ +/* GL_MAP1_TEXTURE_COORD_4 */ +/* GL_MAP2_VERTEX_3 */ +/* GL_MAP2_VERTEX_4 */ +/* GL_MAP2_COLOR_4 */ +/* GL_MAP2_INDEX */ +/* GL_MAP2_NORMAL */ +/* GL_MAP2_TEXTURE_COORD_1 */ +/* GL_MAP2_TEXTURE_COORD_2 */ +/* GL_MAP2_TEXTURE_COORD_3 */ +/* GL_MAP2_TEXTURE_COORD_4 */ +/* GL_POINT_SMOOTH */ +/* GL_LINE_SMOOTH */ +/* GL_POLYGON_SMOOTH */ +/* GL_SCISSOR_TEST */ +/* GL_COLOR_MATERIAL */ +/* GL_NORMALIZE */ +/* GL_AUTO_NORMAL */ +/* GL_VERTEX_ARRAY */ +/* GL_NORMAL_ARRAY */ +/* GL_COLOR_ARRAY */ +/* GL_INDEX_ARRAY */ +/* GL_TEXTURE_COORD_ARRAY */ +/* GL_EDGE_FLAG_ARRAY */ +/* GL_POLYGON_OFFSET_POINT */ +/* GL_POLYGON_OFFSET_LINE */ +/* GL_POLYGON_OFFSET_FILL */ +/* GL_COLOR_TABLE */ +/* GL_POST_CONVOLUTION_COLOR_TABLE */ +/* GL_POST_COLOR_MATRIX_COLOR_TABLE */ +/* GL_CONVOLUTION_1D */ +/* GL_CONVOLUTION_2D */ +/* GL_SEPARABLE_2D */ +/* GL_HISTOGRAM */ +/* GL_MINMAX */ +/* GL_RESCALE_NORMAL */ +/* GL_TEXTURE_3D */ + +/* ErrorCode */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 +/* GL_TABLE_TOO_LARGE */ + +/* FeedBackMode */ +#define GL_2D 0x0600 +#define GL_3D 0x0601 +#define GL_3D_COLOR 0x0602 +#define GL_3D_COLOR_TEXTURE 0x0603 +#define GL_4D_COLOR_TEXTURE 0x0604 + +/* FeedBackToken */ +#define GL_PASS_THROUGH_TOKEN 0x0700 +#define GL_POINT_TOKEN 0x0701 +#define GL_LINE_TOKEN 0x0702 +#define GL_POLYGON_TOKEN 0x0703 +#define GL_BITMAP_TOKEN 0x0704 +#define GL_DRAW_PIXEL_TOKEN 0x0705 +#define GL_COPY_PIXEL_TOKEN 0x0706 +#define GL_LINE_RESET_TOKEN 0x0707 + +/* FogMode */ +/* GL_LINEAR */ +#define GL_EXP 0x0800 +#define GL_EXP2 0x0801 + +/* FogParameter */ +/* GL_FOG_COLOR */ +/* GL_FOG_DENSITY */ +/* GL_FOG_END */ +/* GL_FOG_INDEX */ +/* GL_FOG_MODE */ +/* GL_FOG_START */ + +/* FrontFaceDirection */ +#define GL_CW 0x0900 +#define GL_CCW 0x0901 + +/* GetColorTableParameterPName */ +/* GL_COLOR_TABLE_SCALE */ +/* GL_COLOR_TABLE_BIAS */ +/* GL_COLOR_TABLE_FORMAT */ +/* GL_COLOR_TABLE_WIDTH */ +/* GL_COLOR_TABLE_RED_SIZE */ +/* GL_COLOR_TABLE_GREEN_SIZE */ +/* GL_COLOR_TABLE_BLUE_SIZE */ +/* GL_COLOR_TABLE_ALPHA_SIZE */ +/* GL_COLOR_TABLE_LUMINANCE_SIZE */ +/* GL_COLOR_TABLE_INTENSITY_SIZE */ + +/* GetConvolutionParameterPName */ +/* GL_CONVOLUTION_BORDER_COLOR */ +/* GL_CONVOLUTION_BORDER_MODE */ +/* GL_CONVOLUTION_FILTER_SCALE */ +/* GL_CONVOLUTION_FILTER_BIAS */ +/* GL_CONVOLUTION_FORMAT */ +/* GL_CONVOLUTION_WIDTH */ +/* GL_CONVOLUTION_HEIGHT */ +/* GL_MAX_CONVOLUTION_WIDTH */ +/* GL_MAX_CONVOLUTION_HEIGHT */ + +/* GetHistogramParameterPName */ +/* GL_HISTOGRAM_WIDTH */ +/* GL_HISTOGRAM_FORMAT */ +/* GL_HISTOGRAM_RED_SIZE */ +/* GL_HISTOGRAM_GREEN_SIZE */ +/* GL_HISTOGRAM_BLUE_SIZE */ +/* GL_HISTOGRAM_ALPHA_SIZE */ +/* GL_HISTOGRAM_LUMINANCE_SIZE */ +/* GL_HISTOGRAM_SINK */ + +/* GetMapTarget */ +#define GL_COEFF 0x0A00 +#define GL_ORDER 0x0A01 +#define GL_DOMAIN 0x0A02 + +/* GetMinmaxParameterPName */ +/* GL_MINMAX_FORMAT */ +/* GL_MINMAX_SINK */ + +/* GetPixelMap */ +/* GL_PIXEL_MAP_I_TO_I */ +/* GL_PIXEL_MAP_S_TO_S */ +/* GL_PIXEL_MAP_I_TO_R */ +/* GL_PIXEL_MAP_I_TO_G */ +/* GL_PIXEL_MAP_I_TO_B */ +/* GL_PIXEL_MAP_I_TO_A */ +/* GL_PIXEL_MAP_R_TO_R */ +/* GL_PIXEL_MAP_G_TO_G */ +/* GL_PIXEL_MAP_B_TO_B */ +/* GL_PIXEL_MAP_A_TO_A */ + +/* GetPointerTarget */ +/* GL_VERTEX_ARRAY_POINTER */ +/* GL_NORMAL_ARRAY_POINTER */ +/* GL_COLOR_ARRAY_POINTER */ +/* GL_INDEX_ARRAY_POINTER */ +/* GL_TEXTURE_COORD_ARRAY_POINTER */ +/* GL_EDGE_FLAG_ARRAY_POINTER */ + +/* GetTarget */ +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_INDEX 0x0B01 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_CURRENT_RASTER_COLOR 0x0B04 +#define GL_CURRENT_RASTER_INDEX 0x0B05 +#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 +#define GL_CURRENT_RASTER_POSITION 0x0B07 +#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 +#define GL_CURRENT_RASTER_DISTANCE 0x0B09 +#define GL_POINT_SMOOTH 0x0B10 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_STIPPLE 0x0B24 +#define GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GL_LINE_STIPPLE_REPEAT 0x0B26 +/* GL_SMOOTH_POINT_SIZE_RANGE */ +/* GL_SMOOTH_POINT_SIZE_GRANULARITY */ +/* GL_SMOOTH_LINE_WIDTH_RANGE */ +/* GL_SMOOTH_LINE_WIDTH_GRANULARITY */ +/* GL_ALIASED_POINT_SIZE_RANGE */ +/* GL_ALIASED_LINE_WIDTH_RANGE */ +#define GL_LIST_MODE 0x0B30 +#define GL_MAX_LIST_NESTING 0x0B31 +#define GL_LIST_BASE 0x0B32 +#define GL_LIST_INDEX 0x0B33 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_STIPPLE 0x0B42 +#define GL_EDGE_FLAG 0x0B43 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_LIGHTING 0x0B50 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_SHADE_MODEL 0x0B54 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_FOG 0x0B60 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_COLOR 0x0B66 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_ACCUM_CLEAR_VALUE 0x0B80 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_MATRIX_MODE 0x0BA0 +#define GL_NORMALIZE 0x0BA1 +#define GL_VIEWPORT 0x0BA2 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_ATTRIB_STACK_DEPTH 0x0BB0 +#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 +#define GL_ALPHA_TEST 0x0BC0 +#define GL_ALPHA_TEST_FUNC 0x0BC1 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_INDEX_LOGIC_OP 0x0BF1 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_AUX_BUFFERS 0x0C00 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_INDEX_CLEAR_VALUE 0x0C20 +#define GL_INDEX_WRITEMASK 0x0C21 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_INDEX_MODE 0x0C30 +#define GL_RGBA_MODE 0x0C31 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_RENDER_MODE 0x0C40 +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_FOG_HINT 0x0C54 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_Q 0x0C63 +#define GL_PIXEL_MAP_I_TO_I 0x0C70 +#define GL_PIXEL_MAP_S_TO_S 0x0C71 +#define GL_PIXEL_MAP_I_TO_R 0x0C72 +#define GL_PIXEL_MAP_I_TO_G 0x0C73 +#define GL_PIXEL_MAP_I_TO_B 0x0C74 +#define GL_PIXEL_MAP_I_TO_A 0x0C75 +#define GL_PIXEL_MAP_R_TO_R 0x0C76 +#define GL_PIXEL_MAP_G_TO_G 0x0C77 +#define GL_PIXEL_MAP_B_TO_B 0x0C78 +#define GL_PIXEL_MAP_A_TO_A 0x0C79 +#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 +#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 +#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 +#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 +#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 +#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 +#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 +#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 +#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 +#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAP_COLOR 0x0D10 +#define GL_MAP_STENCIL 0x0D11 +#define GL_INDEX_SHIFT 0x0D12 +#define GL_INDEX_OFFSET 0x0D13 +#define GL_RED_SCALE 0x0D14 +#define GL_RED_BIAS 0x0D15 +#define GL_ZOOM_X 0x0D16 +#define GL_ZOOM_Y 0x0D17 +#define GL_GREEN_SCALE 0x0D18 +#define GL_GREEN_BIAS 0x0D19 +#define GL_BLUE_SCALE 0x0D1A +#define GL_BLUE_BIAS 0x0D1B +#define GL_ALPHA_SCALE 0x0D1C +#define GL_ALPHA_BIAS 0x0D1D +#define GL_DEPTH_SCALE 0x0D1E +#define GL_DEPTH_BIAS 0x0D1F +#define GL_MAX_EVAL_ORDER 0x0D30 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 +#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_NAME_STACK_DEPTH 0x0D37 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_INDEX_BITS 0x0D51 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_ACCUM_RED_BITS 0x0D58 +#define GL_ACCUM_GREEN_BITS 0x0D59 +#define GL_ACCUM_BLUE_BITS 0x0D5A +#define GL_ACCUM_ALPHA_BITS 0x0D5B +#define GL_NAME_STACK_DEPTH 0x0D70 +#define GL_AUTO_NORMAL 0x0D80 +#define GL_MAP1_COLOR_4 0x0D90 +#define GL_MAP1_INDEX 0x0D91 +#define GL_MAP1_NORMAL 0x0D92 +#define GL_MAP1_TEXTURE_COORD_1 0x0D93 +#define GL_MAP1_TEXTURE_COORD_2 0x0D94 +#define GL_MAP1_TEXTURE_COORD_3 0x0D95 +#define GL_MAP1_TEXTURE_COORD_4 0x0D96 +#define GL_MAP1_VERTEX_3 0x0D97 +#define GL_MAP1_VERTEX_4 0x0D98 +#define GL_MAP2_COLOR_4 0x0DB0 +#define GL_MAP2_INDEX 0x0DB1 +#define GL_MAP2_NORMAL 0x0DB2 +#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 +#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 +#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 +#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 +#define GL_MAP2_VERTEX_3 0x0DB7 +#define GL_MAP2_VERTEX_4 0x0DB8 +#define GL_MAP1_GRID_DOMAIN 0x0DD0 +#define GL_MAP1_GRID_SEGMENTS 0x0DD1 +#define GL_MAP2_GRID_DOMAIN 0x0DD2 +#define GL_MAP2_GRID_SEGMENTS 0x0DD3 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 +#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 +#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 +#define GL_SELECTION_BUFFER_POINTER 0x0DF3 +#define GL_SELECTION_BUFFER_SIZE 0x0DF4 +/* GL_TEXTURE_BINDING_1D */ +/* GL_TEXTURE_BINDING_2D */ +/* GL_TEXTURE_BINDING_3D */ +/* GL_VERTEX_ARRAY */ +/* GL_NORMAL_ARRAY */ +/* GL_COLOR_ARRAY */ +/* GL_INDEX_ARRAY */ +/* GL_TEXTURE_COORD_ARRAY */ +/* GL_EDGE_FLAG_ARRAY */ +/* GL_VERTEX_ARRAY_SIZE */ +/* GL_VERTEX_ARRAY_TYPE */ +/* GL_VERTEX_ARRAY_STRIDE */ +/* GL_NORMAL_ARRAY_TYPE */ +/* GL_NORMAL_ARRAY_STRIDE */ +/* GL_COLOR_ARRAY_SIZE */ +/* GL_COLOR_ARRAY_TYPE */ +/* GL_COLOR_ARRAY_STRIDE */ +/* GL_INDEX_ARRAY_TYPE */ +/* GL_INDEX_ARRAY_STRIDE */ +/* GL_TEXTURE_COORD_ARRAY_SIZE */ +/* GL_TEXTURE_COORD_ARRAY_TYPE */ +/* GL_TEXTURE_COORD_ARRAY_STRIDE */ +/* GL_EDGE_FLAG_ARRAY_STRIDE */ +/* GL_POLYGON_OFFSET_FACTOR */ +/* GL_POLYGON_OFFSET_UNITS */ +/* GL_COLOR_TABLE */ +/* GL_POST_CONVOLUTION_COLOR_TABLE */ +/* GL_POST_COLOR_MATRIX_COLOR_TABLE */ +/* GL_CONVOLUTION_1D */ +/* GL_CONVOLUTION_2D */ +/* GL_SEPARABLE_2D */ +/* GL_POST_CONVOLUTION_RED_SCALE */ +/* GL_POST_CONVOLUTION_GREEN_SCALE */ +/* GL_POST_CONVOLUTION_BLUE_SCALE */ +/* GL_POST_CONVOLUTION_ALPHA_SCALE */ +/* GL_POST_CONVOLUTION_RED_BIAS */ +/* GL_POST_CONVOLUTION_GREEN_BIAS */ +/* GL_POST_CONVOLUTION_BLUE_BIAS */ +/* GL_POST_CONVOLUTION_ALPHA_BIAS */ +/* GL_COLOR_MATRIX */ +/* GL_COLOR_MATRIX_STACK_DEPTH */ +/* GL_MAX_COLOR_MATRIX_STACK_DEPTH */ +/* GL_POST_COLOR_MATRIX_RED_SCALE */ +/* GL_POST_COLOR_MATRIX_GREEN_SCALE */ +/* GL_POST_COLOR_MATRIX_BLUE_SCALE */ +/* GL_POST_COLOR_MATRIX_ALPHA_SCALE */ +/* GL_POST_COLOR_MATRIX_RED_BIAS */ +/* GL_POST_COLOR_MATRIX_GREEN_BIAS */ +/* GL_POST_COLOR_MATRIX_BLUE_BIAS */ +/* GL_POST_COLOR_MATRIX_ALPHA_BIAS */ +/* GL_HISTOGRAM */ +/* GL_MINMAX */ +/* GL_MAX_ELEMENTS_VERTICES */ +/* GL_MAX_ELEMENTS_INDICES */ +/* GL_RESCALE_NORMAL */ +/* GL_LIGHT_MODEL_COLOR_CONTROL */ +/* GL_PACK_SKIP_IMAGES */ +/* GL_PACK_IMAGE_HEIGHT */ +/* GL_UNPACK_SKIP_IMAGES */ +/* GL_UNPACK_IMAGE_HEIGHT */ +/* GL_TEXTURE_3D */ +/* GL_MAX_3D_TEXTURE_SIZE */ +/* GL_BLEND_COLOR */ +/* GL_BLEND_EQUATION */ + +/* GetTextureParameter */ +/* GL_TEXTURE_MAG_FILTER */ +/* GL_TEXTURE_MIN_FILTER */ +/* GL_TEXTURE_WRAP_S */ +/* GL_TEXTURE_WRAP_T */ +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_BORDER 0x1005 +/* GL_TEXTURE_RED_SIZE */ +/* GL_TEXTURE_GREEN_SIZE */ +/* GL_TEXTURE_BLUE_SIZE */ +/* GL_TEXTURE_ALPHA_SIZE */ +/* GL_TEXTURE_LUMINANCE_SIZE */ +/* GL_TEXTURE_INTENSITY_SIZE */ +/* GL_TEXTURE_PRIORITY */ +/* GL_TEXTURE_RESIDENT */ +/* GL_TEXTURE_DEPTH */ +/* GL_TEXTURE_WRAP_R */ +/* GL_TEXTURE_MIN_LOD */ +/* GL_TEXTURE_MAX_LOD */ +/* GL_TEXTURE_BASE_LEVEL */ +/* GL_TEXTURE_MAX_LEVEL */ + +/* HintMode */ +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 + +/* HintTarget */ +/* GL_PERSPECTIVE_CORRECTION_HINT */ +/* GL_POINT_SMOOTH_HINT */ +/* GL_LINE_SMOOTH_HINT */ +/* GL_POLYGON_SMOOTH_HINT */ +/* GL_FOG_HINT */ + +/* HistogramTarget */ +/* GL_HISTOGRAM */ +/* GL_PROXY_HISTOGRAM */ + +/* IndexPointerType */ +/* GL_SHORT */ +/* GL_INT */ +/* GL_FLOAT */ +/* GL_DOUBLE */ + +/* LightModelColorControl */ +/* GL_SINGLE_COLOR */ +/* GL_SEPARATE_SPECULAR_COLOR */ + +/* LightModelParameter */ +/* GL_LIGHT_MODEL_AMBIENT */ +/* GL_LIGHT_MODEL_LOCAL_VIEWER */ +/* GL_LIGHT_MODEL_TWO_SIDE */ +/* GL_LIGHT_MODEL_COLOR_CONTROL */ + +/* LightName */ +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 + +/* LightParameter */ +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 + +/* InterleavedArrays */ +/* GL_V2F */ +/* GL_V3F */ +/* GL_C4UB_V2F */ +/* GL_C4UB_V3F */ +/* GL_C3F_V3F */ +/* GL_N3F_V3F */ +/* GL_C4F_N3F_V3F */ +/* GL_T2F_V3F */ +/* GL_T4F_V4F */ +/* GL_T2F_C4UB_V3F */ +/* GL_T2F_C3F_V3F */ +/* GL_T2F_N3F_V3F */ +/* GL_T2F_C4F_N3F_V3F */ +/* GL_T4F_C4F_N3F_V4F */ + +/* ListMode */ +#define GL_COMPILE 0x1300 +#define GL_COMPILE_AND_EXECUTE 0x1301 + +/* ListNameType */ +/* GL_BYTE */ +/* GL_UNSIGNED_BYTE */ +/* GL_SHORT */ +/* GL_UNSIGNED_SHORT */ +/* GL_INT */ +/* GL_UNSIGNED_INT */ +/* GL_FLOAT */ +/* GL_2_BYTES */ +/* GL_3_BYTES */ +/* GL_4_BYTES */ + +/* LogicOp */ +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F + +/* MapTarget */ +/* GL_MAP1_COLOR_4 */ +/* GL_MAP1_INDEX */ +/* GL_MAP1_NORMAL */ +/* GL_MAP1_TEXTURE_COORD_1 */ +/* GL_MAP1_TEXTURE_COORD_2 */ +/* GL_MAP1_TEXTURE_COORD_3 */ +/* GL_MAP1_TEXTURE_COORD_4 */ +/* GL_MAP1_VERTEX_3 */ +/* GL_MAP1_VERTEX_4 */ +/* GL_MAP2_COLOR_4 */ +/* GL_MAP2_INDEX */ +/* GL_MAP2_NORMAL */ +/* GL_MAP2_TEXTURE_COORD_1 */ +/* GL_MAP2_TEXTURE_COORD_2 */ +/* GL_MAP2_TEXTURE_COORD_3 */ +/* GL_MAP2_TEXTURE_COORD_4 */ +/* GL_MAP2_VERTEX_3 */ +/* GL_MAP2_VERTEX_4 */ + +/* MaterialFace */ +/* GL_FRONT */ +/* GL_BACK */ +/* GL_FRONT_AND_BACK */ + +/* MaterialParameter */ +#define GL_EMISSION 0x1600 +#define GL_SHININESS 0x1601 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_COLOR_INDEXES 0x1603 +/* GL_AMBIENT */ +/* GL_DIFFUSE */ +/* GL_SPECULAR */ + +/* MatrixMode */ +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 + +/* MeshMode1 */ +/* GL_POINT */ +/* GL_LINE */ + +/* MeshMode2 */ +/* GL_POINT */ +/* GL_LINE */ +/* GL_FILL */ + +/* MinmaxTarget */ +/* GL_MINMAX */ + +/* NormalPointerType */ +/* GL_BYTE */ +/* GL_SHORT */ +/* GL_INT */ +/* GL_FLOAT */ +/* GL_DOUBLE */ + +/* PixelCopyType */ +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 + +/* PixelFormat */ +#define GL_COLOR_INDEX 0x1900 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +/* GL_ABGR */ + +/* PixelInternalFormat */ +/* GL_ALPHA4 */ +/* GL_ALPHA8 */ +/* GL_ALPHA12 */ +/* GL_ALPHA16 */ +/* GL_LUMINANCE4 */ +/* GL_LUMINANCE8 */ +/* GL_LUMINANCE12 */ +/* GL_LUMINANCE16 */ +/* GL_LUMINANCE4_ALPHA4 */ +/* GL_LUMINANCE6_ALPHA2 */ +/* GL_LUMINANCE8_ALPHA8 */ +/* GL_LUMINANCE12_ALPHA4 */ +/* GL_LUMINANCE12_ALPHA12 */ +/* GL_LUMINANCE16_ALPHA16 */ +/* GL_INTENSITY */ +/* GL_INTENSITY4 */ +/* GL_INTENSITY8 */ +/* GL_INTENSITY12 */ +/* GL_INTENSITY16 */ +/* GL_R3_G3_B2 */ +/* GL_RGB4 */ +/* GL_RGB5 */ +/* GL_RGB8 */ +/* GL_RGB10 */ +/* GL_RGB12 */ +/* GL_RGB16 */ +/* GL_RGBA2 */ +/* GL_RGBA4 */ +/* GL_RGB5_A1 */ +/* GL_RGBA8 */ +/* GL_RGB10_A2 */ +/* GL_RGBA12 */ +/* GL_RGBA16 */ + +/* PixelMap */ +/* GL_PIXEL_MAP_I_TO_I */ +/* GL_PIXEL_MAP_S_TO_S */ +/* GL_PIXEL_MAP_I_TO_R */ +/* GL_PIXEL_MAP_I_TO_G */ +/* GL_PIXEL_MAP_I_TO_B */ +/* GL_PIXEL_MAP_I_TO_A */ +/* GL_PIXEL_MAP_R_TO_R */ +/* GL_PIXEL_MAP_G_TO_G */ +/* GL_PIXEL_MAP_B_TO_B */ +/* GL_PIXEL_MAP_A_TO_A */ + +/* PixelStore */ +/* GL_UNPACK_SWAP_BYTES */ +/* GL_UNPACK_LSB_FIRST */ +/* GL_UNPACK_ROW_LENGTH */ +/* GL_UNPACK_SKIP_ROWS */ +/* GL_UNPACK_SKIP_PIXELS */ +/* GL_UNPACK_ALIGNMENT */ +/* GL_PACK_SWAP_BYTES */ +/* GL_PACK_LSB_FIRST */ +/* GL_PACK_ROW_LENGTH */ +/* GL_PACK_SKIP_ROWS */ +/* GL_PACK_SKIP_PIXELS */ +/* GL_PACK_ALIGNMENT */ +/* GL_PACK_SKIP_IMAGES */ +/* GL_PACK_IMAGE_HEIGHT */ +/* GL_UNPACK_SKIP_IMAGES */ +/* GL_UNPACK_IMAGE_HEIGHT */ + +/* PixelTransfer */ +/* GL_MAP_COLOR */ +/* GL_MAP_STENCIL */ +/* GL_INDEX_SHIFT */ +/* GL_INDEX_OFFSET */ +/* GL_RED_SCALE */ +/* GL_RED_BIAS */ +/* GL_GREEN_SCALE */ +/* GL_GREEN_BIAS */ +/* GL_BLUE_SCALE */ +/* GL_BLUE_BIAS */ +/* GL_ALPHA_SCALE */ +/* GL_ALPHA_BIAS */ +/* GL_DEPTH_SCALE */ +/* GL_DEPTH_BIAS */ +/* GL_POST_CONVOLUTION_RED_SCALE */ +/* GL_POST_CONVOLUTION_GREEN_SCALE */ +/* GL_POST_CONVOLUTION_BLUE_SCALE */ +/* GL_POST_CONVOLUTION_ALPHA_SCALE */ +/* GL_POST_CONVOLUTION_RED_BIAS */ +/* GL_POST_CONVOLUTION_GREEN_BIAS */ +/* GL_POST_CONVOLUTION_BLUE_BIAS */ +/* GL_POST_CONVOLUTION_ALPHA_BIAS */ +/* GL_POST_COLOR_MATRIX_RED_SCALE */ +/* GL_POST_COLOR_MATRIX_GREEN_SCALE */ +/* GL_POST_COLOR_MATRIX_BLUE_SCALE */ +/* GL_POST_COLOR_MATRIX_ALPHA_SCALE */ +/* GL_POST_COLOR_MATRIX_RED_BIAS */ +/* GL_POST_COLOR_MATRIX_GREEN_BIAS */ +/* GL_POST_COLOR_MATRIX_BLUE_BIAS */ +/* GL_POST_COLOR_MATRIX_ALPHA_BIAS */ + +/* PixelType */ +#define GL_BITMAP 0x1A00 +/* GL_BYTE */ +/* GL_UNSIGNED_BYTE */ +/* GL_SHORT */ +/* GL_UNSIGNED_SHORT */ +/* GL_INT */ +/* GL_UNSIGNED_INT */ +/* GL_FLOAT */ +/* GL_BGR */ +/* GL_BGRA */ +/* GL_UNSIGNED_BYTE_3_3_2 */ +/* GL_UNSIGNED_SHORT_4_4_4_4 */ +/* GL_UNSIGNED_SHORT_5_5_5_1 */ +/* GL_UNSIGNED_INT_8_8_8_8 */ +/* GL_UNSIGNED_INT_10_10_10_2 */ +/* GL_UNSIGNED_SHORT_5_6_5 */ +/* GL_UNSIGNED_BYTE_2_3_3_REV */ +/* GL_UNSIGNED_SHORT_5_6_5_REV */ +/* GL_UNSIGNED_SHORT_4_4_4_4_REV */ +/* GL_UNSIGNED_SHORT_1_5_5_5_REV */ +/* GL_UNSIGNED_INT_8_8_8_8_REV */ +/* GL_UNSIGNED_INT_2_10_10_10_REV */ + +/* PolygonMode */ +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 + +/* ReadBufferMode */ +/* GL_FRONT_LEFT */ +/* GL_FRONT_RIGHT */ +/* GL_BACK_LEFT */ +/* GL_BACK_RIGHT */ +/* GL_FRONT */ +/* GL_BACK */ +/* GL_LEFT */ +/* GL_RIGHT */ +/* GL_AUX0 */ +/* GL_AUX1 */ +/* GL_AUX2 */ +/* GL_AUX3 */ + +/* RenderingMode */ +#define GL_RENDER 0x1C00 +#define GL_FEEDBACK 0x1C01 +#define GL_SELECT 0x1C02 + +/* SeparableTarget */ +/* GL_SEPARABLE_2D */ + +/* ShadingModel */ +#define GL_FLAT 0x1D00 +#define GL_SMOOTH 0x1D01 + +/* StencilFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* StencilOp */ +/* GL_ZERO */ +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +/* GL_INVERT */ + +/* StringName */ +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 + +/* TextureCoordName */ +#define GL_S 0x2000 +#define GL_T 0x2001 +#define GL_R 0x2002 +#define GL_Q 0x2003 + +/* TexCoordPointerType */ +/* GL_SHORT */ +/* GL_INT */ +/* GL_FLOAT */ +/* GL_DOUBLE */ + +/* TextureEnvMode */ +#define GL_MODULATE 0x2100 +#define GL_DECAL 0x2101 +/* GL_BLEND */ +/* GL_REPLACE */ + +/* TextureEnvParameter */ +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_ENV_COLOR 0x2201 + +/* TextureEnvTarget */ +#define GL_TEXTURE_ENV 0x2300 + +/* TextureGenMode */ +#define GL_EYE_LINEAR 0x2400 +#define GL_OBJECT_LINEAR 0x2401 +#define GL_SPHERE_MAP 0x2402 + +/* TextureGenParameter */ +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_OBJECT_PLANE 0x2501 +#define GL_EYE_PLANE 0x2502 + +/* TextureMagFilter */ +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 + +/* TextureMinFilter */ +/* GL_NEAREST */ +/* GL_LINEAR */ +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 + +/* TextureParameterName */ +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +/* GL_TEXTURE_BORDER_COLOR */ +/* GL_TEXTURE_PRIORITY */ +/* GL_TEXTURE_WRAP_R */ +/* GL_TEXTURE_MIN_LOD */ +/* GL_TEXTURE_MAX_LOD */ +/* GL_TEXTURE_BASE_LEVEL */ +/* GL_TEXTURE_MAX_LEVEL */ + +/* TextureTarget */ +/* GL_TEXTURE_1D */ +/* GL_TEXTURE_2D */ +/* GL_PROXY_TEXTURE_1D */ +/* GL_PROXY_TEXTURE_2D */ +/* GL_TEXTURE_3D */ +/* GL_PROXY_TEXTURE_3D */ + +/* TextureWrapMode */ +#define GL_CLAMP 0x2900 +#define GL_REPEAT 0x2901 +/* GL_CLAMP_TO_EDGE */ + +/* VertexPointerType */ +/* GL_SHORT */ +/* GL_INT */ +/* GL_FLOAT */ +/* GL_DOUBLE */ + +/* ClientAttribMask */ +#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 +#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define GL_CLIENT_ALL_ATTRIB_BITS 0xffffffff + +/* polygon_offset */ +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_FILL 0x8037 + +/* texture */ +#define GL_ALPHA4 0x803B +#define GL_ALPHA8 0x803C +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_LUMINANCE4 0x803F +#define GL_LUMINANCE8 0x8040 +#define GL_LUMINANCE12 0x8041 +#define GL_LUMINANCE16 0x8042 +#define GL_LUMINANCE4_ALPHA4 0x8043 +#define GL_LUMINANCE6_ALPHA2 0x8044 +#define GL_LUMINANCE8_ALPHA8 0x8045 +#define GL_LUMINANCE12_ALPHA4 0x8046 +#define GL_LUMINANCE12_ALPHA12 0x8047 +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_INTENSITY 0x8049 +#define GL_INTENSITY4 0x804A +#define GL_INTENSITY8 0x804B +#define GL_INTENSITY12 0x804C +#define GL_INTENSITY16 0x804D +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GL_TEXTURE_INTENSITY_SIZE 0x8061 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 + +/* texture_object */ +#define GL_TEXTURE_PRIORITY 0x8066 +#define GL_TEXTURE_RESIDENT 0x8067 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_BINDING_3D 0x806A + +/* vertex_array */ +#define GL_VERTEX_ARRAY 0x8074 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_COLOR_ARRAY 0x8076 +#define GL_INDEX_ARRAY 0x8077 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_EDGE_FLAG_ARRAY 0x8079 +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_TYPE 0x807B +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_INDEX_ARRAY_TYPE 0x8085 +#define GL_INDEX_ARRAY_STRIDE 0x8086 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_INDEX_ARRAY_POINTER 0x8091 +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GL_V2F 0x2A20 +#define GL_V3F 0x2A21 +#define GL_C4UB_V2F 0x2A22 +#define GL_C4UB_V3F 0x2A23 +#define GL_C3F_V3F 0x2A24 +#define GL_N3F_V3F 0x2A25 +#define GL_C4F_N3F_V3F 0x2A26 +#define GL_T2F_V3F 0x2A27 +#define GL_T4F_V4F 0x2A28 +#define GL_T2F_C4UB_V3F 0x2A29 +#define GL_T2F_C3F_V3F 0x2A2A +#define GL_T2F_N3F_V3F 0x2A2B +#define GL_T2F_C4F_N3F_V3F 0x2A2C +#define GL_T4F_C4F_N3F_V4F 0x2A2D + +/* bgra */ +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 + +/* blend_color */ +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 + +/* blend_minmax */ +#define GL_FUNC_ADD 0x8006 +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BLEND_EQUATION 0x8009 + +/* blend_equation_separate */ +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D + +/* blend_subtract */ +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B + +/* color_matrix */ +#define GL_COLOR_MATRIX 0x80B1 +#define GL_COLOR_MATRIX_STACK_DEPTH 0x80B2 +#define GL_MAX_COLOR_MATRIX_STACK_DEPTH 0x80B3 +#define GL_POST_COLOR_MATRIX_RED_SCALE 0x80B4 +#define GL_POST_COLOR_MATRIX_GREEN_SCALE 0x80B5 +#define GL_POST_COLOR_MATRIX_BLUE_SCALE 0x80B6 +#define GL_POST_COLOR_MATRIX_ALPHA_SCALE 0x80B7 +#define GL_POST_COLOR_MATRIX_RED_BIAS 0x80B8 +#define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 +#define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA +#define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB + +/* color_table */ +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_COLOR_TABLE_SCALE 0x80D6 +#define GL_COLOR_TABLE_BIAS 0x80D7 +#define GL_COLOR_TABLE_FORMAT 0x80D8 +#define GL_COLOR_TABLE_WIDTH 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE 0x80DF + +/* convolution */ +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_CONVOLUTION_BORDER_MODE 0x8013 +#define GL_CONVOLUTION_FILTER_SCALE 0x8014 +#define GL_CONVOLUTION_FILTER_BIAS 0x8015 +#define GL_REDUCE 0x8016 +#define GL_CONVOLUTION_FORMAT 0x8017 +#define GL_CONVOLUTION_WIDTH 0x8018 +#define GL_CONVOLUTION_HEIGHT 0x8019 +#define GL_MAX_CONVOLUTION_WIDTH 0x801A +#define GL_MAX_CONVOLUTION_HEIGHT 0x801B +#define GL_POST_CONVOLUTION_RED_SCALE 0x801C +#define GL_POST_CONVOLUTION_GREEN_SCALE 0x801D +#define GL_POST_CONVOLUTION_BLUE_SCALE 0x801E +#define GL_POST_CONVOLUTION_ALPHA_SCALE 0x801F +#define GL_POST_CONVOLUTION_RED_BIAS 0x8020 +#define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 +#define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 +#define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 +#define GL_CONSTANT_BORDER 0x8151 +#define GL_REPLICATE_BORDER 0x8153 +#define GL_CONVOLUTION_BORDER_COLOR 0x8154 + +/* draw_range_elements */ +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 + +/* histogram */ +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_HISTOGRAM_WIDTH 0x8026 +#define GL_HISTOGRAM_FORMAT 0x8027 +#define GL_HISTOGRAM_RED_SIZE 0x8028 +#define GL_HISTOGRAM_GREEN_SIZE 0x8029 +#define GL_HISTOGRAM_BLUE_SIZE 0x802A +#define GL_HISTOGRAM_ALPHA_SIZE 0x802B +#define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C +#define GL_HISTOGRAM_SINK 0x802D +#define GL_MINMAX 0x802E +#define GL_MINMAX_FORMAT 0x802F +#define GL_MINMAX_SINK 0x8030 +#define GL_TABLE_TOO_LARGE 0x8031 + +/* packed_pixels */ +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 + +/* rescale_normal */ +#define GL_RESCALE_NORMAL 0x803A + +/* separate_specular_color */ +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA + +/* texture3D */ +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 + +/* texture_edge_clamp */ +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_CLAMP_TO_BORDER 0x812D + +/* texture_lod */ +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D + +/* GetTarget1_2 */ +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E + +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 + +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_SUBTRACT 0x84E7 + +#define GL_SRC0_RGB 0x8580 +#define GL_SRC1_RGB 0x8581 +#define GL_SRC2_RGB 0x8582 +#define GL_SRC3_RGB 0x8583 +#define GL_SRC4_RGB 0x8584 +#define GL_SRC5_RGB 0x8585 +#define GL_SRC6_RGB 0x8586 +#define GL_SRC7_RGB 0x8587 +#define GL_SRC0_ALPHA 0x8588 +#define GL_SRC1_ALPHA 0x8589 +#define GL_SRC2_ALPHA 0x858A +#define GL_SRC3_ALPHA 0x858B +#define GL_SRC4_ALPHA 0x858C +#define GL_SRC5_ALPHA 0x858D +#define GL_SRC6_ALPHA 0x858E +#define GL_SRC7_ALPHA 0x858F + +/* Obsolete */ +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE3_RGB 0x8583 +#define GL_SOURCE4_RGB 0x8584 +#define GL_SOURCE5_RGB 0x8585 +#define GL_SOURCE6_RGB 0x8586 +#define GL_SOURCE7_RGB 0x8587 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_SOURCE3_ALPHA 0x858B +#define GL_SOURCE4_ALPHA 0x858C +#define GL_SOURCE5_ALPHA 0x858D +#define GL_SOURCE6_ALPHA 0x858E +#define GL_SOURCE7_ALPHA 0x858F + +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND3_RGB 0x8593 +#define GL_OPERAND4_RGB 0x8594 +#define GL_OPERAND5_RGB 0x8595 +#define GL_OPERAND6_RGB 0x8596 +#define GL_OPERAND7_RGB 0x8597 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_OPERAND3_ALPHA 0x859B +#define GL_OPERAND4_ALPHA 0x859C +#define GL_OPERAND5_ALPHA 0x859D +#define GL_OPERAND6_ALPHA 0x859E +#define GL_OPERAND7_ALPHA 0x859F + +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF + +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 + +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C + +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 + +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_MULTISAMPLE_BIT 0x20000000 + +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_DEPTH_TEXTURE_MODE 0x884B + +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_COMPARE_R_TO_TEXTURE 0x884E + +/* occlusion_query */ +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_SAMPLES_PASSED 0x8914 + +#define GL_FOG_COORD_SRC 0x8450 +#define GL_FOG_COORD 0x8451 +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_CURRENT_FOG_COORD 0x8453 +#define GL_FOG_COORD_ARRAY_TYPE 0x8454 +#define GL_FOG_COORD_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORD_ARRAY_POINTER 0x8456 +#define GL_FOG_COORD_ARRAY 0x8457 + +/* Obsolete */ +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORDINATE 0x8451 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY 0x8457 + +#define GL_COLOR_SUM 0x8458 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY 0x845E + +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 + +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB + +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 + +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 + +#define GL_MIRRORED_REPEAT 0x8370 + +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_LOD_BIAS 0x8501 + +/* vertex_buffer_object */ +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +/* Obsolete */ +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D + +/* OpenGL20 */ +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 + +/*************************************************************/ + +#ifdef GL_GLEXT_FUNCTION_POINTERS +typedef void (* glAccumProcPtr) (GLenum op, GLfloat value); +typedef void (* glAlphaFuncProcPtr) (GLenum func, GLclampf ref); +typedef GLboolean (* glAreTexturesResidentProcPtr) (GLsizei n, const GLuint *textures, GLboolean *residences); +typedef void (* glArrayElementProcPtr) (GLint i); +typedef void (* glBeginProcPtr) (GLenum mode); +typedef void (* glBindTextureProcPtr) (GLenum target, GLuint texture); +typedef void (* glBitmapProcPtr) (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +typedef void (* glBlendColorProcPtr) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (* glBlendEquationProcPtr) (GLenum mode); +typedef void (* glBlendEquationSeparateProcPtr) (GLenum modeRGB, GLenum modeAlpha); +typedef void (* glBlendFuncProcPtr) (GLenum sfactor, GLenum dfactor); +typedef void (* glCallListProcPtr) (GLuint list); +typedef void (* glCallListsProcPtr) (GLsizei n, GLenum type, const GLvoid *lists); +typedef void (* glClearProcPtr) (GLbitfield mask); +typedef void (* glClearAccumProcPtr) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (* glClearColorProcPtr) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +typedef void (* glClearDepthProcPtr) (GLclampd depth); +typedef void (* glClearIndexProcPtr) (GLfloat c); +typedef void (* glClearStencilProcPtr) (GLint s); +typedef void (* glClipPlaneProcPtr) (GLenum plane, const GLdouble *equation); +typedef void (* glColor3bProcPtr) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (* glColor3bvProcPtr) (const GLbyte *v); +typedef void (* glColor3dProcPtr) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (* glColor3dvProcPtr) (const GLdouble *v); +typedef void (* glColor3fProcPtr) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (* glColor3fvProcPtr) (const GLfloat *v); +typedef void (* glColor3iProcPtr) (GLint red, GLint green, GLint blue); +typedef void (* glColor3ivProcPtr) (const GLint *v); +typedef void (* glColor3sProcPtr) (GLshort red, GLshort green, GLshort blue); +typedef void (* glColor3svProcPtr) (const GLshort *v); +typedef void (* glColor3ubProcPtr) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (* glColor3ubvProcPtr) (const GLubyte *v); +typedef void (* glColor3uiProcPtr) (GLuint red, GLuint green, GLuint blue); +typedef void (* glColor3uivProcPtr) (const GLuint *v); +typedef void (* glColor3usProcPtr) (GLushort red, GLushort green, GLushort blue); +typedef void (* glColor3usvProcPtr) (const GLushort *v); +typedef void (* glColor4bProcPtr) (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +typedef void (* glColor4bvProcPtr) (const GLbyte *v); +typedef void (* glColor4dProcPtr) (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +typedef void (* glColor4dvProcPtr) (const GLdouble *v); +typedef void (* glColor4fProcPtr) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (* glColor4fvProcPtr) (const GLfloat *v); +typedef void (* glColor4iProcPtr) (GLint red, GLint green, GLint blue, GLint alpha); +typedef void (* glColor4ivProcPtr) (const GLint *v); +typedef void (* glColor4sProcPtr) (GLshort red, GLshort green, GLshort blue, GLshort alpha); +typedef void (* glColor4svProcPtr) (const GLshort *v); +typedef void (* glColor4ubProcPtr) (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +typedef void (* glColor4ubvProcPtr) (const GLubyte *v); +typedef void (* glColor4uiProcPtr) (GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (* glColor4uivProcPtr) (const GLuint *v); +typedef void (* glColor4usProcPtr) (GLushort red, GLushort green, GLushort blue, GLushort alpha); +typedef void (* glColor4usvProcPtr) (const GLushort *v); +typedef void (* glColorMaskProcPtr) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (* glColorMaterialProcPtr) (GLenum face, GLenum mode); +typedef void (* glColorPointerProcPtr) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (* glColorSubTableProcPtr) (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +typedef void (* glColorTableProcPtr) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +typedef void (* glColorTableParameterfvProcPtr) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (* glColorTableParameterivProcPtr) (GLenum target, GLenum pname, const GLint *params); +typedef void (* glConvolutionFilter1DProcPtr) (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +typedef void (* glConvolutionFilter2DProcPtr) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +typedef void (* glConvolutionParameterfProcPtr) (GLenum target, GLenum pname, GLfloat params); +typedef void (* glConvolutionParameterfvProcPtr) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (* glConvolutionParameteriProcPtr) (GLenum target, GLenum pname, GLint params); +typedef void (* glConvolutionParameterivProcPtr) (GLenum target, GLenum pname, const GLint *params); +typedef void (* glCopyColorSubTableProcPtr) (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +typedef void (* glCopyColorTableProcPtr) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (* glCopyConvolutionFilter1DProcPtr) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +typedef void (* glCopyConvolutionFilter2DProcPtr) (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (* glCopyPixelsProcPtr) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +typedef void (* glCopyTexImage1DProcPtr) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (* glCopyTexImage2DProcPtr) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (* glCopyTexSubImage1DProcPtr) (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (* glCopyTexSubImage2DProcPtr) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (* glCopyTexSubImage3DProcPtr) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (* glCullFaceProcPtr) (GLenum mode); +typedef void (* glDeleteListsProcPtr) (GLuint list, GLsizei range); +typedef void (* glDeleteTexturesProcPtr) (GLsizei n, const GLuint *textures); +typedef void (* glDepthFuncProcPtr) (GLenum func); +typedef void (* glDepthMaskProcPtr) (GLboolean flag); +typedef void (* glDepthRangeProcPtr) (GLclampd zNear, GLclampd zFar); +typedef void (* glDisableProcPtr) (GLenum cap); +typedef void (* glDisableClientStateProcPtr) (GLenum array); +typedef void (* glDrawArraysProcPtr) (GLenum mode, GLint first, GLsizei count); +typedef void (* glDrawBufferProcPtr) (GLenum mode); +typedef void (* glDrawElementsProcPtr) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (* glDrawPixelsProcPtr) (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (* glDrawRangeElementsProcPtr) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (* glEdgeFlagProcPtr) (GLboolean flag); +typedef void (* glEdgeFlagPointerProcPtr) (GLsizei stride, const GLvoid *pointer); +typedef void (* glEdgeFlagvProcPtr) (const GLboolean *flag); +typedef void (* glEnableProcPtr) (GLenum cap); +typedef void (* glEnableClientStateProcPtr) (GLenum array); +typedef void (* glEndProcPtr) (void); +typedef void (* glEndListProcPtr) (void); +typedef void (* glEvalCoord1dProcPtr) (GLdouble u); +typedef void (* glEvalCoord1dvProcPtr) (const GLdouble *u); +typedef void (* glEvalCoord1fProcPtr) (GLfloat u); +typedef void (* glEvalCoord1fvProcPtr) (const GLfloat *u); +typedef void (* glEvalCoord2dProcPtr) (GLdouble u, GLdouble v); +typedef void (* glEvalCoord2dvProcPtr) (const GLdouble *u); +typedef void (* glEvalCoord2fProcPtr) (GLfloat u, GLfloat v); +typedef void (* glEvalCoord2fvProcPtr) (const GLfloat *u); +typedef void (* glEvalMesh1ProcPtr) (GLenum mode, GLint i1, GLint i2); +typedef void (* glEvalMesh2ProcPtr) (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +typedef void (* glEvalPoint1ProcPtr) (GLint i); +typedef void (* glEvalPoint2ProcPtr) (GLint i, GLint j); +typedef void (* glFeedbackBufferProcPtr) (GLsizei size, GLenum type, GLfloat *buffer); +typedef void (* glFinishProcPtr) (void); +typedef void (* glFlushProcPtr) (void); +typedef void (* glFogfProcPtr) (GLenum pname, GLfloat param); +typedef void (* glFogfvProcPtr) (GLenum pname, const GLfloat *params); +typedef void (* glFogiProcPtr) (GLenum pname, GLint param); +typedef void (* glFogivProcPtr) (GLenum pname, const GLint *params); +typedef void (* glFrontFaceProcPtr) (GLenum mode); +typedef void (* glFrustumProcPtr) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef GLuint (* glGenListsProcPtr) (GLsizei range); +typedef void (* glGenTexturesProcPtr) (GLsizei n, GLuint *textures); +typedef void (* glGetBooleanvProcPtr) (GLenum pname, GLboolean *params); +typedef void (* glGetClipPlaneProcPtr) (GLenum plane, GLdouble *equation); +typedef void (* glGetColorTableProcPtr) (GLenum target, GLenum format, GLenum type, GLvoid *table); +typedef void (* glGetColorTableParameterfvProcPtr) (GLenum target, GLenum pname, GLfloat *params); +typedef void (* glGetColorTableParameterivProcPtr) (GLenum target, GLenum pname, GLint *params); +typedef void (* glGetConvolutionFilterProcPtr) (GLenum target, GLenum format, GLenum type, GLvoid *image); +typedef void (* glGetConvolutionParameterfvProcPtr) (GLenum target, GLenum pname, GLfloat *params); +typedef void (* glGetConvolutionParameterivProcPtr) (GLenum target, GLenum pname, GLint *params); +typedef void (* glGetDoublevProcPtr) (GLenum pname, GLdouble *params); +typedef GLenum (* glGetErrorProcPtr) (void); +typedef void (* glGetFloatvProcPtr) (GLenum pname, GLfloat *params); +typedef void (* glGetHistogramProcPtr) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (* glGetHistogramParameterfvProcPtr) (GLenum target, GLenum pname, GLfloat *params); +typedef void (* glGetHistogramParameterivProcPtr) (GLenum target, GLenum pname, GLint *params); +typedef void (* glGetIntegervProcPtr) (GLenum pname, GLint *params); +typedef void (* glGetLightfvProcPtr) (GLenum light, GLenum pname, GLfloat *params); +typedef void (* glGetLightivProcPtr) (GLenum light, GLenum pname, GLint *params); +typedef void (* glGetMapdvProcPtr) (GLenum target, GLenum query, GLdouble *v); +typedef void (* glGetMapfvProcPtr) (GLenum target, GLenum query, GLfloat *v); +typedef void (* glGetMapivProcPtr) (GLenum target, GLenum query, GLint *v); +typedef void (* glGetMaterialfvProcPtr) (GLenum face, GLenum pname, GLfloat *params); +typedef void (* glGetMaterialivProcPtr) (GLenum face, GLenum pname, GLint *params); +typedef void (* glGetMinmaxProcPtr) (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +typedef void (* glGetMinmaxParameterfvProcPtr) (GLenum target, GLenum pname, GLfloat *params); +typedef void (* glGetMinmaxParameterivProcPtr) (GLenum target, GLenum pname, GLint *params); +typedef void (* glGetPixelMapfvProcPtr) (GLenum map, GLfloat *values); +typedef void (* glGetPixelMapuivProcPtr) (GLenum map, GLuint *values); +typedef void (* glGetPixelMapusvProcPtr) (GLenum map, GLushort *values); +typedef void (* glGetPointervProcPtr) (GLenum pname, GLvoid* *params); +typedef void (* glGetPolygonStippleProcPtr) (GLubyte *mask); +typedef void (* glGetSeparableFilterProcPtr) (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +typedef const GLubyte * (* glGetStringProcPtr) (GLenum name); +typedef void (* glGetTexEnvfvProcPtr) (GLenum target, GLenum pname, GLfloat *params); +typedef void (* glGetTexEnvivProcPtr) (GLenum target, GLenum pname, GLint *params); +typedef void (* glGetTexGendvProcPtr) (GLenum coord, GLenum pname, GLdouble *params); +typedef void (* glGetTexGenfvProcPtr) (GLenum coord, GLenum pname, GLfloat *params); +typedef void (* glGetTexGenivProcPtr) (GLenum coord, GLenum pname, GLint *params); +typedef void (* glGetTexImageProcPtr) (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +typedef void (* glGetTexLevelParameterfvProcPtr) (GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (* glGetTexLevelParameterivProcPtr) (GLenum target, GLint level, GLenum pname, GLint *params); +typedef void (* glGetTexParameterfvProcPtr) (GLenum target, GLenum pname, GLfloat *params); +typedef void (* glGetTexParameterivProcPtr) (GLenum target, GLenum pname, GLint *params); +typedef void (* glHintProcPtr) (GLenum target, GLenum mode); +typedef void (* glHistogramProcPtr) (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +typedef void (* glIndexMaskProcPtr) (GLuint mask); +typedef void (* glIndexPointerProcPtr) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (* glIndexdProcPtr) (GLdouble c); +typedef void (* glIndexdvProcPtr) (const GLdouble *c); +typedef void (* glIndexfProcPtr) (GLfloat c); +typedef void (* glIndexfvProcPtr) (const GLfloat *c); +typedef void (* glIndexiProcPtr) (GLint c); +typedef void (* glIndexivProcPtr) (const GLint *c); +typedef void (* glIndexsProcPtr) (GLshort c); +typedef void (* glIndexsvProcPtr) (const GLshort *c); +typedef void (* glIndexubProcPtr) (GLubyte c); +typedef void (* glIndexubvProcPtr) (const GLubyte *c); +typedef void (* glInitNamesProcPtr) (void); +typedef void (* glInterleavedArraysProcPtr) (GLenum format, GLsizei stride, const GLvoid *pointer); +typedef GLboolean (* glIsEnabledProcPtr) (GLenum cap); +typedef GLboolean (* glIsListProcPtr) (GLuint list); +typedef GLboolean (* glIsTextureProcPtr) (GLuint texture); +typedef void (* glLightModelfProcPtr) (GLenum pname, GLfloat param); +typedef void (* glLightModelfvProcPtr) (GLenum pname, const GLfloat *params); +typedef void (* glLightModeliProcPtr) (GLenum pname, GLint param); +typedef void (* glLightModelivProcPtr) (GLenum pname, const GLint *params); +typedef void (* glLightfProcPtr) (GLenum light, GLenum pname, GLfloat param); +typedef void (* glLightfvProcPtr) (GLenum light, GLenum pname, const GLfloat *params); +typedef void (* glLightiProcPtr) (GLenum light, GLenum pname, GLint param); +typedef void (* glLightivProcPtr) (GLenum light, GLenum pname, const GLint *params); +typedef void (* glLineStippleProcPtr) (GLint factor, GLushort pattern); +typedef void (* glLineWidthProcPtr) (GLfloat width); +typedef void (* glListBaseProcPtr) (GLuint base); +typedef void (* glLoadIdentityProcPtr) (void); +typedef void (* glLoadMatrixdProcPtr) (const GLdouble *m); +typedef void (* glLoadMatrixfProcPtr) (const GLfloat *m); +typedef void (* glLoadNameProcPtr) (GLuint name); +typedef void (* glLogicOpProcPtr) (GLenum opcode); +typedef void (* glMap1dProcPtr) (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +typedef void (* glMap1fProcPtr) (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +typedef void (* glMap2dProcPtr) (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +typedef void (* glMap2fProcPtr) (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +typedef void (* glMapGrid1dProcPtr) (GLint un, GLdouble u1, GLdouble u2); +typedef void (* glMapGrid1fProcPtr) (GLint un, GLfloat u1, GLfloat u2); +typedef void (* glMapGrid2dProcPtr) (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +typedef void (* glMapGrid2fProcPtr) (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +typedef void (* glMaterialfProcPtr) (GLenum face, GLenum pname, GLfloat param); +typedef void (* glMaterialfvProcPtr) (GLenum face, GLenum pname, const GLfloat *params); +typedef void (* glMaterialiProcPtr) (GLenum face, GLenum pname, GLint param); +typedef void (* glMaterialivProcPtr) (GLenum face, GLenum pname, const GLint *params); +typedef void (* glMatrixModeProcPtr) (GLenum mode); +typedef void (* glMinmaxProcPtr) (GLenum target, GLenum internalformat, GLboolean sink); +typedef void (* glMultMatrixdProcPtr) (const GLdouble *m); +typedef void (* glMultMatrixfProcPtr) (const GLfloat *m); +typedef void (* glNewListProcPtr) (GLuint list, GLenum mode); +typedef void (* glNormal3bProcPtr) (GLbyte nx, GLbyte ny, GLbyte nz); +typedef void (* glNormal3bvProcPtr) (const GLbyte *v); +typedef void (* glNormal3dProcPtr) (GLdouble nx, GLdouble ny, GLdouble nz); +typedef void (* glNormal3dvProcPtr) (const GLdouble *v); +typedef void (* glNormal3fProcPtr) (GLfloat nx, GLfloat ny, GLfloat nz); +typedef void (* glNormal3fvProcPtr) (const GLfloat *v); +typedef void (* glNormal3iProcPtr) (GLint nx, GLint ny, GLint nz); +typedef void (* glNormal3ivProcPtr) (const GLint *v); +typedef void (* glNormal3sProcPtr) (GLshort nx, GLshort ny, GLshort nz); +typedef void (* glNormal3svProcPtr) (const GLshort *v); +typedef void (* glNormalPointerProcPtr) (GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (* glOrthoProcPtr) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (* glPassThroughProcPtr) (GLfloat token); +typedef void (* glPixelMapfvProcPtr) (GLenum map, GLint mapsize, const GLfloat *values); +typedef void (* glPixelMapuivProcPtr) (GLenum map, GLint mapsize, const GLuint *values); +typedef void (* glPixelMapusvProcPtr) (GLenum map, GLint mapsize, const GLushort *values); +typedef void (* glPixelStorefProcPtr) (GLenum pname, GLfloat param); +typedef void (* glPixelStoreiProcPtr) (GLenum pname, GLint param); +typedef void (* glPixelTransferfProcPtr) (GLenum pname, GLfloat param); +typedef void (* glPixelTransferiProcPtr) (GLenum pname, GLint param); +typedef void (* glPixelZoomProcPtr) (GLfloat xfactor, GLfloat yfactor); +typedef void (* glPointSizeProcPtr) (GLfloat size); +typedef void (* glPolygonModeProcPtr) (GLenum face, GLenum mode); +typedef void (* glPolygonOffsetProcPtr) (GLfloat factor, GLfloat units); +typedef void (* glPolygonStippleProcPtr) (const GLubyte *mask); +typedef void (* glPopAttribProcPtr) (void); +typedef void (* glPopClientAttribProcPtr) (void); +typedef void (* glPopMatrixProcPtr) (void); +typedef void (* glPopNameProcPtr) (void); +typedef void (* glPrioritizeTexturesProcPtr) (GLsizei n, const GLuint *textures, const GLclampf *priorities); +typedef void (* glPushAttribProcPtr) (GLbitfield mask); +typedef void (* glPushClientAttribProcPtr) (GLbitfield mask); +typedef void (* glPushMatrixProcPtr) (void); +typedef void (* glPushNameProcPtr) (GLuint name); +typedef void (* glRasterPos2dProcPtr) (GLdouble x, GLdouble y); +typedef void (* glRasterPos2dvProcPtr) (const GLdouble *v); +typedef void (* glRasterPos2fProcPtr) (GLfloat x, GLfloat y); +typedef void (* glRasterPos2fvProcPtr) (const GLfloat *v); +typedef void (* glRasterPos2iProcPtr) (GLint x, GLint y); +typedef void (* glRasterPos2ivProcPtr) (const GLint *v); +typedef void (* glRasterPos2sProcPtr) (GLshort x, GLshort y); +typedef void (* glRasterPos2svProcPtr) (const GLshort *v); +typedef void (* glRasterPos3dProcPtr) (GLdouble x, GLdouble y, GLdouble z); +typedef void (* glRasterPos3dvProcPtr) (const GLdouble *v); +typedef void (* glRasterPos3fProcPtr) (GLfloat x, GLfloat y, GLfloat z); +typedef void (* glRasterPos3fvProcPtr) (const GLfloat *v); +typedef void (* glRasterPos3iProcPtr) (GLint x, GLint y, GLint z); +typedef void (* glRasterPos3ivProcPtr) (const GLint *v); +typedef void (* glRasterPos3sProcPtr) (GLshort x, GLshort y, GLshort z); +typedef void (* glRasterPos3svProcPtr) (const GLshort *v); +typedef void (* glRasterPos4dProcPtr) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (* glRasterPos4dvProcPtr) (const GLdouble *v); +typedef void (* glRasterPos4fProcPtr) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (* glRasterPos4fvProcPtr) (const GLfloat *v); +typedef void (* glRasterPos4iProcPtr) (GLint x, GLint y, GLint z, GLint w); +typedef void (* glRasterPos4ivProcPtr) (const GLint *v); +typedef void (* glRasterPos4sProcPtr) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (* glRasterPos4svProcPtr) (const GLshort *v); +typedef void (* glReadBufferProcPtr) (GLenum mode); +typedef void (* glReadPixelsProcPtr) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +typedef void (* glRectdProcPtr) (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +typedef void (* glRectdvProcPtr) (const GLdouble *v1, const GLdouble *v2); +typedef void (* glRectfProcPtr) (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +typedef void (* glRectfvProcPtr) (const GLfloat *v1, const GLfloat *v2); +typedef void (* glRectiProcPtr) (GLint x1, GLint y1, GLint x2, GLint y2); +typedef void (* glRectivProcPtr) (const GLint *v1, const GLint *v2); +typedef void (* glRectsProcPtr) (GLshort x1, GLshort y1, GLshort x2, GLshort y2); +typedef void (* glRectsvProcPtr) (const GLshort *v1, const GLshort *v2); +typedef GLint (* glRenderModeProcPtr) (GLenum mode); +typedef void (* glResetHistogramProcPtr) (GLenum target); +typedef void (* glResetMinmaxProcPtr) (GLenum target); +typedef void (* glRotatedProcPtr) (GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (* glRotatefProcPtr) (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (* glScaledProcPtr) (GLdouble x, GLdouble y, GLdouble z); +typedef void (* glScalefProcPtr) (GLfloat x, GLfloat y, GLfloat z); +typedef void (* glScissorProcPtr) (GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (* glSelectBufferProcPtr) (GLsizei size, GLuint *buffer); +typedef void (* glSeparableFilter2DProcPtr) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +typedef void (* glShadeModelProcPtr) (GLenum mode); +typedef void (* glStencilFuncProcPtr) (GLenum func, GLint ref, GLuint mask); +typedef void (* glStencilMaskProcPtr) (GLuint mask); +typedef void (* glStencilOpProcPtr) (GLenum fail, GLenum zfail, GLenum zpass); +typedef void (* glTexCoord1dProcPtr) (GLdouble s); +typedef void (* glTexCoord1dvProcPtr) (const GLdouble *v); +typedef void (* glTexCoord1fProcPtr) (GLfloat s); +typedef void (* glTexCoord1fvProcPtr) (const GLfloat *v); +typedef void (* glTexCoord1iProcPtr) (GLint s); +typedef void (* glTexCoord1ivProcPtr) (const GLint *v); +typedef void (* glTexCoord1sProcPtr) (GLshort s); +typedef void (* glTexCoord1svProcPtr) (const GLshort *v); +typedef void (* glTexCoord2dProcPtr) (GLdouble s, GLdouble t); +typedef void (* glTexCoord2dvProcPtr) (const GLdouble *v); +typedef void (* glTexCoord2fProcPtr) (GLfloat s, GLfloat t); +typedef void (* glTexCoord2fvProcPtr) (const GLfloat *v); +typedef void (* glTexCoord2iProcPtr) (GLint s, GLint t); +typedef void (* glTexCoord2ivProcPtr) (const GLint *v); +typedef void (* glTexCoord2sProcPtr) (GLshort s, GLshort t); +typedef void (* glTexCoord2svProcPtr) (const GLshort *v); +typedef void (* glTexCoord3dProcPtr) (GLdouble s, GLdouble t, GLdouble r); +typedef void (* glTexCoord3dvProcPtr) (const GLdouble *v); +typedef void (* glTexCoord3fProcPtr) (GLfloat s, GLfloat t, GLfloat r); +typedef void (* glTexCoord3fvProcPtr) (const GLfloat *v); +typedef void (* glTexCoord3iProcPtr) (GLint s, GLint t, GLint r); +typedef void (* glTexCoord3ivProcPtr) (const GLint *v); +typedef void (* glTexCoord3sProcPtr) (GLshort s, GLshort t, GLshort r); +typedef void (* glTexCoord3svProcPtr) (const GLshort *v); +typedef void (* glTexCoord4dProcPtr) (GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (* glTexCoord4dvProcPtr) (const GLdouble *v); +typedef void (* glTexCoord4fProcPtr) (GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (* glTexCoord4fvProcPtr) (const GLfloat *v); +typedef void (* glTexCoord4iProcPtr) (GLint s, GLint t, GLint r, GLint q); +typedef void (* glTexCoord4ivProcPtr) (const GLint *v); +typedef void (* glTexCoord4sProcPtr) (GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (* glTexCoord4svProcPtr) (const GLshort *v); +typedef void (* glTexCoordPointerProcPtr) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (* glTexEnvfProcPtr) (GLenum target, GLenum pname, GLfloat param); +typedef void (* glTexEnvfvProcPtr) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (* glTexEnviProcPtr) (GLenum target, GLenum pname, GLint param); +typedef void (* glTexEnvivProcPtr) (GLenum target, GLenum pname, const GLint *params); +typedef void (* glTexGendProcPtr) (GLenum coord, GLenum pname, GLdouble param); +typedef void (* glTexGendvProcPtr) (GLenum coord, GLenum pname, const GLdouble *params); +typedef void (* glTexGenfProcPtr) (GLenum coord, GLenum pname, GLfloat param); +typedef void (* glTexGenfvProcPtr) (GLenum coord, GLenum pname, const GLfloat *params); +typedef void (* glTexGeniProcPtr) (GLenum coord, GLenum pname, GLint param); +typedef void (* glTexGenivProcPtr) (GLenum coord, GLenum pname, const GLint *params); +typedef void (* glTexImage1DProcPtr) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (* glTexImage2DProcPtr) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (* glTexImage3DProcPtr) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (* glTexParameterfProcPtr) (GLenum target, GLenum pname, GLfloat param); +typedef void (* glTexParameterfvProcPtr) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (* glTexParameteriProcPtr) (GLenum target, GLenum pname, GLint param); +typedef void (* glTexParameterivProcPtr) (GLenum target, GLenum pname, const GLint *params); +typedef void (* glTexSubImage1DProcPtr) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (* glTexSubImage2DProcPtr) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (* glTexSubImage3DProcPtr) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (* glTranslatedProcPtr) (GLdouble x, GLdouble y, GLdouble z); +typedef void (* glTranslatefProcPtr) (GLfloat x, GLfloat y, GLfloat z); +typedef void (* glVertex2dProcPtr) (GLdouble x, GLdouble y); +typedef void (* glVertex2dvProcPtr) (const GLdouble *v); +typedef void (* glVertex2fProcPtr) (GLfloat x, GLfloat y); +typedef void (* glVertex2fvProcPtr) (const GLfloat *v); +typedef void (* glVertex2iProcPtr) (GLint x, GLint y); +typedef void (* glVertex2ivProcPtr) (const GLint *v); +typedef void (* glVertex2sProcPtr) (GLshort x, GLshort y); +typedef void (* glVertex2svProcPtr) (const GLshort *v); +typedef void (* glVertex3dProcPtr) (GLdouble x, GLdouble y, GLdouble z); +typedef void (* glVertex3dvProcPtr) (const GLdouble *v); +typedef void (* glVertex3fProcPtr) (GLfloat x, GLfloat y, GLfloat z); +typedef void (* glVertex3fvProcPtr) (const GLfloat *v); +typedef void (* glVertex3iProcPtr) (GLint x, GLint y, GLint z); +typedef void (* glVertex3ivProcPtr) (const GLint *v); +typedef void (* glVertex3sProcPtr) (GLshort x, GLshort y, GLshort z); +typedef void (* glVertex3svProcPtr) (const GLshort *v); +typedef void (* glVertex4dProcPtr) (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (* glVertex4dvProcPtr) (const GLdouble *v); +typedef void (* glVertex4fProcPtr) (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (* glVertex4fvProcPtr) (const GLfloat *v); +typedef void (* glVertex4iProcPtr) (GLint x, GLint y, GLint z, GLint w); +typedef void (* glVertex4ivProcPtr) (const GLint *v); +typedef void (* glVertex4sProcPtr) (GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (* glVertex4svProcPtr) (const GLshort *v); +typedef void (* glVertexPointerProcPtr) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (* glViewportProcPtr) (GLint x, GLint y, GLsizei width, GLsizei height); + +typedef void (* glSampleCoverageProcPtr) (GLclampf value, GLboolean invert); +typedef void (* glSamplePassProcPtr) (GLenum pass); + +typedef void (* glLoadTransposeMatrixfProcPtr) (const GLfloat *m); +typedef void (* glLoadTransposeMatrixdProcPtr) (const GLdouble *m); +typedef void (* glMultTransposeMatrixfProcPtr) (const GLfloat *m); +typedef void (* glMultTransposeMatrixdProcPtr) (const GLdouble *m); + +typedef void (* glCompressedTexImage3DProcPtr) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (* glCompressedTexImage2DProcPtr) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (* glCompressedTexImage1DProcPtr) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +typedef void (* glCompressedTexSubImage3DProcPtr) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (* glCompressedTexSubImage2DProcPtr) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (* glCompressedTexSubImage1DProcPtr) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +typedef void (* glGetCompressedTexImageProcPtr) (GLenum target, GLint lod, GLvoid *img); + +typedef void (* glActiveTextureProcPtr) (GLenum texture); +typedef void (* glClientActiveTextureProcPtr) (GLenum texture); +typedef void (* glMultiTexCoord1dProcPtr) (GLenum target, GLdouble s); +typedef void (* glMultiTexCoord1dvProcPtr) (GLenum target, const GLdouble *v); +typedef void (* glMultiTexCoord1fProcPtr) (GLenum target, GLfloat s); +typedef void (* glMultiTexCoord1fvProcPtr) (GLenum target, const GLfloat *v); +typedef void (* glMultiTexCoord1iProcPtr) (GLenum target, GLint s); +typedef void (* glMultiTexCoord1ivProcPtr) (GLenum target, const GLint *v); +typedef void (* glMultiTexCoord1sProcPtr) (GLenum target, GLshort s); +typedef void (* glMultiTexCoord1svProcPtr) (GLenum target, const GLshort *v); +typedef void (* glMultiTexCoord2dProcPtr) (GLenum target, GLdouble s, GLdouble t); +typedef void (* glMultiTexCoord2dvProcPtr) (GLenum target, const GLdouble *v); +typedef void (* glMultiTexCoord2fProcPtr) (GLenum target, GLfloat s, GLfloat t); +typedef void (* glMultiTexCoord2fvProcPtr) (GLenum target, const GLfloat *v); +typedef void (* glMultiTexCoord2iProcPtr) (GLenum target, GLint s, GLint t); +typedef void (* glMultiTexCoord2ivProcPtr) (GLenum target, const GLint *v); +typedef void (* glMultiTexCoord2sProcPtr) (GLenum target, GLshort s, GLshort t); +typedef void (* glMultiTexCoord2svProcPtr) (GLenum target, const GLshort *v); +typedef void (* glMultiTexCoord3dProcPtr) (GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (* glMultiTexCoord3dvProcPtr) (GLenum target, const GLdouble *v); +typedef void (* glMultiTexCoord3fProcPtr) (GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (* glMultiTexCoord3fvProcPtr) (GLenum target, const GLfloat *v); +typedef void (* glMultiTexCoord3iProcPtr) (GLenum target, GLint s, GLint t, GLint r); +typedef void (* glMultiTexCoord3ivProcPtr) (GLenum target, const GLint *v); +typedef void (* glMultiTexCoord3sProcPtr) (GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (* glMultiTexCoord3svProcPtr) (GLenum target, const GLshort *v); +typedef void (* glMultiTexCoord4dProcPtr) (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (* glMultiTexCoord4dvProcPtr) (GLenum target, const GLdouble *v); +typedef void (* glMultiTexCoord4fProcPtr) (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (* glMultiTexCoord4fvProcPtr) (GLenum target, const GLfloat *v); +typedef void (* glMultiTexCoord4iProcPtr) (GLenum target, GLint, GLint s, GLint t, GLint r); +typedef void (* glMultiTexCoord4ivProcPtr) (GLenum target, const GLint *v); +typedef void (* glMultiTexCoord4sProcPtr) (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (* glMultiTexCoord4svProcPtr) (GLenum target, const GLshort *v); + +typedef void (* glFogCoordfProcPtr) (GLfloat coord); +typedef void (* glFogCoordfvProcPtr) (const GLfloat *coord); +typedef void (* glFogCoorddProcPtr) (GLdouble coord); +typedef void (* glFogCoorddvProcPtr) (const GLdouble *coord); +typedef void (* glFogCoordPointerProcPtr) (GLenum type, GLsizei stride, const GLvoid *pointer); + +typedef void (* glSecondaryColor3bProcPtr) (GLbyte red, GLbyte green, GLbyte blue); +typedef void (* glSecondaryColor3bvProcPtr) (const GLbyte *v); +typedef void (* glSecondaryColor3dProcPtr) (GLdouble red, GLdouble green, GLdouble blue); +typedef void (* glSecondaryColor3dvProcPtr) (const GLdouble *v); +typedef void (* glSecondaryColor3fProcPtr) (GLfloat red, GLfloat green, GLfloat blue); +typedef void (* glSecondaryColor3fvProcPtr) (const GLfloat *v); +typedef void (* glSecondaryColor3iProcPtr) (GLint red, GLint green, GLint blue); +typedef void (* glSecondaryColor3ivProcPtr) (const GLint *v); +typedef void (* glSecondaryColor3sProcPtr) (GLshort red, GLshort green, GLshort blue); +typedef void (* glSecondaryColor3svProcPtr) (const GLshort *v); +typedef void (* glSecondaryColor3ubProcPtr) (GLubyte red, GLubyte green, GLubyte blue); +typedef void (* glSecondaryColor3ubvProcPtr) (const GLubyte *v); +typedef void (* glSecondaryColor3uiProcPtr) (GLuint red, GLuint green, GLuint blue); +typedef void (* glSecondaryColor3uivProcPtr) (const GLuint *v); +typedef void (* glSecondaryColor3usProcPtr) (GLushort red, GLushort green, GLushort blue); +typedef void (* glSecondaryColor3usvProcPtr) (const GLushort *v); +typedef void (* glSecondaryColorPointerProcPtr) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + +typedef void (* glPointParameterfProcPtr) (GLenum pname, GLfloat param); +typedef void (* glPointParameterfvProcPtr) (GLenum pname, const GLfloat *params); +typedef void (* glPointParameteriProcPtr) (GLenum pname, GLint param); +typedef void (* glPointParameterivProcPtr) (GLenum pname, const GLint *params); + +typedef void (* glBlendFuncSeparateProcPtr) (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + +typedef void (* glMultiDrawArraysProcPtr) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +typedef void (* glMultiDrawElementsProcPtr) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); + +typedef void (* glWindowPos2dProcPtr) (GLdouble x, GLdouble y); +typedef void (* glWindowPos2dvProcPtr) (const GLdouble *v); +typedef void (* glWindowPos2fProcPtr) (GLfloat x, GLfloat y); +typedef void (* glWindowPos2fvProcPtr) (const GLfloat *v); +typedef void (* glWindowPos2iProcPtr) (GLint x, GLint y); +typedef void (* glWindowPos2ivProcPtr) (const GLint *v); +typedef void (* glWindowPos2sProcPtr) (GLshort x, GLshort y); +typedef void (* glWindowPos2svProcPtr) (const GLshort *v); +typedef void (* glWindowPos3dProcPtr) (GLdouble x, GLdouble y, GLdouble z); +typedef void (* glWindowPos3dvProcPtr) (const GLdouble *v); +typedef void (* glWindowPos3fProcPtr) (GLfloat x, GLfloat y, GLfloat z); +typedef void (* glWindowPos3fvProcPtr) (const GLfloat *v); +typedef void (* glWindowPos3iProcPtr) (GLint x, GLint y, GLint z); +typedef void (* glWindowPos3ivProcPtr) (const GLint *v); +typedef void (* glWindowPos3sProcPtr) (GLshort x, GLshort y, GLshort z); +typedef void (* glWindowPos3svProcPtr) (const GLshort *v); + +typedef void (* glGenQueriesProcPtr) (GLsizei n, GLuint *ids); +typedef void (* glDeleteQueriesProcPtr) (GLsizei n, const GLuint *ids); +typedef GLboolean (* glIsQueryProcPtr) (GLuint id); +typedef void (* glBeginQueryProcPtr) (GLenum target, GLuint id); +typedef void (* glEndQueryProcPtr) (GLenum target); +typedef void (* glGetQueryivProcPtr) (GLenum target, GLenum pname, GLint *params); +typedef void (* glGetQueryObjectivProcPtr) (GLuint id, GLenum pname, GLint *params); +typedef void (* glGetQueryObjectuivProcPtr) (GLuint id, GLenum pname, GLuint *params); + +typedef void (* glBindBufferProcPtr) (GLenum target, GLuint buffer); +typedef void (* glDeleteBuffersProcPtr) (GLsizei n, const GLuint *buffers); +typedef void (* glGenBuffersProcPtr) (GLsizei n, GLuint *buffers); +typedef GLboolean (* glIsBufferProcPtr) (GLuint buffer); +typedef void (* glBufferDataProcPtr) (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); +typedef void (* glBufferSubDataProcPtr) (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); +typedef void (* glGetBufferSubDataProcPtr) (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); +typedef GLvoid *(* glMapBufferProcPtr) (GLenum target, GLenum access); +typedef GLboolean (* glUnmapBufferProcPtr) (GLenum target); +typedef void (* glGetBufferParameterivProcPtr) (GLenum target, GLenum pname, GLint *params); +typedef void (* glGetBufferPointervProcPtr) (GLenum target, GLenum pname, GLvoid **params); + +typedef void (* glDrawBuffersProcPtr) (GLsizei n, const GLenum *bufs); +typedef void (* glVertexAttrib1dProcPtr) (GLuint index, GLdouble x); +typedef void (* glVertexAttrib1dvProcPtr) (GLuint index, const GLdouble *v); +typedef void (* glVertexAttrib1fProcPtr) (GLuint index, GLfloat x); +typedef void (* glVertexAttrib1fvProcPtr) (GLuint index, const GLfloat *v); +typedef void (* glVertexAttrib1sProcPtr) (GLuint index, GLshort x); +typedef void (* glVertexAttrib1svProcPtr) (GLuint index, const GLshort *v); +typedef void (* glVertexAttrib2dProcPtr) (GLuint index, GLdouble x, GLdouble y); +typedef void (* glVertexAttrib2dvProcPtr) (GLuint index, const GLdouble *v); +typedef void (* glVertexAttrib2fProcPtr) (GLuint index, GLfloat x, GLfloat y); +typedef void (* glVertexAttrib2fvProcPtr) (GLuint index, const GLfloat *v); +typedef void (* glVertexAttrib2sProcPtr) (GLuint index, GLshort x, GLshort y); +typedef void (* glVertexAttrib2svProcPtr) (GLuint index, const GLshort *v); +typedef void (* glVertexAttrib3dProcPtr) (GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (* glVertexAttrib3dvProcPtr) (GLuint index, const GLdouble *v); +typedef void (* glVertexAttrib3fProcPtr) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (* glVertexAttrib3fvProcPtr) (GLuint index, const GLfloat *v); +typedef void (* glVertexAttrib3sProcPtr) (GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (* glVertexAttrib3svProcPtr) (GLuint index, const GLshort *v); +typedef void (* glVertexAttrib4NbvProcPtr) (GLuint index, const GLbyte *v); +typedef void (* glVertexAttrib4NivProcPtr) (GLuint index, const GLint *v); +typedef void (* glVertexAttrib4NsvProcPtr) (GLuint index, const GLshort *v); +typedef void (* glVertexAttrib4NubProcPtr) (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (* glVertexAttrib4NubvProcPtr) (GLuint index, const GLubyte *v); +typedef void (* glVertexAttrib4NuivProcPtr) (GLuint index, const GLuint *v); +typedef void (* glVertexAttrib4NusvProcPtr) (GLuint index, const GLushort *v); +typedef void (* glVertexAttrib4bvProcPtr) (GLuint index, const GLbyte *v); +typedef void (* glVertexAttrib4dProcPtr) (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (* glVertexAttrib4dvProcPtr) (GLuint index, const GLdouble *v); +typedef void (* glVertexAttrib4fProcPtr) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (* glVertexAttrib4fvProcPtr) (GLuint index, const GLfloat *v); +typedef void (* glVertexAttrib4ivProcPtr) (GLuint index, const GLint *v); +typedef void (* glVertexAttrib4sProcPtr) (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (* glVertexAttrib4svProcPtr) (GLuint index, const GLshort *v); +typedef void (* glVertexAttrib4ubvProcPtr) (GLuint index, const GLubyte *v); +typedef void (* glVertexAttrib4uivProcPtr) (GLuint index, const GLuint *v); +typedef void (* glVertexAttrib4usvProcPtr) (GLuint index, const GLushort *v); +typedef void (* glVertexAttribPointerProcPtr) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +typedef void (* glEnableVertexAttribArrayProcPtr) (GLuint index); +typedef void (* glDisableVertexAttribArrayProcPtr) (GLuint index); +typedef void (* glGetVertexAttribdvProcPtr) (GLuint index, GLenum pname, GLdouble *params); +typedef void (* glGetVertexAttribfvProcPtr) (GLuint index, GLenum pname, GLfloat *params); +typedef void (* glGetVertexAttribivProcPtr) (GLuint index, GLenum pname, GLint *params); +typedef void (* glGetVertexAttribPointervProcPtr) (GLuint index, GLenum pname, GLvoid* *pointer); +typedef void (* glDeleteShaderProcPtr) (GLuint shader); +typedef void (* glDetachShaderProcPtr) (GLuint program, GLuint shader); +typedef GLuint (* glCreateShaderProcPtr) (GLenum type); +typedef void (* glShaderSourceProcPtr) (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); +typedef void (* glCompileShaderProcPtr) (GLuint shader); +typedef GLuint (* glCreateProgramProcPtr) (void); +typedef void (* glAttachShaderProcPtr) (GLuint program, GLuint shader); +typedef void (* glLinkProgramProcPtr) (GLuint program); +typedef void (* glUseProgramProcPtr) (GLuint program); +typedef void (* glDeleteProgramProcPtr) (GLuint program); +typedef void (* glValidateProgramProcPtr) (GLuint program); +typedef void (* glUniform1fProcPtr) (GLint location, GLfloat v0); +typedef void (* glUniform2fProcPtr) (GLint location, GLfloat v0, GLfloat v1); +typedef void (* glUniform3fProcPtr) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (* glUniform4fProcPtr) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (* glUniform1iProcPtr) (GLint location, GLint v0); +typedef void (* glUniform2iProcPtr) (GLint location, GLint v0, GLint v1); +typedef void (* glUniform3iProcPtr) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (* glUniform4iProcPtr) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (* glUniform1fvProcPtr) (GLint location, GLsizei count, const GLfloat *value); +typedef void (* glUniform2fvProcPtr) (GLint location, GLsizei count, const GLfloat *value); +typedef void (* glUniform3fvProcPtr) (GLint location, GLsizei count, const GLfloat *value); +typedef void (* glUniform4fvProcPtr) (GLint location, GLsizei count, const GLfloat *value); +typedef void (* glUniform1ivProcPtr) (GLint location, GLsizei count, const GLint *value); +typedef void (* glUniform2ivProcPtr) (GLint location, GLsizei count, const GLint *value); +typedef void (* glUniform3ivProcPtr) (GLint location, GLsizei count, const GLint *value); +typedef void (* glUniform4ivProcPtr) (GLint location, GLsizei count, const GLint *value); +typedef void (* glUniformMatrix2fvProcPtr) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (* glUniformMatrix3fvProcPtr) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (* glUniformMatrix4fvProcPtr) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef GLboolean (* glIsShaderProcPtr) (GLuint shader); +typedef GLboolean (* glIsProgramProcPtr) (GLuint program); +typedef void (* glGetShaderivProcPtr) (GLuint shader, GLenum pname, GLint *params); +typedef void (* glGetProgramivProcPtr) (GLuint program, GLenum pname, GLint *params); +typedef void (* glGetAttachedShadersProcPtr) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +typedef void (* glGetShaderInfoLogProcPtr) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (* glGetProgramInfoLogProcPtr) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef GLint (* glGetUniformLocationProcPtr) (GLuint program, const GLchar *name); +typedef void (* glGetActiveUniformProcPtr) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (* glGetUniformfvProcPtr) (GLuint program, GLint location, GLfloat *params); +typedef void (* glGetUniformivProcPtr) (GLuint program, GLint location, GLint *params); +typedef void (* glGetShaderSourceProcPtr) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +typedef void (* glBindAttribLocationProcPtr) (GLuint program, GLuint index, const GLchar *name); +typedef void (* glGetActiveAttribProcPtr) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef GLint (* glGetAttribLocationProcPtr) (GLuint program, const GLchar *name); +typedef void (* glStencilFuncSeparateProcPtr) (GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (* glStencilOpSeparateProcPtr) (GLenum face, GLenum fail, GLenum zfail, GLenum zpass); +typedef void (* glStencilMaskSeparateProcPtr) (GLenum face, GLuint mask); + +#else /* GL_GLEXT_FUNCTION_POINTERS */ + +extern void glAccum (GLenum op, GLfloat value); +extern void glAlphaFunc (GLenum func, GLclampf ref); +extern GLboolean glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences); +extern void glArrayElement (GLint i); +extern void glBegin (GLenum mode); +extern void glBindTexture (GLenum target, GLuint texture); +extern void glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); +extern void glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +extern void glBlendEquation (GLenum mode); +extern void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); +extern void glBlendFunc (GLenum sfactor, GLenum dfactor); +extern void glCallList (GLuint list); +extern void glCallLists (GLsizei n, GLenum type, const GLvoid *lists); +extern void glClear (GLbitfield mask); +extern void glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +extern void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +extern void glClearDepth (GLclampd depth); +extern void glClearIndex (GLfloat c); +extern void glClearStencil (GLint s); +extern void glClipPlane (GLenum plane, const GLdouble *equation); +extern void glColor3b (GLbyte red, GLbyte green, GLbyte blue); +extern void glColor3bv (const GLbyte *v); +extern void glColor3d (GLdouble red, GLdouble green, GLdouble blue); +extern void glColor3dv (const GLdouble *v); +extern void glColor3f (GLfloat red, GLfloat green, GLfloat blue); +extern void glColor3fv (const GLfloat *v); +extern void glColor3i (GLint red, GLint green, GLint blue); +extern void glColor3iv (const GLint *v); +extern void glColor3s (GLshort red, GLshort green, GLshort blue); +extern void glColor3sv (const GLshort *v); +extern void glColor3ub (GLubyte red, GLubyte green, GLubyte blue); +extern void glColor3ubv (const GLubyte *v); +extern void glColor3ui (GLuint red, GLuint green, GLuint blue); +extern void glColor3uiv (const GLuint *v); +extern void glColor3us (GLushort red, GLushort green, GLushort blue); +extern void glColor3usv (const GLushort *v); +extern void glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +extern void glColor4bv (const GLbyte *v); +extern void glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +extern void glColor4dv (const GLdouble *v); +extern void glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +extern void glColor4fv (const GLfloat *v); +extern void glColor4i (GLint red, GLint green, GLint blue, GLint alpha); +extern void glColor4iv (const GLint *v); +extern void glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha); +extern void glColor4sv (const GLshort *v); +extern void glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +extern void glColor4ubv (const GLubyte *v); +extern void glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha); +extern void glColor4uiv (const GLuint *v); +extern void glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha); +extern void glColor4usv (const GLushort *v); +extern void glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +extern void glColorMaterial (GLenum face, GLenum mode); +extern void glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +extern void glColorSubTable (GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data); +extern void glColorTable (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table); +extern void glColorTableParameterfv (GLenum target, GLenum pname, const GLfloat *params); +extern void glColorTableParameteriv (GLenum target, GLenum pname, const GLint *params); +extern void glConvolutionFilter1D (GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *image); +extern void glConvolutionFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *image); +extern void glConvolutionParameterf (GLenum target, GLenum pname, GLfloat params); +extern void glConvolutionParameterfv (GLenum target, GLenum pname, const GLfloat *params); +extern void glConvolutionParameteri (GLenum target, GLenum pname, GLint params); +extern void glConvolutionParameteriv (GLenum target, GLenum pname, const GLint *params); +extern void glCopyColorSubTable (GLenum target, GLsizei start, GLint x, GLint y, GLsizei width); +extern void glCopyColorTable (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +extern void glCopyConvolutionFilter1D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width); +extern void glCopyConvolutionFilter2D (GLenum target, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height); +extern void glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +extern void glCopyTexImage1D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +extern void glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +extern void glCopyTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +extern void glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +extern void glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +extern void glCullFace (GLenum mode); +extern void glDeleteLists (GLuint list, GLsizei range); +extern void glDeleteTextures (GLsizei n, const GLuint *textures); +extern void glDepthFunc (GLenum func); +extern void glDepthMask (GLboolean flag); +extern void glDepthRange (GLclampd zNear, GLclampd zFar); +extern void glDisable (GLenum cap); +extern void glDisableClientState (GLenum array); +extern void glDrawArrays (GLenum mode, GLint first, GLsizei count); +extern void glDrawBuffer (GLenum mode); +extern void glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +extern void glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +extern void glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); +extern void glEdgeFlag (GLboolean flag); +extern void glEdgeFlagPointer (GLsizei stride, const GLvoid *pointer); +extern void glEdgeFlagv (const GLboolean *flag); +extern void glEnable (GLenum cap); +extern void glEnableClientState (GLenum array); +extern void glEnd (void); +extern void glEndList (void); +extern void glEvalCoord1d (GLdouble u); +extern void glEvalCoord1dv (const GLdouble *u); +extern void glEvalCoord1f (GLfloat u); +extern void glEvalCoord1fv (const GLfloat *u); +extern void glEvalCoord2d (GLdouble u, GLdouble v); +extern void glEvalCoord2dv (const GLdouble *u); +extern void glEvalCoord2f (GLfloat u, GLfloat v); +extern void glEvalCoord2fv (const GLfloat *u); +extern void glEvalMesh1 (GLenum mode, GLint i1, GLint i2); +extern void glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +extern void glEvalPoint1 (GLint i); +extern void glEvalPoint2 (GLint i, GLint j); +extern void glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer); +extern void glFinish (void); +extern void glFlush (void); +extern void glFogf (GLenum pname, GLfloat param); +extern void glFogfv (GLenum pname, const GLfloat *params); +extern void glFogi (GLenum pname, GLint param); +extern void glFogiv (GLenum pname, const GLint *params); +extern void glFrontFace (GLenum mode); +extern void glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +extern GLuint glGenLists (GLsizei range); +extern void glGenTextures (GLsizei n, GLuint *textures); +extern void glGetBooleanv (GLenum pname, GLboolean *params); +extern void glGetClipPlane (GLenum plane, GLdouble *equation); +extern void glGetColorTable (GLenum target, GLenum format, GLenum type, GLvoid *table); +extern void glGetColorTableParameterfv (GLenum target, GLenum pname, GLfloat *params); +extern void glGetColorTableParameteriv (GLenum target, GLenum pname, GLint *params); +extern void glGetConvolutionFilter (GLenum target, GLenum format, GLenum type, GLvoid *image); +extern void glGetConvolutionParameterfv (GLenum target, GLenum pname, GLfloat *params); +extern void glGetConvolutionParameteriv (GLenum target, GLenum pname, GLint *params); +extern void glGetDoublev (GLenum pname, GLdouble *params); +extern GLenum glGetError (void); +extern void glGetFloatv (GLenum pname, GLfloat *params); +extern void glGetHistogram (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +extern void glGetHistogramParameterfv (GLenum target, GLenum pname, GLfloat *params); +extern void glGetHistogramParameteriv (GLenum target, GLenum pname, GLint *params); +extern void glGetIntegerv (GLenum pname, GLint *params); +extern void glGetLightfv (GLenum light, GLenum pname, GLfloat *params); +extern void glGetLightiv (GLenum light, GLenum pname, GLint *params); +extern void glGetMapdv (GLenum target, GLenum query, GLdouble *v); +extern void glGetMapfv (GLenum target, GLenum query, GLfloat *v); +extern void glGetMapiv (GLenum target, GLenum query, GLint *v); +extern void glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params); +extern void glGetMaterialiv (GLenum face, GLenum pname, GLint *params); +extern void glGetMinmax (GLenum target, GLboolean reset, GLenum format, GLenum type, GLvoid *values); +extern void glGetMinmaxParameterfv (GLenum target, GLenum pname, GLfloat *params); +extern void glGetMinmaxParameteriv (GLenum target, GLenum pname, GLint *params); +extern void glGetPixelMapfv (GLenum map, GLfloat *values); +extern void glGetPixelMapuiv (GLenum map, GLuint *values); +extern void glGetPixelMapusv (GLenum map, GLushort *values); +extern void glGetPointerv (GLenum pname, GLvoid* *params); +extern void glGetPolygonStipple (GLubyte *mask); +extern void glGetSeparableFilter (GLenum target, GLenum format, GLenum type, GLvoid *row, GLvoid *column, GLvoid *span); +extern const GLubyte * glGetString (GLenum name); +extern void glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params); +extern void glGetTexEnviv (GLenum target, GLenum pname, GLint *params); +extern void glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params); +extern void glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params); +extern void glGetTexGeniv (GLenum coord, GLenum pname, GLint *params); +extern void glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); +extern void glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); +extern void glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); +extern void glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +extern void glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +extern void glHint (GLenum target, GLenum mode); +extern void glHistogram (GLenum target, GLsizei width, GLenum internalformat, GLboolean sink); +extern void glIndexMask (GLuint mask); +extern void glIndexPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +extern void glIndexd (GLdouble c); +extern void glIndexdv (const GLdouble *c); +extern void glIndexf (GLfloat c); +extern void glIndexfv (const GLfloat *c); +extern void glIndexi (GLint c); +extern void glIndexiv (const GLint *c); +extern void glIndexs (GLshort c); +extern void glIndexsv (const GLshort *c); +extern void glIndexub (GLubyte c); +extern void glIndexubv (const GLubyte *c); +extern void glInitNames (void); +extern void glInterleavedArrays (GLenum format, GLsizei stride, const GLvoid *pointer); +extern GLboolean glIsEnabled (GLenum cap); +extern GLboolean glIsList (GLuint list); +extern GLboolean glIsTexture (GLuint texture); +extern void glLightModelf (GLenum pname, GLfloat param); +extern void glLightModelfv (GLenum pname, const GLfloat *params); +extern void glLightModeli (GLenum pname, GLint param); +extern void glLightModeliv (GLenum pname, const GLint *params); +extern void glLightf (GLenum light, GLenum pname, GLfloat param); +extern void glLightfv (GLenum light, GLenum pname, const GLfloat *params); +extern void glLighti (GLenum light, GLenum pname, GLint param); +extern void glLightiv (GLenum light, GLenum pname, const GLint *params); +extern void glLineStipple (GLint factor, GLushort pattern); +extern void glLineWidth (GLfloat width); +extern void glListBase (GLuint base); +extern void glLoadIdentity (void); +extern void glLoadMatrixd (const GLdouble *m); +extern void glLoadMatrixf (const GLfloat *m); +extern void glLoadName (GLuint name); +extern void glLogicOp (GLenum opcode); +extern void glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); +extern void glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); +extern void glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); +extern void glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); +extern void glMapGrid1d (GLint un, GLdouble u1, GLdouble u2); +extern void glMapGrid1f (GLint un, GLfloat u1, GLfloat u2); +extern void glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +extern void glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +extern void glMaterialf (GLenum face, GLenum pname, GLfloat param); +extern void glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); +extern void glMateriali (GLenum face, GLenum pname, GLint param); +extern void glMaterialiv (GLenum face, GLenum pname, const GLint *params); +extern void glMatrixMode (GLenum mode); +extern void glMinmax (GLenum target, GLenum internalformat, GLboolean sink); +extern void glMultMatrixd (const GLdouble *m); +extern void glMultMatrixf (const GLfloat *m); +extern void glNewList (GLuint list, GLenum mode); +extern void glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz); +extern void glNormal3bv (const GLbyte *v); +extern void glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz); +extern void glNormal3dv (const GLdouble *v); +extern void glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); +extern void glNormal3fv (const GLfloat *v); +extern void glNormal3i (GLint nx, GLint ny, GLint nz); +extern void glNormal3iv (const GLint *v); +extern void glNormal3s (GLshort nx, GLshort ny, GLshort nz); +extern void glNormal3sv (const GLshort *v); +extern void glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +extern void glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +extern void glPassThrough (GLfloat token); +extern void glPixelMapfv (GLenum map, GLint mapsize, const GLfloat *values); +extern void glPixelMapuiv (GLenum map, GLint mapsize, const GLuint *values); +extern void glPixelMapusv (GLenum map, GLint mapsize, const GLushort *values); +extern void glPixelStoref (GLenum pname, GLfloat param); +extern void glPixelStorei (GLenum pname, GLint param); +extern void glPixelTransferf (GLenum pname, GLfloat param); +extern void glPixelTransferi (GLenum pname, GLint param); +extern void glPixelZoom (GLfloat xfactor, GLfloat yfactor); +extern void glPointSize (GLfloat size); +extern void glPolygonMode (GLenum face, GLenum mode); +extern void glPolygonOffset (GLfloat factor, GLfloat units); +extern void glPolygonStipple (const GLubyte *mask); +extern void glPopAttrib (void); +extern void glPopClientAttrib (void); +extern void glPopMatrix (void); +extern void glPopName (void); +extern void glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities); +extern void glPushAttrib (GLbitfield mask); +extern void glPushClientAttrib (GLbitfield mask); +extern void glPushMatrix (void); +extern void glPushName (GLuint name); +extern void glRasterPos2d (GLdouble x, GLdouble y); +extern void glRasterPos2dv (const GLdouble *v); +extern void glRasterPos2f (GLfloat x, GLfloat y); +extern void glRasterPos2fv (const GLfloat *v); +extern void glRasterPos2i (GLint x, GLint y); +extern void glRasterPos2iv (const GLint *v); +extern void glRasterPos2s (GLshort x, GLshort y); +extern void glRasterPos2sv (const GLshort *v); +extern void glRasterPos3d (GLdouble x, GLdouble y, GLdouble z); +extern void glRasterPos3dv (const GLdouble *v); +extern void glRasterPos3f (GLfloat x, GLfloat y, GLfloat z); +extern void glRasterPos3fv (const GLfloat *v); +extern void glRasterPos3i (GLint x, GLint y, GLint z); +extern void glRasterPos3iv (const GLint *v); +extern void glRasterPos3s (GLshort x, GLshort y, GLshort z); +extern void glRasterPos3sv (const GLshort *v); +extern void glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +extern void glRasterPos4dv (const GLdouble *v); +extern void glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +extern void glRasterPos4fv (const GLfloat *v); +extern void glRasterPos4i (GLint x, GLint y, GLint z, GLint w); +extern void glRasterPos4iv (const GLint *v); +extern void glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w); +extern void glRasterPos4sv (const GLshort *v); +extern void glReadBuffer (GLenum mode); +extern void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +extern void glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +extern void glRectdv (const GLdouble *v1, const GLdouble *v2); +extern void glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +extern void glRectfv (const GLfloat *v1, const GLfloat *v2); +extern void glRecti (GLint x1, GLint y1, GLint x2, GLint y2); +extern void glRectiv (const GLint *v1, const GLint *v2); +extern void glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2); +extern void glRectsv (const GLshort *v1, const GLshort *v2); +extern GLint glRenderMode (GLenum mode); +extern void glResetHistogram (GLenum target); +extern void glResetMinmax (GLenum target); +extern void glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +extern void glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +extern void glScaled (GLdouble x, GLdouble y, GLdouble z); +extern void glScalef (GLfloat x, GLfloat y, GLfloat z); +extern void glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +extern void glSelectBuffer (GLsizei size, GLuint *buffer); +extern void glSeparableFilter2D (GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *row, const GLvoid *column); +extern void glShadeModel (GLenum mode); +extern void glStencilFunc (GLenum func, GLint ref, GLuint mask); +extern void glStencilMask (GLuint mask); +extern void glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +extern void glTexCoord1d (GLdouble s); +extern void glTexCoord1dv (const GLdouble *v); +extern void glTexCoord1f (GLfloat s); +extern void glTexCoord1fv (const GLfloat *v); +extern void glTexCoord1i (GLint s); +extern void glTexCoord1iv (const GLint *v); +extern void glTexCoord1s (GLshort s); +extern void glTexCoord1sv (const GLshort *v); +extern void glTexCoord2d (GLdouble s, GLdouble t); +extern void glTexCoord2dv (const GLdouble *v); +extern void glTexCoord2f (GLfloat s, GLfloat t); +extern void glTexCoord2fv (const GLfloat *v); +extern void glTexCoord2i (GLint s, GLint t); +extern void glTexCoord2iv (const GLint *v); +extern void glTexCoord2s (GLshort s, GLshort t); +extern void glTexCoord2sv (const GLshort *v); +extern void glTexCoord3d (GLdouble s, GLdouble t, GLdouble r); +extern void glTexCoord3dv (const GLdouble *v); +extern void glTexCoord3f (GLfloat s, GLfloat t, GLfloat r); +extern void glTexCoord3fv (const GLfloat *v); +extern void glTexCoord3i (GLint s, GLint t, GLint r); +extern void glTexCoord3iv (const GLint *v); +extern void glTexCoord3s (GLshort s, GLshort t, GLshort r); +extern void glTexCoord3sv (const GLshort *v); +extern void glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q); +extern void glTexCoord4dv (const GLdouble *v); +extern void glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q); +extern void glTexCoord4fv (const GLfloat *v); +extern void glTexCoord4i (GLint s, GLint t, GLint r, GLint q); +extern void glTexCoord4iv (const GLint *v); +extern void glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q); +extern void glTexCoord4sv (const GLshort *v); +extern void glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +extern void glTexEnvf (GLenum target, GLenum pname, GLfloat param); +extern void glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); +extern void glTexEnvi (GLenum target, GLenum pname, GLint param); +extern void glTexEnviv (GLenum target, GLenum pname, const GLint *params); +extern void glTexGend (GLenum coord, GLenum pname, GLdouble param); +extern void glTexGendv (GLenum coord, GLenum pname, const GLdouble *params); +extern void glTexGenf (GLenum coord, GLenum pname, GLfloat param); +extern void glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params); +extern void glTexGeni (GLenum coord, GLenum pname, GLint param); +extern void glTexGeniv (GLenum coord, GLenum pname, const GLint *params); +extern void glTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +extern void glTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +extern void glTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +extern void glTexParameterf (GLenum target, GLenum pname, GLfloat param); +extern void glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +extern void glTexParameteri (GLenum target, GLenum pname, GLint param); +extern void glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +extern void glTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); +extern void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +extern void glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels); +extern void glTranslated (GLdouble x, GLdouble y, GLdouble z); +extern void glTranslatef (GLfloat x, GLfloat y, GLfloat z); +extern void glVertex2d (GLdouble x, GLdouble y); +extern void glVertex2dv (const GLdouble *v); +extern void glVertex2f (GLfloat x, GLfloat y); +extern void glVertex2fv (const GLfloat *v); +extern void glVertex2i (GLint x, GLint y); +extern void glVertex2iv (const GLint *v); +extern void glVertex2s (GLshort x, GLshort y); +extern void glVertex2sv (const GLshort *v); +extern void glVertex3d (GLdouble x, GLdouble y, GLdouble z); +extern void glVertex3dv (const GLdouble *v); +extern void glVertex3f (GLfloat x, GLfloat y, GLfloat z); +extern void glVertex3fv (const GLfloat *v); +extern void glVertex3i (GLint x, GLint y, GLint z); +extern void glVertex3iv (const GLint *v); +extern void glVertex3s (GLshort x, GLshort y, GLshort z); +extern void glVertex3sv (const GLshort *v); +extern void glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w); +extern void glVertex4dv (const GLdouble *v); +extern void glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w); +extern void glVertex4fv (const GLfloat *v); +extern void glVertex4i (GLint x, GLint y, GLint z, GLint w); +extern void glVertex4iv (const GLint *v); +extern void glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w); +extern void glVertex4sv (const GLshort *v); +extern void glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +extern void glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +extern void glSampleCoverage (GLclampf value, GLboolean invert); +extern void glSamplePass (GLenum pass); + +extern void glLoadTransposeMatrixf (const GLfloat *m); +extern void glLoadTransposeMatrixd (const GLdouble *m); +extern void glMultTransposeMatrixf (const GLfloat *m); +extern void glMultTransposeMatrixd (const GLdouble *m); + +extern void glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data); +extern void glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +extern void glCompressedTexImage1D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data); +extern void glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data); +extern void glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +extern void glCompressedTexSubImage1D (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data); +extern void glGetCompressedTexImage (GLenum target, GLint lod, GLvoid *img); + +extern void glActiveTexture (GLenum texture); +extern void glClientActiveTexture (GLenum texture); +extern void glMultiTexCoord1d (GLenum target, GLdouble s); +extern void glMultiTexCoord1dv (GLenum target, const GLdouble *v); +extern void glMultiTexCoord1f (GLenum target, GLfloat s); +extern void glMultiTexCoord1fv (GLenum target, const GLfloat *v); +extern void glMultiTexCoord1i (GLenum target, GLint s); +extern void glMultiTexCoord1iv (GLenum target, const GLint *v); +extern void glMultiTexCoord1s (GLenum target, GLshort s); +extern void glMultiTexCoord1sv (GLenum target, const GLshort *v); +extern void glMultiTexCoord2d (GLenum target, GLdouble s, GLdouble t); +extern void glMultiTexCoord2dv (GLenum target, const GLdouble *v); +extern void glMultiTexCoord2f (GLenum target, GLfloat s, GLfloat t); +extern void glMultiTexCoord2fv (GLenum target, const GLfloat *v); +extern void glMultiTexCoord2i (GLenum target, GLint s, GLint t); +extern void glMultiTexCoord2iv (GLenum target, const GLint *v); +extern void glMultiTexCoord2s (GLenum target, GLshort s, GLshort t); +extern void glMultiTexCoord2sv (GLenum target, const GLshort *v); +extern void glMultiTexCoord3d (GLenum target, GLdouble s, GLdouble t, GLdouble r); +extern void glMultiTexCoord3dv (GLenum target, const GLdouble *v); +extern void glMultiTexCoord3f (GLenum target, GLfloat s, GLfloat t, GLfloat r); +extern void glMultiTexCoord3fv (GLenum target, const GLfloat *v); +extern void glMultiTexCoord3i (GLenum target, GLint s, GLint t, GLint r); +extern void glMultiTexCoord3iv (GLenum target, const GLint *v); +extern void glMultiTexCoord3s (GLenum target, GLshort s, GLshort t, GLshort r); +extern void glMultiTexCoord3sv (GLenum target, const GLshort *v); +extern void glMultiTexCoord4d (GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +extern void glMultiTexCoord4dv (GLenum target, const GLdouble *v); +extern void glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +extern void glMultiTexCoord4fv (GLenum target, const GLfloat *v); +extern void glMultiTexCoord4i (GLenum target, GLint, GLint s, GLint t, GLint r); +extern void glMultiTexCoord4iv (GLenum target, const GLint *v); +extern void glMultiTexCoord4s (GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +extern void glMultiTexCoord4sv (GLenum target, const GLshort *v); + +extern void glFogCoordf (GLfloat coord); +extern void glFogCoordfv (const GLfloat *coord); +extern void glFogCoordd (GLdouble coord); +extern void glFogCoorddv (const GLdouble * coord); +extern void glFogCoordPointer (GLenum type, GLsizei stride, const GLvoid *pointer); + +extern void glSecondaryColor3b (GLbyte red, GLbyte green, GLbyte blue); +extern void glSecondaryColor3bv (const GLbyte *v); +extern void glSecondaryColor3d (GLdouble red, GLdouble green, GLdouble blue); +extern void glSecondaryColor3dv (const GLdouble *v); +extern void glSecondaryColor3f (GLfloat red, GLfloat green, GLfloat blue); +extern void glSecondaryColor3fv (const GLfloat *v); +extern void glSecondaryColor3i (GLint red, GLint green, GLint blue); +extern void glSecondaryColor3iv (const GLint *v); +extern void glSecondaryColor3s (GLshort red, GLshort green, GLshort blue); +extern void glSecondaryColor3sv (const GLshort *v); +extern void glSecondaryColor3ub (GLubyte red, GLubyte green, GLubyte blue); +extern void glSecondaryColor3ubv (const GLubyte *v); +extern void glSecondaryColor3ui (GLuint red, GLuint green, GLuint blue); +extern void glSecondaryColor3uiv (const GLuint *v); +extern void glSecondaryColor3us (GLushort red, GLushort green, GLushort blue); +extern void glSecondaryColor3usv (const GLushort *v); +extern void glSecondaryColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + +extern void glPointParameterf (GLenum pname, GLfloat param); +extern void glPointParameterfv (GLenum pname, const GLfloat *params); +extern void glPointParameteri (GLenum pname, GLint param); +extern void glPointParameteriv (GLenum pname, const GLint *params); + +extern void glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + +extern void glMultiDrawArrays (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +extern void glMultiDrawElements (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); + +extern void glWindowPos2d (GLdouble x, GLdouble y); +extern void glWindowPos2dv (const GLdouble *v); +extern void glWindowPos2f (GLfloat x, GLfloat y); +extern void glWindowPos2fv (const GLfloat *v); +extern void glWindowPos2i (GLint x, GLint y); +extern void glWindowPos2iv (const GLint *v); +extern void glWindowPos2s (GLshort x, GLshort y); +extern void glWindowPos2sv (const GLshort *v); +extern void glWindowPos3d (GLdouble x, GLdouble y, GLdouble z); +extern void glWindowPos3dv (const GLdouble *v); +extern void glWindowPos3f (GLfloat x, GLfloat y, GLfloat z); +extern void glWindowPos3fv (const GLfloat *v); +extern void glWindowPos3i (GLint x, GLint y, GLint z); +extern void glWindowPos3iv (const GLint *v); +extern void glWindowPos3s (GLshort x, GLshort y, GLshort z); +extern void glWindowPos3sv (const GLshort *v); + +extern void glGenQueries(GLsizei n, GLuint *ids); +extern void glDeleteQueries(GLsizei n, const GLuint *ids); +extern GLboolean glIsQuery(GLuint id); +extern void glBeginQuery(GLenum target, GLuint id); +extern void glEndQuery(GLenum target); +extern void glGetQueryiv(GLenum target, GLenum pname, GLint *params); +extern void glGetQueryObjectiv(GLuint id, GLenum pname, GLint *params); +extern void glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params); + +extern void glBindBuffer (GLenum target, GLuint buffer); +extern void glDeleteBuffers (GLsizei n, const GLuint *buffers); +extern void glGenBuffers (GLsizei n, GLuint *buffers); +extern GLboolean glIsBuffer (GLuint buffer); +extern void glBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); +extern void glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); +extern void glGetBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data); +extern GLvoid * glMapBuffer (GLenum target, GLenum access); +extern GLboolean glUnmapBuffer (GLenum target); +extern void glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); +extern void glGetBufferPointerv (GLenum target, GLenum pname, GLvoid **params); + +extern void glDrawBuffers (GLsizei n, const GLenum *bufs); +extern void glVertexAttrib1d (GLuint index, GLdouble x); +extern void glVertexAttrib1dv (GLuint index, const GLdouble *v); +extern void glVertexAttrib1f (GLuint index, GLfloat x); +extern void glVertexAttrib1fv (GLuint index, const GLfloat *v); +extern void glVertexAttrib1s (GLuint index, GLshort x); +extern void glVertexAttrib1sv (GLuint index, const GLshort *v); +extern void glVertexAttrib2d (GLuint index, GLdouble x, GLdouble y); +extern void glVertexAttrib2dv (GLuint index, const GLdouble *v); +extern void glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); +extern void glVertexAttrib2fv (GLuint index, const GLfloat *v); +extern void glVertexAttrib2s (GLuint index, GLshort x, GLshort y); +extern void glVertexAttrib2sv (GLuint index, const GLshort *v); +extern void glVertexAttrib3d (GLuint index, GLdouble x, GLdouble y, GLdouble z); +extern void glVertexAttrib3dv (GLuint index, const GLdouble *v); +extern void glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); +extern void glVertexAttrib3fv (GLuint index, const GLfloat *v); +extern void glVertexAttrib3s (GLuint index, GLshort x, GLshort y, GLshort z); +extern void glVertexAttrib3sv (GLuint index, const GLshort *v); +extern void glVertexAttrib4Nbv (GLuint index, const GLbyte *v); +extern void glVertexAttrib4Niv (GLuint index, const GLint *v); +extern void glVertexAttrib4Nsv (GLuint index, const GLshort *v); +extern void glVertexAttrib4Nub (GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +extern void glVertexAttrib4Nubv (GLuint index, const GLubyte *v); +extern void glVertexAttrib4Nuiv (GLuint index, const GLuint *v); +extern void glVertexAttrib4Nusv (GLuint index, const GLushort *v); +extern void glVertexAttrib4bv (GLuint index, const GLbyte *v); +extern void glVertexAttrib4d (GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +extern void glVertexAttrib4dv (GLuint index, const GLdouble *v); +extern void glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +extern void glVertexAttrib4fv (GLuint index, const GLfloat *v); +extern void glVertexAttrib4iv (GLuint index, const GLint *v); +extern void glVertexAttrib4s (GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +extern void glVertexAttrib4sv (GLuint index, const GLshort *v); +extern void glVertexAttrib4ubv (GLuint index, const GLubyte *v); +extern void glVertexAttrib4uiv (GLuint index, const GLuint *v); +extern void glVertexAttrib4usv (GLuint index, const GLushort *v); +extern void glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); +extern void glEnableVertexAttribArray (GLuint index); +extern void glDisableVertexAttribArray (GLuint index); +extern void glGetVertexAttribdv (GLuint index, GLenum pname, GLdouble *params); +extern void glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); +extern void glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); +extern void glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid* *pointer); +extern void glDeleteShader (GLuint shader); +extern void glDetachShader (GLuint program, GLuint shader); +extern GLuint glCreateShader (GLenum type); +extern void glShaderSource (GLuint shader, GLsizei count, const GLchar* *string, const GLint *length); +extern void glCompileShader (GLuint shader); +extern GLuint glCreateProgram (void); +extern void glAttachShader (GLuint program, GLuint shader); +extern void glLinkProgram (GLuint program); +extern void glUseProgram (GLuint program); +extern void glDeleteProgram (GLuint program); +extern void glValidateProgram (GLuint program); +extern void glUniform1f (GLint location, GLfloat v0); +extern void glUniform2f (GLint location, GLfloat v0, GLfloat v1); +extern void glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +extern void glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +extern void glUniform1i (GLint location, GLint v0); +extern void glUniform2i (GLint location, GLint v0, GLint v1); +extern void glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); +extern void glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +extern void glUniform1fv (GLint location, GLsizei count, const GLfloat *value); +extern void glUniform2fv (GLint location, GLsizei count, const GLfloat *value); +extern void glUniform3fv (GLint location, GLsizei count, const GLfloat *value); +extern void glUniform4fv (GLint location, GLsizei count, const GLfloat *value); +extern void glUniform1iv (GLint location, GLsizei count, const GLint *value); +extern void glUniform2iv (GLint location, GLsizei count, const GLint *value); +extern void glUniform3iv (GLint location, GLsizei count, const GLint *value); +extern void glUniform4iv (GLint location, GLsizei count, const GLint *value); +extern void glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +extern void glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +extern void glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +extern GLboolean glIsShader (GLuint shader); +extern GLboolean glIsProgram (GLuint program); +extern void glGetShaderiv (GLuint shader, GLenum pname, GLint *params); +extern void glGetProgramiv (GLuint program, GLenum pname, GLint *params); +extern void glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +extern void glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +extern void glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +extern GLint glGetUniformLocation (GLuint program, const GLchar *name); +extern void glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +extern void glGetUniformfv (GLuint program, GLint location, GLfloat *params); +extern void glGetUniformiv (GLuint program, GLint location, GLint *params); +extern void glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +extern void glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); +extern void glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +extern GLint glGetAttribLocation (GLuint program, const GLchar *name); +extern void glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +extern void glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass); +extern void glStencilMaskSeparate (GLenum face, GLuint mask); + + +#endif /* GL_GLEXT_FUNCTION_POINTERS */ + +#ifdef __cplusplus +} +#endif + +#endif /* __gl_h_ */ diff --git a/archive/hge/graphics.cpp b/archive/hge/graphics.cpp new file mode 100644 index 0000000..6ee9578 --- /dev/null +++ b/archive/hge/graphics.cpp @@ -0,0 +1,1524 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: graphics +*/ + +// !!! FIXME: the texture data when locking/unlocking textures is in GL_BGRA format, not GL_RGBA. +// !!! FIXME: ...but this mistake wasn't noticed for several games, since most didn't lock outside +// !!! FIXME: of a piece of code that was #ifdef'd for Unix anyhow. +// !!! FIXME: But if you lock textures and the colors are wrong, that's what happened. We need to +// !!! FIXME: sort out all the places where we're passing things around in RGBA to fix this. +// !!! FIXME: In the mean time, it's usually easier to just change your application to expect +// !!! FIXME: locked textures to be RGBA instead of BGRA. + +// !!! FIXME: ...apparently we're locking textures upside down, too? + +#include "hge_impl.h" + +#define SUPPORT_CXIMAGE 1 +#if SUPPORT_CXIMAGE +// conflict with Mac OS X 10.3.9 SDK... +#ifdef _T +#undef _T +#endif +#include "CxImage/ximage.h" +#else +/* Use DevIL instead of CXImage */ +#include <IL/il.h> +#include <IL/ilu.h> +#endif + +// avoiding glext.h here ... +#ifndef GL_TEXTURE_RECTANGLE_ARB +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#endif +#ifndef GL_FRAMEBUFFER_EXT +#define GL_FRAMEBUFFER_EXT 0x8D40 +#endif +#ifndef GL_RENDERBUFFER_EXT +#define GL_RENDERBUFFER_EXT 0x8D41 +#endif +#ifndef GL_COLOR_ATTACHMENT0_EXT +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#endif +#ifndef GL_DEPTH_ATTACHMENT_EXT +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#endif +#ifndef GL_FRAMEBUFFER_COMPLETE_EXT +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#endif +#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#endif +#ifndef GL_YCBCR_422_APPLE +#define GL_YCBCR_422_APPLE 0x85B9 +#endif +#ifndef GL_UNSIGNED_SHORT_8_8_APPLE +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#endif +#ifndef GL_UNSIGNED_SHORT_8_8_REV_APPLE +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#endif +static const char* GRAPHICS_SRC_FN="hge/graphics.cpp"; +struct gltexture +{ + GLuint name; + GLuint width; + GLuint height; + GLuint potw; // Power-of-two width. + GLuint poth; // Power-of-two height. + const char *filename; // if backed by a file, not a managed buffer. + DWORD *pixels; // original rgba data. + DWORD *lock_pixels; // for locked texture + bool is_render_target; + bool lost; + bool lock_readonly; + GLint lock_x; + GLint lock_y; + GLint lock_width; + GLint lock_height; +}; + +static DWORD *_DecodeImage(BYTE *data, const char *fname, DWORD size, int &width, int &height) +{ + width = height = 0; + + DWORD *pixels = NULL; + const size_t fnamelen = fname ? strlen(fname) : 0; + if ( (fnamelen > 5) && (strcasecmp((fname + fnamelen) - 5, ".rgba") == 0) ) + { + DWORD *ptr = (DWORD *) data; + DWORD w = ptr[0]; + DWORD h = ptr[1]; + BYTESWAP(w); + BYTESWAP(h); + if ( ((w * h * 4) + 8) == size ) // not truncated? + { + width = (int) w; + height = (int) h; + pixels = new DWORD[width * height]; + memcpy(pixels, ptr + 2, w * h * 4); // !!! FIXME: ignores pitch. + } + return pixels; + } + +#if SUPPORT_CXIMAGE + CxImage img; + img.Decode(data, size, CXIMAGE_FORMAT_UNKNOWN); + if (img.IsValid()) + { + width = img.GetWidth(); + height = img.GetHeight(); + pixels = new DWORD[width * height]; + BYTE *wptr = (BYTE *) pixels; + const bool hasalpha = img.AlphaIsValid(); + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + const RGBQUAD rgb = img.GetPixelColor(x, y, true); + *(wptr++) = rgb.rgbRed; + *(wptr++) = rgb.rgbGreen; + *(wptr++) = rgb.rgbBlue; + *(wptr++) = hasalpha ? rgb.rgbReserved : 0xFF; // alpha. + } + } + } +#else + ilInit(); + iluInit(); + + ILuint id; + ilGenImages(1, &id); + + if(ilLoadImage(fname)) { + printf("success: %s\n", fname); + ILinfo info; + iluGetImageInfo(&info); + width = info.Width; + height = info.Height; + size = info.SizeOfData; + pixels = new DWORD[width * height]; + ilCopyPixels(0, 0, 0, width, height, 0, IL_RGBA, IL_UNSIGNED_INT, pixels); + ilShutDown(); + } +#endif + + return pixels; +} + + +void HGE_Impl::_BindTexture(gltexture *t) +{ + // The Direct3D renderer is using managed textures, so they aren't every + // actually "lost" ... we may have to rebuild them here, though. + if ((t != NULL) && (t->lost)) + _ConfigureTexture(t, t->width, t->height, t->pixels); + + if ( ((HTEXTURE)t) != CurTexture ) + { + pOpenGLDevice->glBindTexture(pOpenGLDevice->TextureTarget, t ? t->name : 0); + CurTexture = (HTEXTURE) t; + } +} + +void CALL HGE_Impl::Gfx_Clear(DWORD color) +{ + GLbitfield flags = GL_COLOR_BUFFER_BIT; + if ( ((pCurTarget) && (pCurTarget->depth)) || bZBuffer ) + flags |= GL_DEPTH_BUFFER_BIT; + + const GLfloat a = ((GLfloat) ((color >> 24) & 0xFF)) / 255.0f; + const GLfloat r = ((GLfloat) ((color >> 16) & 0xFF)) / 255.0f; + const GLfloat g = ((GLfloat) ((color >> 8) & 0xFF)) / 255.0f; + const GLfloat b = ((GLfloat) ((color >> 0) & 0xFF)) / 255.0f; + pOpenGLDevice->glClearColor(r, g, b, a); + pOpenGLDevice->glClear(flags); +} + +void CALL HGE_Impl::Gfx_SetClipping(int x, int y, int w, int h) +{ + int scr_width, scr_height; + struct { int X; int Y; int Width; int Height; float MinZ; float MaxZ; } vp; + + if(!pCurTarget) { + scr_width=pHGE->System_GetStateInt(HGE_SCREENWIDTH); + scr_height=pHGE->System_GetStateInt(HGE_SCREENHEIGHT); + } + else { + scr_width=Texture_GetWidth(pCurTarget->tex); + scr_height=Texture_GetHeight(pCurTarget->tex); + } + + if(!w) { + vp.X=0; + vp.Y=0; + vp.Width=scr_width; + vp.Height=scr_height; + } + else + { + if(x<0) { w+=x; x=0; } + if(y<0) { h+=y; y=0; } + + if(x+w > scr_width) w=scr_width-x; + if(y+h > scr_height) h=scr_height-y; + + vp.X=x; + vp.Y=y; + vp.Width=w; + vp.Height=h; + } + + if ((clipX == vp.X) && (clipY == vp.Y) && (clipW == vp.Width) && (clipH == vp.Height)) + return; // nothing to do here, don't call into the GL. + + vp.MinZ=0.0f; + vp.MaxZ=1.0f; + + _render_batch(); + + clipX = vp.X; + clipY = vp.Y; + clipW = vp.Width; + clipH = vp.Height; + pOpenGLDevice->glScissor(vp.X, (scr_height-vp.Y)-vp.Height, vp.Width, vp.Height); +} + +void CALL HGE_Impl::Gfx_SetTransform(float x, float y, float dx, float dy, float rot, float hscale, float vscale) +{ + if ((x == 0.0f) && (y == 0.0f) && (dx == 0.0f) && (dy == 0.0f) && (rot == 0.0f) && (hscale == 0.0f) && (vscale == 0.0f)) + { + //reset everything + pOpenGLDevice->glMatrixMode(GL_MODELVIEW); + pOpenGLDevice->glLoadIdentity(); + bTransforming=false; + return; + } + + _render_batch(); + bTransforming = true; + + pOpenGLDevice->glMatrixMode(GL_MODELVIEW); + //we have to reset the matrix in all cases. + //or this would cause insane transforming... + pOpenGLDevice->glLoadIdentity(); + pOpenGLDevice->glTranslatef(-x, -y, 0.0f); + pOpenGLDevice->glScalef(hscale, vscale, 1.0f); + pOpenGLDevice->glRotatef(rot, 0.0f, 0.0f, 1.0f); + pOpenGLDevice->glTranslatef(x+dx, y+dy, 0.0f); +} + +bool CALL HGE_Impl::Gfx_BeginScene(HTARGET targ) +{ + CRenderTargetList *target=(CRenderTargetList *)targ; + + if(VertArray) + { + _PostError("Gfx_BeginScene: Scene is already being rendered"); + return false; + } + + if(target != pCurTarget) + { + if (pOpenGLDevice->have_GL_EXT_framebuffer_object) + pOpenGLDevice->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (target) ? target->frame : 0); + + if ( ((target) && (target->depth)) || (bZBuffer) ) + pOpenGLDevice->glEnable(GL_DEPTH_TEST); + else + pOpenGLDevice->glDisable(GL_DEPTH_TEST); + + // d3d's SetRenderTarget() forces the viewport to surface size... + if (target) + { + pOpenGLDevice->glScissor(0, 0, target->width, target->height); + pOpenGLDevice->glViewport(0, 0, target->width, target->height); + _SetProjectionMatrix(target->width, target->height); + } + else + { + pOpenGLDevice->glScissor(0, 0, nScreenWidth, nScreenHeight); + pOpenGLDevice->glViewport(0, 0, nScreenWidth, nScreenHeight); + _SetProjectionMatrix(nScreenWidth, nScreenHeight); + } + + pOpenGLDevice->glMatrixMode(GL_MODELVIEW); + pOpenGLDevice->glLoadIdentity(); + + pCurTarget=target; + } + + VertArray = pVB; + return true; +} + +void CALL HGE_Impl::Gfx_EndScene() +{ + _render_batch(true); + + // no "real" render targets? Push the framebuffer to a texture. + // This is not going to work in lots of legitimate scenarios, but it will + // most of the time, so it's better than nothing when you lack FBOs. + if ((pCurTarget) && (!pOpenGLDevice->have_GL_EXT_framebuffer_object)) + { + gltexture *pTex = (gltexture *) pCurTarget->tex; + if ((pTex != NULL) && (pTex->lost)) + _ConfigureTexture(pTex, pTex->width, pTex->height, pTex->pixels); + + const int width = pCurTarget->width; + const int height = pCurTarget->height; + pOpenGLDevice->glFinish(); + DWORD *pixels = new DWORD[width * height]; + pOpenGLDevice->glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + pOpenGLDevice->glBindTexture(pOpenGLDevice->TextureTarget, pTex->name); + pOpenGLDevice->glTexSubImage2D(pOpenGLDevice->TextureTarget, 0, 0, 0, width, height, + GL_RGBA, GL_UNSIGNED_BYTE, pixels); + pOpenGLDevice->glBindTexture(pOpenGLDevice->TextureTarget, CurTexture ? (((gltexture *) CurTexture)->name) : 0); + delete[] pixels; + } + + if(!pCurTarget) SDL_GL_SwapBuffers(); + //const GLenum err = pOpenGLDevice->glGetError(); + //if (err != GL_NO_ERROR) printf("GL error! 0x%X\n", (int) err); + //Gfx_Clear(0xFF | (0xFF<<24) | (random() & 0xFF << 16) | (random() & 0xFF << 8)); + //Gfx_Clear(0xFF000000); +} + +void HGE_Impl::_SetTextureFilter() +{ + const GLenum filter = (bTextureFilter) ? GL_LINEAR : GL_NEAREST; + pOpenGLDevice->glTexParameteri(pOpenGLDevice->TextureTarget, GL_TEXTURE_MIN_FILTER, filter); + pOpenGLDevice->glTexParameteri(pOpenGLDevice->TextureTarget, GL_TEXTURE_MAG_FILTER, filter); +} + + +bool HGE_Impl::_PrimsOutsideClipping(const hgeVertex *v, const int verts) +{ + if (bTransforming) + return false; // screw it, let the GL do the clipping. + + const int maxX = clipX + clipW; + const int maxY = clipY + clipH; + for (int i = 0; i < verts; i++, v++) + { + const int x = v->x; + const int y = v->y; + if ((x > clipX) && (x < maxX) && (y > clipY) && (y < maxY)) + return false; + } + return true; +} + + +void CALL HGE_Impl::Gfx_RenderLine(float x1, float y1, float x2, float y2, DWORD color, float z) +{ + if (VertArray) + { + if(CurPrimType!=HGEPRIM_LINES || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_LINES || CurTexture || CurBlendMode!=BLEND_DEFAULT) + { + _render_batch(); + + CurPrimType=HGEPRIM_LINES; + if(CurBlendMode != BLEND_DEFAULT) _SetBlendMode(BLEND_DEFAULT); + _BindTexture(NULL); + } + + int i=nPrim*HGEPRIM_LINES; + VertArray[i].x = x1; VertArray[i+1].x = x2; + VertArray[i].y = y1; VertArray[i+1].y = y2; + VertArray[i].z = VertArray[i+1].z = z; + VertArray[i].col = VertArray[i+1].col = color; + VertArray[i].tx = VertArray[i+1].tx = + VertArray[i].ty = VertArray[i+1].ty = 0.0f; + + if (!_PrimsOutsideClipping(&VertArray[i], HGEPRIM_LINES)) + nPrim++; + } +} + +template <class T> static inline const T Min(const T a, const T b) { return a < b ? a : b; } +template <class T> static inline const T Max(const T a, const T b) { return a > b ? a : b; } + +void CALL HGE_Impl::Gfx_RenderTriple(const hgeTriple *triple) +{ + if (VertArray) + { + const hgeVertex *v = triple->v; + if (_PrimsOutsideClipping(v, HGEPRIM_TRIPLES)) + { + // check for overlap, despite triangle points being outside clipping... + const int maxX = clipX + clipW; + const int maxY = clipY + clipH; + const int leftmost = Min(Min(v[0].x, v[1].x), v[2].x); + const int rightmost = Max(Max(v[0].x, v[1].x), v[2].x); + const int topmost = Min(Min(v[0].y, v[1].y), v[2].y); + const int bottommost = Max(Max(v[0].y, v[1].y), v[2].y); + if ( ((clipX < leftmost) || (clipX > rightmost)) && + ((maxX < leftmost) || (maxX > rightmost)) && + ((clipY < topmost) || (clipY > bottommost)) && + ((maxY < topmost) || (maxY > bottommost)) ) + return; // no, this is really totally clipped. + } + + if(CurPrimType!=HGEPRIM_TRIPLES || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_TRIPLES || CurTexture!=triple->tex || CurBlendMode!=triple->blend) + { + _render_batch(); + + CurPrimType=HGEPRIM_TRIPLES; + if(CurBlendMode != triple->blend) _SetBlendMode(triple->blend); + _BindTexture((gltexture *) triple->tex); + } + + memcpy(&VertArray[nPrim*HGEPRIM_TRIPLES], triple->v, sizeof(hgeVertex)*HGEPRIM_TRIPLES); + nPrim++; + } +} + +void CALL HGE_Impl::Gfx_RenderQuad(const hgeQuad *quad) +{ + if (VertArray) + { + const hgeVertex *v = quad->v; + if (_PrimsOutsideClipping(v, HGEPRIM_QUADS)) + { + // check for overlap, despite quad points being outside clipping... + const int maxX = clipX + clipW; + const int maxY = clipY + clipH; + const int leftmost = Min(Min(Min(v[0].x, v[1].x), v[2].x), v[3].x); + const int rightmost = Max(Max(Max(v[0].x, v[1].x), v[2].x), v[3].x); + const int topmost = Min(Min(Min(v[0].y, v[1].y), v[2].y), v[3].y); + const int bottommost = Max(Max(Max(v[0].y, v[1].y), v[2].y), v[3].y); + if ( ((clipX < leftmost) || (clipX > rightmost)) && + ((maxX < leftmost) || (maxX > rightmost)) && + ((clipY < topmost) || (clipY > bottommost)) && + ((maxY < topmost) || (maxY > bottommost)) ) + return; // no, this is really totally clipped. + } + + if(CurPrimType!=HGEPRIM_QUADS || nPrim>=VERTEX_BUFFER_SIZE/HGEPRIM_QUADS || CurTexture!=quad->tex || CurBlendMode!=quad->blend) + { + _render_batch(); + + CurPrimType=HGEPRIM_QUADS; + if(CurBlendMode != quad->blend) _SetBlendMode(quad->blend); + _BindTexture((gltexture *) quad->tex); + } + + memcpy(&VertArray[nPrim*HGEPRIM_QUADS], quad->v, sizeof(hgeVertex)*HGEPRIM_QUADS); + nPrim++; + } +} + +hgeVertex* CALL HGE_Impl::Gfx_StartBatch(int prim_type, HTEXTURE tex, int blend, int *max_prim) +{ + if(VertArray) + { + _render_batch(); + + CurPrimType=prim_type; + if(CurBlendMode != blend) _SetBlendMode(blend); + _BindTexture((gltexture *) tex); + *max_prim=VERTEX_BUFFER_SIZE / prim_type; + return VertArray; + } + else return 0; +} + +void CALL HGE_Impl::Gfx_FinishBatch(int nprim) +{ + nPrim = nprim; +} + +bool HGE_Impl::_BuildTarget(CRenderTargetList *pTarget, GLuint texname, int width, int height, bool zbuffer) +{ + bool okay = true; // no FBOs? Fake success by default. + if (pOpenGLDevice->have_GL_EXT_framebuffer_object) + { + pOpenGLDevice->glGenFramebuffersEXT(1, &pTarget->frame); + if (zbuffer) + pOpenGLDevice->glGenRenderbuffersEXT(1, &pTarget->depth); + pOpenGLDevice->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pTarget->frame); + pOpenGLDevice->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, pOpenGLDevice->TextureTarget, texname, 0); + if (zbuffer) + { + pOpenGLDevice->glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, pTarget->depth); + pOpenGLDevice->glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height); + pOpenGLDevice->glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, pTarget->depth); + } + + GLenum rc = pOpenGLDevice->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if ((rc == GL_FRAMEBUFFER_COMPLETE_EXT) && (pOpenGLDevice->glGetError() == GL_NO_ERROR)) + { + pOpenGLDevice->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + okay = true; + } + else + { + pOpenGLDevice->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + pOpenGLDevice->glDeleteRenderbuffersEXT(1, &pTarget->depth); + pOpenGLDevice->glDeleteFramebuffersEXT(1, &pTarget->frame); + } + pOpenGLDevice->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, pCurTarget ? pCurTarget->frame : 0); + } + + return okay; +} + +HTARGET CALL HGE_Impl::Target_Create(int width, int height, bool zbuffer) +{ + bool okay = false; + CRenderTargetList *pTarget = new CRenderTargetList; + memset(pTarget, '\0', sizeof (CRenderTargetList)); + + pTarget->tex = _BuildTexture(width, height, NULL); + gltexture *gltex = (gltexture *) pTarget->tex; + gltex->is_render_target = true; + gltex->lost = false; + _ConfigureTexture(gltex, width, height, NULL); + + pTarget->width = width; + pTarget->height = height; + + okay = _BuildTarget(pTarget, gltex->name, width, height, zbuffer); + if (!okay) + { + System_Log("%s: OpenGL: Failed to create render target!",GRAPHICS_SRC_FN); + Texture_Free(pTarget->tex); + delete pTarget; + return 0; + } + + pTarget->next=pTargets; + pTargets=pTarget; + + return (HTARGET)pTarget; +} + +void CALL HGE_Impl::Target_Free(HTARGET target) +{ + CRenderTargetList *pTarget=pTargets, *pPrevTarget=NULL; + + while(pTarget) + { + if((CRenderTargetList *)target == pTarget) + { + if(pPrevTarget) + pPrevTarget->next = pTarget->next; + else + pTargets = pTarget->next; + + if (pOpenGLDevice->have_GL_EXT_framebuffer_object) + { + if (pCurTarget == (CRenderTargetList *)target) + pOpenGLDevice->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + if (pTarget->depth) + pOpenGLDevice->glDeleteRenderbuffersEXT(1, &pTarget->depth); + pOpenGLDevice->glDeleteFramebuffersEXT(1, &pTarget->frame); + } + + if (pCurTarget == (CRenderTargetList *)target) + pCurTarget = 0; + + Texture_Free(pTarget->tex); + delete pTarget; + return; + } + + pPrevTarget = pTarget; + pTarget = pTarget->next; + } +} + +HTEXTURE CALL HGE_Impl::Target_GetTexture(HTARGET target) +{ + CRenderTargetList *targ=(CRenderTargetList *)target; + if(target) return targ->tex; + else return 0; +} + +static inline bool _IsPowerOfTwo(const GLuint x) +{ + return ((x & (x - 1)) == 0); +} + +static inline GLuint _NextPowerOfTwo(GLuint x) +{ + x--; + for (unsigned i = 1; i < (sizeof(GLuint) * 8); i <<= 1) + x |= x >> i; + return x + 1; +} + +void HGE_Impl::_ConfigureTexture(gltexture *t, int width, int height, DWORD *pixels) +{ + GLuint tex = 0; + pOpenGLDevice->glGenTextures(1, &tex); + + t->lost = false; + t->name = tex; + t->width = width; + t->height = height; + t->pixels = pixels; + t->potw = 0; + t->poth = 0; + + // see if we're backed by a file and not RAM. + const bool loadFromFile = ((pixels == NULL) && (t->filename != NULL)); + if (loadFromFile) + { + DWORD size = 0; + BYTE *data = (BYTE *) pHGE->Resource_Load(t->filename, &size); + if (data != NULL) + { + int w, h; + pixels = _DecodeImage(data, t->filename, size, w, h); + if ((w != width) || (h != height)) // yikes, file changed? + { + delete[] pixels; + pixels = NULL; + } + Resource_Free(data); + } + } + + pOpenGLDevice->glBindTexture(pOpenGLDevice->TextureTarget, tex); + if (pOpenGLDevice->TextureTarget != GL_TEXTURE_RECTANGLE_ARB) + { + pOpenGLDevice->glTexParameterf(pOpenGLDevice->TextureTarget, GL_TEXTURE_MIN_LOD, 0.0f); + pOpenGLDevice->glTexParameterf(pOpenGLDevice->TextureTarget, GL_TEXTURE_MAX_LOD, 0.0f); + pOpenGLDevice->glTexParameteri(pOpenGLDevice->TextureTarget, GL_TEXTURE_BASE_LEVEL, 0); + pOpenGLDevice->glTexParameteri(pOpenGLDevice->TextureTarget, GL_TEXTURE_MAX_LEVEL, 0); + } + const GLenum intfmt = pOpenGLDevice->have_GL_EXT_texture_compression_s3tc ? GL_COMPRESSED_RGBA_S3TC_DXT5_EXT : GL_RGBA; + if ((pOpenGLDevice->have_GL_ARB_texture_rectangle) || (pOpenGLDevice->have_GL_ARB_texture_non_power_of_two) || (_IsPowerOfTwo(width) && _IsPowerOfTwo(height))) { + pOpenGLDevice->glTexImage2D(pOpenGLDevice->TextureTarget, 0, intfmt, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + } + else + { + t->potw = _NextPowerOfTwo(width); + t->poth = _NextPowerOfTwo(height); + pOpenGLDevice->glTexImage2D(pOpenGLDevice->TextureTarget, 0, intfmt, t->potw, t->poth, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + pOpenGLDevice->glTexSubImage2D(pOpenGLDevice->TextureTarget, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + } + + pOpenGLDevice->glBindTexture(pOpenGLDevice->TextureTarget, CurTexture ? (((gltexture *) CurTexture)->name) : 0); + + if (loadFromFile) + delete[] pixels; +} + +HTEXTURE HGE_Impl::_BuildTexture(int width, int height, DWORD *pixels) +{ + gltexture *retval = new gltexture; + memset(retval, '\0', sizeof (gltexture)); + retval->lost = true; // we'll actually generate a texture and upload when forced. + retval->width = width; + retval->height = height; + retval->pixels = pixels; + return (HTEXTURE)retval; +} + +HTEXTURE CALL HGE_Impl::Texture_Create(int width, int height) +{ + DWORD *pixels = new DWORD[width * height]; + memset(pixels, '\0', sizeof (DWORD) * width * height); + HTEXTURE retval = _BuildTexture(width, height, pixels); + + // the Direct3D renderer doesn't add these to the (textures) list, but we need them for when we "lose" the GL context. + if (retval != 0) + { + CTextureList *texItem=new CTextureList; + texItem->tex=retval; + texItem->width=width; + texItem->height=height; + texItem->next=textures; + textures=texItem; + } + + return retval; +} + +HTEXTURE CALL HGE_Impl::Texture_Load(const char *filename, DWORD size, bool bMipmap) +{ + HTEXTURE retval = 0; + int width = 0; + int height = 0; + + void *data; + DWORD _size; + CTextureList *texItem; + const char *fname = NULL; + if(size) { data=(void *)filename; _size=size; } + else + { + fname = filename; + data=pHGE->Resource_Load(filename, &_size); + if(!data) return 0; + } + + DWORD *pixels = _DecodeImage((BYTE *) data, fname, _size, width, height); + if (pixels != NULL) + retval = _BuildTexture(width, height, pixels); + + if(!size) Resource_Free(data); + + if (retval == 0) + { + STUBBED("texture load fail!"); + _PostError("Can't create texture"); + } + else + { + texItem=new CTextureList; + texItem->tex=retval; + texItem->width=width; + texItem->height=height; + texItem->next=textures; + textures=texItem; + + // force an upload to the GL and lose our copy if it's backed by + // a file. We won't keep it here to conserve system RAM. + if (!size) + { + gltexture *t = (gltexture *) retval; + _ConfigureTexture(t, t->width, t->height, t->pixels); + delete[] t->pixels; + t->pixels = NULL; + t->filename = strcpy(new char[strlen(filename) + 1], filename); + } + } + + return retval; +} + +void CALL HGE_Impl::Texture_Free(HTEXTURE tex) +{ + if (pOpenGLDevice == NULL) + return; // in case we already shut down. + + CTextureList *texItem=textures, *texPrev=0; + + while(texItem) + { + if(texItem->tex==tex) + { + if(texPrev) texPrev->next=texItem->next; + else textures=texItem->next; + delete texItem; + break; + } + texPrev=texItem; + texItem=texItem->next; + } + if(tex) + { + gltexture *pTex = (gltexture *) tex; + delete[] pTex->filename; + delete[] pTex->lock_pixels; + delete[] pTex->pixels; + pOpenGLDevice->glDeleteTextures(1, &pTex->name); + delete pTex; + } +} + +int CALL HGE_Impl::Texture_GetWidth(HTEXTURE tex, bool bOriginal) +{ + CTextureList *texItem=textures; + + if(bOriginal) + { + while(texItem) + { + if(texItem->tex==tex) return texItem->width; + texItem=texItem->next; + } + } + else + { + return ((gltexture*)tex)->width; + } + return 0; +} + + +int CALL HGE_Impl::Texture_GetHeight(HTEXTURE tex, bool bOriginal) +{ + CTextureList *texItem=textures; + + if(bOriginal) + { + while(texItem) + { + if(texItem->tex==tex) return texItem->height; + texItem=texItem->next; + } + } + else + { + return ((gltexture*)tex)->height; + } + return 0; +} + +// HGE extension! +// fast path for pushing YUV video to a texture instead of having to +// lock/convert-to-rgba/unlock...current HGE semantics involve a +// lot of unnecessary overhead on this, not to mention the conversion +// on the CPU is painful on PowerPC chips. +// This lets us use OpenGL extensions to move data to the hardware +// without conversion. +// Don't taunt this function. Side effects are probably rampant. +bool CALL HGE_Impl::HGEEXT_Texture_PushYUV422(HTEXTURE tex, const BYTE *yuv) +{ + if (!pOpenGLDevice->have_GL_APPLE_ycbcr_422) + return false; + + gltexture *pTex=(gltexture*)tex; + assert(!pTex->lock_pixels); + + if (pTex->lost) // just reupload the whole thing. + _ConfigureTexture(pTex, pTex->width, pTex->height, pTex->pixels); + + // Any existing pixels aren't valid anymore. + if (pTex->pixels) + { + delete[] pTex->pixels; + pTex->pixels = NULL; + } + + pOpenGLDevice->glBindTexture(pOpenGLDevice->TextureTarget, pTex->name); + pOpenGLDevice->glTexSubImage2D(pOpenGLDevice->TextureTarget, 0, 0, 0, + pTex->width, pTex->height, GL_YCBCR_422_APPLE, + GL_UNSIGNED_SHORT_8_8_APPLE, yuv); + pOpenGLDevice->glBindTexture(pOpenGLDevice->TextureTarget, CurTexture ? (((gltexture *) CurTexture)->name) : 0); + return true; +} + +DWORD * CALL HGE_Impl::Texture_Lock(HTEXTURE tex, bool bReadOnly, int left, int top, int width, int height) +{ + gltexture *pTex=(gltexture*)tex; + + if (pTex->lock_pixels) + { + assert(false && "multiple lock of texture..."); + return 0; + } + + // see if we're backed by a file and not RAM. + const bool loadFromFile = ((pTex->pixels == NULL) && (pTex->filename != NULL)); + if (loadFromFile) + { + DWORD size = 0; + BYTE *data = (BYTE *) pHGE->Resource_Load(pTex->filename, &size); + if (data != NULL) + { + int w, h; + pTex->pixels = _DecodeImage(data, pTex->filename, size, w, h); + if ((w != (int)pTex->width) || (h != (int)pTex->height)) // yikes, file changed? + { + delete[] pTex->pixels; + pTex->pixels = NULL; + } + Resource_Free(data); + } + if (pTex->pixels != NULL) + { + // can't go back to file after we lock, since app might change data. + if (!bReadOnly) + { + delete[] pTex->filename; + pTex->filename = NULL; + } + } + } + + if ((pTex->pixels == NULL) && (!pTex->is_render_target)) // can't lock this texture...?! + return 0; + + // !!! FIXME: is this right? + if((width == 0) && (height == 0)) + { + width = pTex->width; + height = pTex->height; + } + + // !!! FIXME: do something with this? + assert(width > 0); + assert(width <= (int)pTex->width); + assert(height > 0); + assert(height <= (int)pTex->height); + assert(left >= 0); + assert(left <= width); + assert(top >= 0); + assert(top <= height); + + pTex->lock_readonly = bReadOnly; + pTex->lock_x = left; + pTex->lock_y = top; + pTex->lock_width = width; + pTex->lock_height = height; + pTex->lock_pixels = new DWORD[width * height]; + + DWORD *dst = pTex->lock_pixels; + + if (pTex->is_render_target) + { + assert(false && "need to bind fbo before glReadPixels..."); + DWORD *upsideDown = new DWORD[width * height]; + DWORD *src = upsideDown + ((height-1) * width); + pOpenGLDevice->glReadPixels(left, (pTex->height-top)-height, width, height, GL_RGBA, GL_UNSIGNED_BYTE, upsideDown); + for (int i = 0; i < height; i++) + { + memcpy(dst, src, width * sizeof (DWORD)); + dst += width; + src -= width; + } + delete[] upsideDown; + } + else + { + DWORD *src = pTex->pixels + ((top*pTex->width) + left); + for (int i = 0; i < height; i++) + { + memcpy(dst, src, width * sizeof (DWORD)); + dst += width; + src += pTex->width; + } + } + + return pTex->lock_pixels; +} + + +void CALL HGE_Impl::Texture_Unlock(HTEXTURE tex) +{ + gltexture *pTex=(gltexture*)tex; + + if (pTex->lock_pixels == NULL) return; // not locked. + + if (!pTex->lock_readonly) // have to reupload to the hardware. + { + // need to update pTex->pixels ... + const DWORD *src = pTex->lock_pixels; + DWORD *dst = pTex->pixels + ((pTex->lock_y*pTex->width) + pTex->lock_x); + for (int i = 0; i < pTex->lock_height; i++) + { + memcpy(dst, src, pTex->lock_width * sizeof (DWORD)); + dst += pTex->width; + src += pTex->lock_width; + } + + if (pTex->lost) // just reupload the whole thing. + _ConfigureTexture(pTex, pTex->width, pTex->height, pTex->pixels); + else + { + pOpenGLDevice->glBindTexture(pOpenGLDevice->TextureTarget, pTex->name); + pOpenGLDevice->glTexSubImage2D(pOpenGLDevice->TextureTarget, 0, pTex->lock_x, + (pTex->height-pTex->lock_y)-pTex->lock_height, + pTex->lock_width, pTex->lock_height, GL_RGBA, + GL_UNSIGNED_BYTE, pTex->lock_pixels); + pOpenGLDevice->glBindTexture(pOpenGLDevice->TextureTarget, CurTexture ? (((gltexture *) CurTexture)->name) : 0); + } + } + + // if we were read-only and we're backed by a file, ditch the uncompressed copy in system RAM. + if ((pTex->filename != NULL) && (pTex->lock_readonly)) + { + delete[] pTex->pixels; + pTex->pixels = NULL; + } + + delete[] pTex->lock_pixels; + pTex->lock_pixels = NULL; + pTex->lock_readonly = false; + pTex->lock_x = -1; + pTex->lock_y = -1; + pTex->lock_width = -1; + pTex->lock_height = -1; +} + +//////// Implementation //////// + +#define DEBUG_VERTICES 0 +#if DEBUG_VERTICES +static inline void print_vertex(const hgeVertex *v) +{ + printf(" (%f, %f, %f), 0x%X, (%f, %f)\n", v->x, v->y, v->z, v->col, v->tx, v->ty); +} +#endif + +void HGE_Impl::_render_batch(bool bEndScene) +{ + if(VertArray) + { + if(nPrim) + { + const float h = (float) ((pCurTarget) ? pCurTarget->height : nScreenHeight); + + // texture rectangles range from 0 to size, not 0 to 1. :/ + float texwmult = 1.0f; + float texhmult = 1.0f; + + if (CurTexture) + { + _SetTextureFilter(); + const gltexture *pTex = ((gltexture *)CurTexture); + if (pOpenGLDevice->TextureTarget == GL_TEXTURE_RECTANGLE_ARB) + { + texwmult = pTex->width; + texhmult = pTex->height; + } + else if ((pTex->potw != 0) && (pTex->poth != 0)) + { + texwmult = ( ((float)pTex->width) / ((float)pTex->potw) ); + texhmult = ( ((float)pTex->height) / ((float)pTex->poth) ); + } + } + + for (int i = 0; i < nPrim*CurPrimType; i++) + { + // (0, 0) is the lower left in OpenGL, upper left in D3D. + VertArray[i].y = h - VertArray[i].y; + + // Z axis is inverted in OpenGL from D3D. + VertArray[i].z = -VertArray[i].z; + + // (0, 0) is lower left texcoord in OpenGL, upper left in D3D. + // Also, scale for texture rectangles vs. 2D textures. + VertArray[i].tx *= texwmult; + VertArray[i].ty = (1.0f - VertArray[i].ty) * texhmult; + + // Colors are RGBA in OpenGL, ARGB in Direct3D. + const DWORD color = VertArray[i].col; + BYTE *col = (BYTE *) &VertArray[i].col; + const BYTE a = ((color >> 24) & 0xFF); + const BYTE r = ((color >> 16) & 0xFF); + const BYTE g = ((color >> 8) & 0xFF); + const BYTE b = ((color >> 0) & 0xFF); + col[0] = r; + col[1] = g; + col[2] = b; + col[3] = a; + } + + switch(CurPrimType) + { + case HGEPRIM_QUADS: + pOpenGLDevice->glDrawElements(GL_TRIANGLES, nPrim * 6, GL_UNSIGNED_SHORT, pIB); + #if DEBUG_VERTICES + for (int i = 0; i < nPrim*6; i+=3) + { + printf("QUAD'S TRIANGLE:\n"); + print_vertex(&pVB[pIB[i+0]]); + print_vertex(&pVB[pIB[i+1]]); + print_vertex(&pVB[pIB[i+2]]); + } + printf("DONE.\n"); + #endif + break; + + case HGEPRIM_TRIPLES: + pOpenGLDevice->glDrawArrays(GL_TRIANGLES, 0, nPrim * 3); + break; + + case HGEPRIM_LINES: + pOpenGLDevice->glDrawArrays(GL_LINES, 0, nPrim * 2); + break; + } + + nPrim=0; + } + if(bEndScene) VertArray = 0; + else VertArray = pVB; + } +} + +void HGE_Impl::_SetBlendMode(int blend) +{ + if((blend & BLEND_ALPHABLEND) != (CurBlendMode & BLEND_ALPHABLEND)) + { + if(blend & BLEND_ALPHABLEND) pOpenGLDevice->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + else pOpenGLDevice->glBlendFunc(GL_SRC_ALPHA, GL_ONE); + } + + if((blend & BLEND_ZWRITE) != (CurBlendMode & BLEND_ZWRITE)) + { + if(blend & BLEND_ZWRITE) pOpenGLDevice->glDepthMask(GL_TRUE); + else pOpenGLDevice->glDepthMask(GL_FALSE); + } + + if((blend & BLEND_COLORADD) != (CurBlendMode & BLEND_COLORADD)) + { + if(blend & BLEND_COLORADD) pOpenGLDevice->glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); + else pOpenGLDevice->glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + + CurBlendMode = blend; +} + +void HGE_Impl::_SetProjectionMatrix(int width, int height) +{ + pOpenGLDevice->glMatrixMode(GL_PROJECTION); + pOpenGLDevice->glLoadIdentity(); + pOpenGLDevice->glOrtho(0, (float)width, 0, (float)height, 0.0f, 1.0f); + bTransforming = false; + clipX = 0; + clipY = 0; + clipW = width; + clipH = height; +} + +void HGE_Impl::_UnloadOpenGLEntryPoints() +{ + #define GL_PROC(ext,fn,call,ret,params) pOpenGLDevice->fn = NULL; + #include "hge_glfuncs.h" + #undef GL_PROC +} + +bool HGE_Impl::_HaveOpenGLExtension(const char *extlist, const char *ext) +{ + const char *ptr = strstr(extlist, ext); + if (ptr == NULL) + return false; + + const char endchar = ptr[strlen(ext)]; + if ((endchar == '\0') || (endchar == ' ')) + return true; // extension is in the list. + + return false; // just not supported, fail. +} + +bool HGE_Impl::_LoadOpenGLEntryPoints() +{ + System_Log("%s: OpenGL: loading entry points and examining extensions...",GRAPHICS_SRC_FN); + + // these can be reset to false below... + pOpenGLDevice->have_base_opengl = true; + pOpenGLDevice->have_GL_ARB_texture_rectangle = true; + pOpenGLDevice->have_GL_ARB_texture_non_power_of_two = true; + pOpenGLDevice->have_GL_EXT_framebuffer_object = true; + pOpenGLDevice->have_GL_EXT_texture_compression_s3tc = true; + pOpenGLDevice->have_GL_ARB_vertex_buffer_object = true; + pOpenGLDevice->have_GL_APPLE_ycbcr_422 = true; + + #define GL_PROC(ext,fn,call,ret,params) \ + if (pOpenGLDevice->have_##ext) { \ + if ((pOpenGLDevice->fn = (_HGE_PFN_##fn) SDL_GL_GetProcAddress(#fn)) == NULL) { \ + System_Log("Failed to load OpenGL entry point '" #fn "'"); \ + pOpenGLDevice->have_##ext = false; \ + } \ + } else {} + #include "hge_glfuncs.h" + #undef GL_PROC + + if (!pOpenGLDevice->have_base_opengl) + { + _UnloadOpenGLEntryPoints(); + return false; + } + + System_Log("%s: GL_RENDERER: %s",GRAPHICS_SRC_FN, (const char *) pOpenGLDevice->glGetString(GL_RENDERER)); + System_Log("%s: GL_VENDOR: %s",GRAPHICS_SRC_FN, (const char *) pOpenGLDevice->glGetString(GL_VENDOR)); + System_Log("%s: GL_VERSION: %s",GRAPHICS_SRC_FN, (const char *) pOpenGLDevice->glGetString(GL_VERSION)); + + const char *verstr = (const char *) pOpenGLDevice->glGetString(GL_VERSION); + int maj = 0; + int min = 0; + sscanf(verstr, "%d.%d", &maj, &min); + + if ( (maj < 1) || ((maj == 1) && (min < 2)) ) + { + _PostError("OpenGL implementation must be at least version 1.2"); + _UnloadOpenGLEntryPoints(); + return false; + } + + const char *exts = (const char *) pOpenGLDevice->glGetString(GL_EXTENSIONS); + + // NPOT texture support ... + + if (_HaveOpenGLExtension(exts, "GL_ARB_texture_rectangle")) + pOpenGLDevice->have_GL_ARB_texture_rectangle = true; + else if (_HaveOpenGLExtension(exts, "GL_EXT_texture_rectangle")) + pOpenGLDevice->have_GL_ARB_texture_rectangle = true; + else if (_HaveOpenGLExtension(exts, "GL_NV_texture_rectangle")) + pOpenGLDevice->have_GL_ARB_texture_rectangle = true; + else + pOpenGLDevice->have_GL_ARB_texture_rectangle = false; + + if (maj >= 2) + pOpenGLDevice->have_GL_ARB_texture_non_power_of_two = true; + else if (_HaveOpenGLExtension(exts, "GL_ARB_texture_non_power_of_two")) + pOpenGLDevice->have_GL_ARB_texture_non_power_of_two = true; + else + pOpenGLDevice->have_GL_ARB_texture_non_power_of_two = false; + + if (pOpenGLDevice->have_GL_ARB_texture_rectangle) + { + System_Log("%s: OpenGL: Using GL_ARB_texture_rectangle",GRAPHICS_SRC_FN); + pOpenGLDevice->TextureTarget = GL_TEXTURE_RECTANGLE_ARB; + } + else if (pOpenGLDevice->have_GL_ARB_texture_non_power_of_two) + { + System_Log("%s: OpenGL: Using GL_ARB_texture_non_power_of_two",GRAPHICS_SRC_FN); + pOpenGLDevice->TextureTarget = GL_TEXTURE_2D; + } + else + { + // We can fake this with POT textures. Get a real OpenGL! + System_Log("%s: OpenGL: Using power-of-two textures. This costs more memory!",GRAPHICS_SRC_FN); + pOpenGLDevice->TextureTarget = GL_TEXTURE_2D; + } + + // render-to-texture support ... + + // is false if an entry point is missing, but we still need to check for the extension string... + if (pOpenGLDevice->have_GL_EXT_framebuffer_object) + { + // Disable this on Mac OS X Tiger, since some drivers appear to be buggy. + if ((pHGE->MacOSXVersion) && (pHGE->MacOSXVersion < 0x1050)) + pOpenGLDevice->have_GL_EXT_framebuffer_object = false; + else if (_HaveOpenGLExtension(exts, "GL_EXT_framebuffer_object")) + pOpenGLDevice->have_GL_EXT_framebuffer_object = true; + else + pOpenGLDevice->have_GL_EXT_framebuffer_object = false; + } + + if (pOpenGLDevice->have_GL_EXT_framebuffer_object) + System_Log("%s: OpenGL: Using GL_EXT_framebuffer_object",GRAPHICS_SRC_FN); + else + System_Log("%s: OpenGL: WARNING! No render-to-texture support. Things may render badly.",GRAPHICS_SRC_FN); + + + // Texture compression ... + + if (bForceTextureCompression && + _HaveOpenGLExtension(exts, "GL_ARB_texture_compression") && + _HaveOpenGLExtension(exts, "GL_EXT_texture_compression_s3tc")) + pOpenGLDevice->have_GL_EXT_texture_compression_s3tc = true; + else + pOpenGLDevice->have_GL_EXT_texture_compression_s3tc = false; + + if (pOpenGLDevice->have_GL_EXT_texture_compression_s3tc) + System_Log("%s: OpenGL: Using GL_EXT_texture_compression_s3tc",GRAPHICS_SRC_FN); + else if (bForceTextureCompression) + { + bForceTextureCompression = false; // oh well. + System_Log("%s: OpenGL: WARNING: no texture compression support, in a low-memory system.",GRAPHICS_SRC_FN); + System_Log("%s: OpenGL: Performance may be very bad!",GRAPHICS_SRC_FN); + } + + // YUV textures... + + if (_HaveOpenGLExtension(exts, "GL_APPLE_ycbcr_422")) + pOpenGLDevice->have_GL_APPLE_ycbcr_422 = true; + else + pOpenGLDevice->have_GL_APPLE_ycbcr_422 = false; + + if (pOpenGLDevice->have_GL_APPLE_ycbcr_422) + System_Log("%s: OpenGL: Using GL_APPLE_ycbcr_422 to render YUV frames.",GRAPHICS_SRC_FN); + else + System_Log("%s: OpenGL: WARNING: no YUV texture support; videos may render slowly.",GRAPHICS_SRC_FN); + + // VBOs... + + // is false if an entry point is missing, but we still need to check for the extension string... + if (pOpenGLDevice->have_GL_ARB_vertex_buffer_object) + { + if (_HaveOpenGLExtension(exts, "GL_ARB_vertex_buffer_object")) + pOpenGLDevice->have_GL_ARB_vertex_buffer_object = true; + else + pOpenGLDevice->have_GL_ARB_vertex_buffer_object = false; + } + + if (pOpenGLDevice->have_GL_ARB_vertex_buffer_object) + System_Log("%s: OpenGL: Using GL_ARB_vertex_buffer_object",GRAPHICS_SRC_FN); + else + System_Log("%s: OpenGL: WARNING! No VBO support; performance may suffer.",GRAPHICS_SRC_FN); + + return true; +} + +bool HGE_Impl::_GfxInit() +{ + CurTexture = 0; + +// Init OpenGL ... SDL should have created a context at this point. + assert(pOpenGLDevice == NULL); + pOpenGLDevice = new COpenGLDevice; + if (!_LoadOpenGLEntryPoints()) + return false; // already called _PostError(). + + nScreenBPP=SDL_GetVideoSurface()->format->BitsPerPixel; + + _AdjustWindow(); + + System_Log("%s: Mode: %d x %d\n",GRAPHICS_SRC_FN,nScreenWidth,nScreenHeight); +// Create vertex batch buffer + + VertArray=0; + textures=0; + IndexBufferObject=0; + +// Init all stuff that can be lost + + if(!_init_lost()) return false; + + // make sure the framebuffers are cleared and force to screen + pOpenGLDevice->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + SDL_GL_SwapBuffers(); + pOpenGLDevice->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + SDL_GL_SwapBuffers(); + + return true; +} + +void HGE_Impl::_AdjustWindow() +{ + // no-op. +} + +void HGE_Impl::_Resize(int width, int height) +{ + if(hwndParent) + { + //if(procFocusLostFunc) procFocusLostFunc(); + STUBBED("resize"); + #if 0 + d3dppW.BackBufferWidth=width; + d3dppW.BackBufferHeight=height; + nScreenWidth=width; + nScreenHeight=height; + + _SetProjectionMatrix(nScreenWidth, nScreenHeight); + _GfxRestore(); + #endif + + //if(procFocusGainFunc) procFocusGainFunc(); + } +} + +void HGE_Impl::_GfxDone() +{ + //CRenderTargetList *target=pTargets; + + while(textures) Texture_Free(textures->tex); + while(pTargets) Target_Free((HTARGET) pTargets); + textures=0; + pTargets=0; + + VertArray = 0; + delete[] pVB; + pVB=0; + delete[] pIB; + pIB=0; + + if(pOpenGLDevice) + { + if (pOpenGLDevice->have_GL_ARB_vertex_buffer_object) + { + if (IndexBufferObject != 0) + { + pOpenGLDevice->glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0); + pOpenGLDevice->glDeleteBuffersARB(1, &IndexBufferObject); + IndexBufferObject = 0; + } + } + + delete pOpenGLDevice; + pOpenGLDevice=0; + } +} + + +bool HGE_Impl::_GfxRestore() +{ + if(!pOpenGLDevice) return false; + + delete[] pVB; + pVB=0; + + delete[] pIB; + pIB=0; + + _UnloadOpenGLEntryPoints(); + if (!_LoadOpenGLEntryPoints()) + return false; + + if(!_init_lost()) return false; + + if(procGfxRestoreFunc) return procGfxRestoreFunc(); + + return true; +} + + +bool HGE_Impl::_init_lost() +{ + _BindTexture(NULL); // make sure nothing is bound, so everything that we do bind regenerates. + + for (CTextureList *item = textures; item != NULL; item = item->next) + { + gltexture *t = (gltexture *) item->tex; + if (t == NULL) continue; + t->lost = true; + t->name = 0; + } + + CRenderTargetList *target=pTargets; + while(target) + { + gltexture *tex = (gltexture *) target->tex; + _BindTexture(tex); // force texture recreation. + _BindTexture(NULL); + _BuildTarget(target, tex ? tex->name : 0, target->width, target->height, target->depth != 0); + target=target->next; + } + +// Create Vertex buffer + // We just use a client-side array, since you can reasonably count on support + // existing in any GL, and it basically offers the same functionality that + // HGE uses in Direct3D: it locks the vertex buffer, unlocks in time to + // draw something, then relocks again immediately...more or less, that method + // offers the same performance metrics as a client-side array. + // We _will_ stuff the indices in a buffer object, though, if possible, + // since they never change...this matches the D3D behaviour better, since + // they lock, store, and forget about it, but without a buffer object, + // we'd have to pass the array over the bus every glDrawElements() call. + // It's not worth the tapdance for vertex buffer objects though, due to + // HGE's usage patterns. + pVB = new hgeVertex[VERTEX_BUFFER_SIZE]; + +// Create and setup Index buffer + pIB = new GLushort[VERTEX_BUFFER_SIZE*6/4]; + GLushort *pIndices = pIB; + int n = 0; + for(int i=0; i<VERTEX_BUFFER_SIZE/4; i++) { + *pIndices++=n; + *pIndices++=n+1; + *pIndices++=n+2; + *pIndices++=n+2; + *pIndices++=n+3; + *pIndices++=n; + n+=4; + } + + #if !DEBUG_VERTICES // need pIB for DEBUG_VERTICES. + if (pOpenGLDevice->have_GL_ARB_vertex_buffer_object) + { + // stay bound forever. The Index Buffer Object never changes. + pOpenGLDevice->glGenBuffersARB(1, &IndexBufferObject); + pOpenGLDevice->glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, IndexBufferObject); + pOpenGLDevice->glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, sizeof (GLushort) * ((VERTEX_BUFFER_SIZE*6)/4), pIB, GL_STATIC_DRAW); + delete[] pIB; + pIB=0; + } + #endif + + // always use client-side arrays; set it up once at startup. + pOpenGLDevice->glVertexPointer(3, GL_FLOAT, sizeof (hgeVertex), &pVB[0].x); + pOpenGLDevice->glColorPointer(4, GL_UNSIGNED_BYTE, sizeof (hgeVertex), &pVB[0].col); + pOpenGLDevice->glTexCoordPointer(2, GL_FLOAT, sizeof (hgeVertex), &pVB[0].tx); + pOpenGLDevice->glEnableClientState(GL_VERTEX_ARRAY); + pOpenGLDevice->glEnableClientState(GL_COLOR_ARRAY); + pOpenGLDevice->glEnableClientState(GL_TEXTURE_COORD_ARRAY); + +// Set common render states + + pOpenGLDevice->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + pOpenGLDevice->glPixelStorei(GL_PACK_ALIGNMENT, 1); + + //pD3DDevice->SetRenderState( D3DRS_LASTPIXEL, FALSE ); + pOpenGLDevice->glDisable(GL_TEXTURE_2D); + if (pOpenGLDevice->have_GL_ARB_texture_rectangle) + pOpenGLDevice->glDisable(GL_TEXTURE_RECTANGLE_ARB); + pOpenGLDevice->glEnable(pOpenGLDevice->TextureTarget); + pOpenGLDevice->glEnable(GL_SCISSOR_TEST); + pOpenGLDevice->glDisable(GL_CULL_FACE); + pOpenGLDevice->glDisable(GL_LIGHTING); + pOpenGLDevice->glDepthFunc(GL_GEQUAL); + + if (bZBuffer) + pOpenGLDevice->glEnable(GL_DEPTH_TEST); + else + pOpenGLDevice->glDisable(GL_DEPTH_TEST); + + pOpenGLDevice->glEnable(GL_BLEND); + pOpenGLDevice->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + pOpenGLDevice->glEnable(GL_ALPHA_TEST); + pOpenGLDevice->glAlphaFunc(GL_GEQUAL, 1.0f / 255.0f); + + pOpenGLDevice->glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + _SetTextureFilter(); + + // !!! FIXME: this isn't what HGE's Direct3D code does, but the game I'm working with + // !!! FIXME: forces clamping outside of HGE, so I just wedged it in here. + // Apple says texture rectangle on ATI X1000 chips only supports CLAMP_TO_EDGE. + // Texture rectangle only supports CLAMP* wrap modes anyhow. + pOpenGLDevice->glTexParameteri(pOpenGLDevice->TextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + pOpenGLDevice->glTexParameteri(pOpenGLDevice->TextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + pOpenGLDevice->glTexParameteri(pOpenGLDevice->TextureTarget, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + nPrim=0; + CurPrimType=HGEPRIM_QUADS; + CurBlendMode = BLEND_DEFAULT; + CurTexture = 0; + + pOpenGLDevice->glScissor(0, 0, nScreenWidth, nScreenHeight); + pOpenGLDevice->glViewport(0, 0, nScreenWidth, nScreenHeight); + + // make sure the framebuffer is cleared and force to screen + pOpenGLDevice->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + _SetProjectionMatrix(nScreenWidth, nScreenHeight); + pOpenGLDevice->glMatrixMode(GL_MODELVIEW); + pOpenGLDevice->glLoadIdentity(); + + return true; +} diff --git a/archive/hge/hge_glfuncs.h b/archive/hge/hge_glfuncs.h new file mode 100644 index 0000000..1c0af81 --- /dev/null +++ b/archive/hge/hge_glfuncs.h @@ -0,0 +1,72 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** OpenGL entry points. +*/ + +// don't put #pragma once wrappers in this file, it gets #included +// several times with different #defines for GL_PROC. + +// base GL functionality... +GL_PROC(base_opengl,glEnable,WINGDIAPI,void,(GLenum cap)) +GL_PROC(base_opengl,glDisable,WINGDIAPI,void,(GLenum cap)) +GL_PROC(base_opengl,glGetIntegerv,WINGDIAPI,void,(GLenum pname, GLint *params)) +GL_PROC(base_opengl,glGetString,WINGDIAPI,const GLubyte *,(GLenum name)) +GL_PROC(base_opengl,glGetError,WINGDIAPI,GLenum,(void)) +GL_PROC(base_opengl,glDepthMask,WINGDIAPI,void,(GLboolean flag)) +GL_PROC(base_opengl,glDepthRange,WINGDIAPI,void,(GLclampd zNear, GLclampd zFar)) +GL_PROC(base_opengl,glBlendFunc,WINGDIAPI,void,(GLenum sfactor, GLenum dfactor)) +GL_PROC(base_opengl,glAlphaFunc,WINGDIAPI,void,(GLenum func, GLclampf ref)) +GL_PROC(base_opengl,glDepthFunc,WINGDIAPI,void,(GLenum func)) +GL_PROC(base_opengl,glMatrixMode,WINGDIAPI,void,(GLenum mode)) +GL_PROC(base_opengl,glLoadIdentity,WINGDIAPI,void,(void)) +GL_PROC(base_opengl,glScalef,WINGDIAPI,void,(GLfloat x, GLfloat y, GLfloat z)) +GL_PROC(base_opengl,glViewport,WINGDIAPI,void,(GLint x, GLint y, GLsizei width, GLsizei height)) +GL_PROC(base_opengl,glTranslatef,WINGDIAPI,void,(GLfloat x, GLfloat y, GLfloat z)) +GL_PROC(base_opengl,glRotatef,WINGDIAPI,void,(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)) +GL_PROC(base_opengl,glOrtho,WINGDIAPI,void,(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)) +GL_PROC(base_opengl,glScissor,WINGDIAPI,void,(GLint x, GLint y, GLsizei width, GLsizei height)) +GL_PROC(base_opengl,glClearColor,WINGDIAPI,void,(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)) +GL_PROC(base_opengl,glClear,WINGDIAPI,void,(GLbitfield mask)) +GL_PROC(base_opengl,glPixelStorei,WINGDIAPI,void,(GLenum pname, GLint param)) +GL_PROC(base_opengl,glBindTexture,WINGDIAPI,void,(GLenum target, GLuint texture)) +GL_PROC(base_opengl,glTexEnvi,WINGDIAPI,void,(GLenum target, GLenum pname, GLint param)) +GL_PROC(base_opengl,glTexParameterf,WINGDIAPI,void,(GLenum target, GLenum pname, GLfloat param)) +GL_PROC(base_opengl,glTexParameteri,WINGDIAPI,void,(GLenum target, GLenum pname, GLint param)) +GL_PROC(base_opengl,glTexImage2D,WINGDIAPI,void,(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)) +GL_PROC(base_opengl,glTexSubImage2D,WINGDIAPI,void,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)) +GL_PROC(base_opengl,glGenTextures,WINGDIAPI,void,(GLsizei n, GLuint *textures)) +GL_PROC(base_opengl,glDeleteTextures,WINGDIAPI,void,(GLsizei n, const GLuint *textures)) +GL_PROC(base_opengl,glVertexPointer,WINGDIAPI,void,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +GL_PROC(base_opengl,glColorPointer,WINGDIAPI,void,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +GL_PROC(base_opengl,glTexCoordPointer,WINGDIAPI,void,(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)) +GL_PROC(base_opengl,glDrawArrays,WINGDIAPI,void,(GLenum mode, GLint first, GLsizei count)) +GL_PROC(base_opengl,glDrawElements,WINGDIAPI,void,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)) +GL_PROC(base_opengl,glEnableClientState,WINGDIAPI,void,(GLenum array)) +GL_PROC(base_opengl,glFinish,WINGDIAPI,void,(void)) +GL_PROC(base_opengl,glReadPixels,WINGDIAPI,void,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)) + +// GL_EXT_framebuffer_object ... +GL_PROC(GL_EXT_framebuffer_object,glBindRenderbufferEXT,,void,(GLenum target, GLuint name)) +GL_PROC(GL_EXT_framebuffer_object,glDeleteRenderbuffersEXT,,void,(GLsizei, const GLuint *)) +GL_PROC(GL_EXT_framebuffer_object,glGenRenderbuffersEXT,,void,(GLsizei, GLuint *)) +GL_PROC(GL_EXT_framebuffer_object,glRenderbufferStorageEXT,,void,(GLenum, GLenum, GLsizei, GLsizei)) +GL_PROC(GL_EXT_framebuffer_object,glBindFramebufferEXT,,void,(GLenum, GLuint)) +GL_PROC(GL_EXT_framebuffer_object,glDeleteFramebuffersEXT,,void,(GLsizei, const GLuint *)) +GL_PROC(GL_EXT_framebuffer_object,glGenFramebuffersEXT,,void,(GLsizei, GLuint *)) +GL_PROC(GL_EXT_framebuffer_object,glCheckFramebufferStatusEXT,,GLenum,(GLenum)) +GL_PROC(GL_EXT_framebuffer_object,glFramebufferRenderbufferEXT,,void,(GLenum, GLenum, GLenum, GLuint)) +GL_PROC(GL_EXT_framebuffer_object,glFramebufferTexture2DEXT,,void,(GLenum, GLenum, GLenum, GLuint, GLint)) + +// GL_ARB_vertex_buffer_object ... +GL_PROC(GL_ARB_vertex_buffer_object,glBindBufferARB,,void,(GLenum, GLuint)) +GL_PROC(GL_ARB_vertex_buffer_object,glDeleteBuffersARB,,void,(GLsizei, const GLuint *)) +GL_PROC(GL_ARB_vertex_buffer_object,glGenBuffersARB,,void,(GLsizei, GLuint *)) +GL_PROC(GL_ARB_vertex_buffer_object,glBufferDataARB,,void,(GLenum, GLsizeiptr, const GLvoid *, GLenum)) +GL_PROC(GL_ARB_vertex_buffer_object,glMapBufferARB,,GLvoid*,(GLenum, GLenum)) +GL_PROC(GL_ARB_vertex_buffer_object,glUnmapBufferARB,,GLboolean,(GLenum)) + +// end of hge_glfuncs.h ... + diff --git a/archive/hge/hge_impl.h b/archive/hge/hge_impl.h new file mode 100644 index 0000000..bf42c2f --- /dev/null +++ b/archive/hge/hge_impl.h @@ -0,0 +1,416 @@ +// -*- C++ -*- +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Common core implementation header +*/ + +#ifndef HGE_IMPL_UNIX_H +#define HGE_IMPL_UNIX_H +#include "unix_compat.h" + +#include "hge.h" +#include <stdio.h> +#include <dirent.h> +#include "SDL/SDL.h" + +#define GL_GLEXT_LEGACY 1 +#include "gl.h" + +#ifndef WINGDIAPI +#define WINGDIAPI +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif + +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif + +#define GL_PROC(ext,fn,call,ret,params) typedef call ret (APIENTRYP _HGE_PFN_##fn) params; +#include "hge_glfuncs.h" +#undef GL_PROC + +class COpenGLDevice +{ +public: + #define GL_PROC(ext,fn,call,ret,params) _HGE_PFN_##fn fn; + #include "hge_glfuncs.h" + #undef GL_PROC + + GLenum TextureTarget; // texture rectangle vs (npot) 2D. + bool have_base_opengl; + bool have_GL_ARB_texture_rectangle; + bool have_GL_ARB_texture_non_power_of_two; + bool have_GL_EXT_framebuffer_object; + bool have_GL_EXT_texture_compression_s3tc; + bool have_GL_ARB_vertex_buffer_object; + bool have_GL_APPLE_ycbcr_422; +}; + + +#define VERTEX_BUFFER_SIZE 4000 + + +struct gltexture; // used internally. + +struct CRenderTargetList +{ + int width; + int height; + HTEXTURE tex; + GLuint depth; + GLuint frame; + CRenderTargetList* next; +}; + +struct CTextureList +{ + HTEXTURE tex; + int width; + int height; + CTextureList* next; +}; + +struct CResourceList +{ + char filename[_MAX_PATH]; + char password[64]; + CResourceList* next; +}; + +struct CStreamList +{ + HSTREAM hstream; + void* data; + CStreamList* next; +}; + +struct CInputEventList +{ + hgeInputEvent event; + CInputEventList* next; +}; + + +void DInit(); +void DDone(); +bool DFrame(); + + +/* +** HGE Interface implementation +*/ +class HGE_Impl : public HGE +{ +public: + virtual void CALL Release(); + + virtual bool CALL System_Initiate(); + virtual void CALL System_Shutdown(); + virtual bool CALL System_Start(); + virtual void CALL System_SetStateBool (hgeBoolState state, bool value); + virtual void CALL System_SetStateFunc (hgeFuncState state, hgeCallback value); + virtual void CALL System_SetStateHwnd (hgeHwndState state, HWND value); + virtual void CALL System_SetStateInt (hgeIntState state, int value); + virtual void CALL System_SetStateString(hgeStringState state, const char *value); + virtual bool CALL System_GetStateBool (hgeBoolState ); + virtual hgeCallback CALL System_GetStateFunc (hgeFuncState ); + virtual HWND CALL System_GetStateHwnd (hgeHwndState ); + virtual int CALL System_GetStateInt (hgeIntState ); + virtual const char* CALL System_GetStateString(hgeStringState); + virtual const char* CALL System_GetErrorMessage(); + virtual void CALL System_Log(const char *format, ...); + virtual bool CALL System_Launch(const char *url); + virtual void CALL System_Snapshot(const char *filename=0); + + virtual void* CALL Resource_Load(const char *filename, DWORD *size=0); + virtual void CALL Resource_Free(void *res); + virtual bool CALL Resource_AttachPack(const char *filename, const char *password=0); + virtual void CALL Resource_RemovePack(const char *filename); + virtual void CALL Resource_RemoveAllPacks(); + virtual char* CALL Resource_MakePath(const char *filename=0); + virtual char* CALL Resource_EnumFiles(const char *wildcard=0); + virtual char* CALL Resource_EnumFolders(const char *wildcard=0); + + virtual void CALL Ini_SetInt(const char *section, const char *name, int value); + virtual int CALL Ini_GetInt(const char *section, const char *name, int def_val); + virtual void CALL Ini_SetFloat(const char *section, const char *name, float value); + virtual float CALL Ini_GetFloat(const char *section, const char *name, float def_val); + virtual void CALL Ini_SetString(const char *section, const char *name, const char *value); + virtual char* CALL Ini_GetString(const char *section, const char *name, const char *def_val); + + virtual void CALL Random_Seed(int seed=0); + virtual int CALL Random_Int(int min, int max); + virtual float CALL Random_Float(float min, float max); + + virtual float CALL Timer_GetTime(); + virtual float CALL Timer_GetDelta(); + virtual int CALL Timer_GetFPS(); + virtual float CALL Timer_GetFPSf(); + + virtual HEFFECT CALL Effect_Load(const char *filename, DWORD size=0); + virtual void CALL Effect_Free(HEFFECT eff); + virtual HCHANNEL CALL Effect_Play(HEFFECT eff); + virtual HCHANNEL CALL Effect_PlayEx(HEFFECT eff, float volume=1.0, float pan=0.0, float pitch=1.0f, bool loop=false); + + virtual HMUSIC CALL Music_Load(const char *filename, DWORD size=0); + virtual void CALL Music_Free(HMUSIC mus); + virtual HCHANNEL CALL Music_Play(HMUSIC mus, bool loop, int volume = 100, int order = 0, int row = 0); + virtual void CALL Music_SetAmplification(HMUSIC music, int ampl); + virtual int CALL Music_GetAmplification(HMUSIC music); + virtual int CALL Music_GetLength(HMUSIC music); + virtual void CALL Music_SetPos(HMUSIC music, int order, int row); + virtual bool CALL Music_GetPos(HMUSIC music, int *order, int *row); + virtual void CALL Music_SetInstrVolume(HMUSIC music, int instr, int volume); + virtual int CALL Music_GetInstrVolume(HMUSIC music, int instr); + virtual void CALL Music_SetChannelVolume(HMUSIC music, int channel, int volume); + virtual int CALL Music_GetChannelVolume(HMUSIC music, int channel); + + virtual HSTREAM CALL Stream_Load(const char *filename, DWORD size=0); + virtual void CALL Stream_Free(HSTREAM stream); + virtual HCHANNEL CALL Stream_Play(HSTREAM stream, bool loop, int volume = 100); + + virtual void CALL Channel_SetPanning(HCHANNEL chn, float pan); + virtual void CALL Channel_SetVolume(HCHANNEL chn, float volume); + virtual void CALL Channel_SetPitch(HCHANNEL chn, float pitch); + virtual void CALL Channel_Pause(HCHANNEL chn); + virtual void CALL Channel_Resume(HCHANNEL chn); + virtual void CALL Channel_Stop(HCHANNEL chn); + virtual void CALL Channel_PauseAll(); + virtual void CALL Channel_ResumeAll(); + virtual void CALL Channel_StopAll(); + virtual bool CALL Channel_IsPlaying(HCHANNEL chn); + virtual float CALL Channel_GetLength(HCHANNEL chn); + virtual float CALL Channel_GetPos(HCHANNEL chn); + virtual void CALL Channel_SetPos(HCHANNEL chn, float fSeconds); + virtual int CALL Channel_GetPos_BySample(HCHANNEL chn); + virtual void CALL Channel_SetPos_BySample(HCHANNEL chn, int iSample); + virtual void CALL Channel_SlideTo(HCHANNEL channel, float time, int volume, int pan = -101, float pitch = -1); + virtual bool CALL Channel_IsSliding(HCHANNEL channel); + + virtual void CALL Input_GetMousePos(float *x, float *y); + virtual void CALL Input_SetMousePos(float x, float y); + virtual int CALL Input_GetMouseWheel(); + virtual bool CALL Input_IsMouseOver(); + virtual bool CALL Input_KeyDown(int key); + virtual bool CALL Input_KeyUp(int key); + virtual bool CALL Input_GetKeyState(int key); + virtual int CALL Input_GetKeyStateEx(int key); + virtual const char* CALL Input_GetKeyName(int key); + virtual int CALL Input_GetKey(); + virtual int CALL Input_GetChar(); + virtual bool CALL Input_GetEvent(hgeInputEvent *event); + + virtual bool CALL Gfx_BeginScene(HTARGET target=0); + virtual void CALL Gfx_EndScene(); + virtual void CALL Gfx_Clear(DWORD color); + virtual void CALL Gfx_RenderLine(float x1, float y1, float x2, float y2, DWORD color=0xFFFFFFFF, float z=0.5f); + virtual void CALL Gfx_RenderTriple(const hgeTriple *triple); + virtual void CALL Gfx_RenderQuad(const hgeQuad *quad); + virtual hgeVertex* CALL Gfx_StartBatch(int prim_type, HTEXTURE tex, int blend, int *max_prim); + virtual void CALL Gfx_FinishBatch(int nprim); + virtual void CALL Gfx_SetClipping(int x=0, int y=0, int w=0, int h=0); + virtual void CALL Gfx_SetTransform(float x=0, float y=0, float dx=0, float dy=0, float rot=0, float hscale=0, float vscale=0); + + virtual HTARGET CALL Target_Create(int width, int height, bool zbuffer); + virtual void CALL Target_Free(HTARGET target); + virtual HTEXTURE CALL Target_GetTexture(HTARGET target); + + virtual HTEXTURE CALL Texture_Create(int width, int height); + virtual HTEXTURE CALL Texture_Load(const char *filename, DWORD size=0, bool bMipmap=false); + virtual void CALL Texture_Free(HTEXTURE tex); + virtual int CALL Texture_GetWidth(HTEXTURE tex, bool bOriginal=false); + virtual int CALL Texture_GetHeight(HTEXTURE tex, bool bOriginal=false); + virtual DWORD* CALL Texture_Lock(HTEXTURE tex, bool bReadOnly=true, int left=0, int top=0, int width=0, int height=0); + virtual void CALL Texture_Unlock(HTEXTURE tex); + + bool CALL HGEEXT_Texture_PushYUV422(HTEXTURE tex, const BYTE *yuv); + + //////// Implementation //////// + + static HGE_Impl* _Interface_Get(); + void _FocusChange(bool bAct); + void _PostError(const char *error); + + // ini ... + void _LoadIniFile(const char *fname); + const char* _BuildProfilePath(const char *section, const char *name, const char *szIniFile); + bool _WritePrivateProfileString(const char *section, const char *name, const char *buf, const char *szIniFile); + bool _GetPrivateProfileString(const char *section, const char *name, const char *deflt, char *buf, size_t bufsize, const char *szIniFile); + + long MacOSXVersion; + HWND hwnd; + bool bActive; + char szError[256]; + char szAppPath[_MAX_PATH]; + char szIniString[256]; + + + // System States + bool (*procFrameFunc)(); + bool (*procRenderFunc)(); + bool (*procFocusLostFunc)(); + bool (*procFocusGainFunc)(); + bool (*procGfxRestoreFunc)(); + bool (*procExitFunc)(); + const char* szIcon; + char szWinTitle[256]; + int nScreenWidth; + int nScreenHeight; + int nOrigScreenWidth; + int nOrigScreenHeight; + int nScreenBPP; + bool bWindowed; + bool bVsync; + bool bZBuffer; + bool bTextureFilter; + char szIniFile[_MAX_PATH]; + char szLogFile[_MAX_PATH]; + bool bUseSound; + int nSampleRate; + int nFXVolume; + int nMusVolume; + int nStreamVolume; + int nHGEFPS; + bool bHideMouse; + bool bDontSuspend; + HWND hwndParent; + bool bForceTextureCompression; + GLuint IndexBufferObject; + + bool _PrimsOutsideClipping(const hgeVertex *v, const int verts); + bool bTransforming; + int clipX; + int clipY; + int clipW; + int clipH; + +// #ifdef DEMO + bool bDMO; +// #endif + + + // Power + int nPowerStatus; + + void _InitPowerStatus(); + void _UpdatePowerStatus(); + void _DonePowerStatus(); + + + // Graphics + COpenGLDevice* pOpenGLDevice; // GL entry points, dynamically loaded. + hgeVertex* pVB; // vertex buffer is a client-side array in the OpenGL renderer. + GLushort* pIB; // index buffer is a client-side array in the OpenGL renderer. + + CRenderTargetList* pTargets; + CRenderTargetList* pCurTarget; + + //D3DXMATRIX matView; + //D3DXMATRIX matProj; + + CTextureList* textures; + hgeVertex* VertArray; + + int nPrim; + int CurPrimType; + int CurBlendMode; + HTEXTURE CurTexture; + + bool _HaveOpenGLExtension(const char *extlist, const char *ext); + void _UnloadOpenGLEntryPoints(); + bool _LoadOpenGLEntryPoints(); + + bool _GfxInit(); + void _GfxDone(); + bool _GfxRestore(); + void _AdjustWindow(); + void _Resize(int width, int height); + bool _init_lost(); + void _render_batch(bool bEndScene=false); + void _SetTextureFilter(); + void _ConfigureTexture(gltexture *t, int width, int height, DWORD *pixels); + void _BindTexture(gltexture *t); + bool _BuildTarget(CRenderTargetList *pTarget, GLuint texname, int width, int height, bool zbuffer); + HTEXTURE _BuildTexture(int width, int height, DWORD *pixels); + //int _format_id(D3DFORMAT fmt); + void _SetBlendMode(int blend); + void _SetProjectionMatrix(int width, int height); + int _flipSDLSurface(int pitch, int height, void* image_pixels); + + + // Audio + void* hBass; + void* hOpenAL; + bool bSilent; + CStreamList* streams; + bool _SoundInit(); + void _SoundDone(); + void _SetMusVolume(int vol); + void _SetStreamVolume(int vol); + void _SetFXVolume(int vol); + + + // Input + int VKey; + int Char; + int Zpos; + float Xpos; + float Ypos; + SDLMod keymods; + bool bMouseOver; + bool bCaptured; + char keyz[256]; + bool keylast[256]; + CInputEventList* queue; + void _UpdateMouse(); + void _InputInit(); + void _ClearQueue(); + void _BuildEvent(int type, int key, int scan, int flags, int x, int y); + bool _ProcessSDLEvent(const SDL_Event &e); + + // Resources + char szTmpFilename[_MAX_PATH]; + CResourceList* res; + + bool _WildcardMatch(const char *str, const char *wildcard); + bool _PrepareFileEnum(const char *wildcard); + char* _DoEnumIteration(const bool wantdir); + DIR* hSearch; + char szSearchDir[_MAX_PATH]; + char szSearchWildcard[_MAX_PATH]; + char szSearchResult[_MAX_PATH]; + + // Timer + float fTime; + float fDeltaTime; + float fUpdateFPSDelay; + float nFPSf; + DWORD nFixedDelta; + int nFPS; + int Fcnt; + DWORD t0, t0fps, dt; + int cfps; + + +private: + HGE_Impl(); + + #if PLATFORM_MACOSX + void _MacMinimizeWindow(); + void _MacHideOtherWindows(); + void _MacHideWindow(); + #endif +}; + +extern HGE_Impl* pHGE; + +#endif // include-once blocker + +// end of hg_impl_unix.h ... + diff --git a/archive/hge/ini.cpp b/archive/hge/ini.cpp new file mode 100644 index 0000000..6fed586 --- /dev/null +++ b/archive/hge/ini.cpp @@ -0,0 +1,196 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: unix ini file +*/ + +#include "hge_impl.h" + +const char *HGE_Impl::_BuildProfilePath(const char *section, const char *name, const char *szIniFile) +{ + // !!! FIXME: not efficient. + static char path[_MAX_PATH]; + const char *home = getenv("HOME"); + strcpy(path, home); + mkdir(path, S_IRWXU); + + #if PLATFORM_MACOSX + strcat(path, "/Library"); + mkdir(path, S_IRWXU); + strcat(path, "/Application Support"); + mkdir(path, S_IRWXU); + strcat(path, "/"); + strcat(path, szWinTitle); + mkdir(path, S_IRWXU); + #else + strcat(path, "/."); + strcat(path, szWinTitle); + mkdir(path, S_IRWXU); + #endif + + strcat(path, "/inis"); + mkdir(path, S_IRWXU); + + strcat(path, "/"); + strcat(path, szIniFile); + mkdir(path, S_IRWXU); + strcat(path, "/"); + strcat(path, section); + mkdir(path, S_IRWXU); + strcat(path, "/"); + strcat(path, name); + + return path; +} + +bool HGE_Impl::_WritePrivateProfileString(const char *section, const char *name, const char *buf, const char *szIniFile) +{ + const char *path = _BuildProfilePath(section, name, szIniFile); + FILE *io = fopen(path, "wb"); + if (io == NULL) + return false; + const size_t rc = fwrite(buf, strlen(buf), 1, io); + if (fclose(io) == EOF) + return false; + return (rc == 1); +} + +bool HGE_Impl::_GetPrivateProfileString(const char *section, const char *name, const char *deflt, char *buf, size_t bufsize, const char *szIniFile) +{ + bool retval = false; + const char *path = _BuildProfilePath(section, name, szIniFile); + FILE *io = fopen(path, "rb"); + if (io != NULL) + { + const size_t rc = fread(buf, 1, bufsize-1, io); + retval = (ferror(io) == 0); + fclose(io); + if (retval) + buf[rc] = '\0'; + } + + if (!retval) + snprintf(buf, bufsize, "%s", deflt); + + return retval; +} + +// We parse the usual .ini files, and build them into our directory tree when items don't exist. +// !!! FIXME: this code sort of stinks. In fact, the whole directory tree thing could be a mistake... +void HGE_Impl::_LoadIniFile(const char *fname) +{ + char section[128] = { 0 }; + struct stat statbuf; + if (stat(fname, &statbuf) == -1) + return; + FILE *io = fopen(fname, "rb"); + char *buf = new char[statbuf.st_size + 1]; + size_t rc = fread(buf, statbuf.st_size, 1, io); + buf[statbuf.st_size] = '\0'; + fclose(io); + if (rc == 1) + { + char *start = buf; + char *ptr = start; + while (start <= (buf + statbuf.st_size)) + { + while ((*ptr != '\r') && (*ptr != '\n') && (*ptr != '\0')) + ptr++; + *ptr = '\0'; + + while ((*start == ' ') || (*start == '\t') || (*start == '\r') || (*start == '\n')) + start++; + + if ((*start == ';') || (*start == '\0')) // comment or empty line. + ; + else if (*start == '[') // section + { + start++; + char *end = strchr(start, ']'); + if (end != NULL) + { + *end = '\0'; + snprintf(section, sizeof (section), "%s", start); + } + } + else if (section[0] != '\0') + { + char *eq = strchr(start, '='); + if (eq != NULL) + { + *eq = '\0'; + eq++; + char tmpbuf[128]; + if (!_GetPrivateProfileString(section, start, "", tmpbuf, sizeof (tmpbuf), fname)) + _WritePrivateProfileString(section, start, eq, fname); + } + } + ptr++; + start = ptr; + } + } + delete[] buf; +} + +void CALL HGE_Impl::Ini_SetInt(const char *section, const char *name, int value) +{ + char buf[256]; + + if(szIniFile[0]) { + sprintf(buf,"%d",value); + _WritePrivateProfileString(section, name, buf, szIniFile); + } +} + + +int CALL HGE_Impl::Ini_GetInt(const char *section, const char *name, int def_val) +{ + char buf[256]; + + if(szIniFile[0]) { + if(_GetPrivateProfileString(section, name, "", buf, sizeof(buf), szIniFile)) + { return atoi(buf); } + else { return def_val; } + } + return def_val; +} + + +void CALL HGE_Impl::Ini_SetFloat(const char *section, const char *name, float value) +{ + char buf[256]; + + if(szIniFile[0]) { + sprintf(buf,"%f",value); + _WritePrivateProfileString(section, name, buf, szIniFile); + } +} + + +float CALL HGE_Impl::Ini_GetFloat(const char *section, const char *name, float def_val) +{ + char buf[256]; + + if(szIniFile[0]) { + if(_GetPrivateProfileString(section, name, "", buf, sizeof(buf), szIniFile)) + { return (float)atof(buf); } + else { return def_val; } + } + return def_val; +} + + +void CALL HGE_Impl::Ini_SetString(const char *section, const char *name, const char *value) +{ + if(szIniFile[0]) _WritePrivateProfileString(section, name, value, szIniFile); +} + + +char* CALL HGE_Impl::Ini_GetString(const char *section, const char *name, const char *def_val) +{ + if(szIniFile[0]) _GetPrivateProfileString(section, name, def_val, szIniString, sizeof(szIniString), szIniFile); + else strcpy(szIniString, def_val); + return szIniString; +} diff --git a/archive/hge/input.cpp b/archive/hge/input.cpp new file mode 100644 index 0000000..2710c7f --- /dev/null +++ b/archive/hge/input.cpp @@ -0,0 +1,363 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: input +*/ + + +#include "hge_impl.h" + +const char *KeyNames[] = +{ + "?", + "Left Mouse Button", "Right Mouse Button", "?", "Middle Mouse Button", + "?", "?", "?", "Backspace", "Tab", "?", "?", "?", "Enter", "?", "?", + "Shift", "Ctrl", "Alt", "Pause", "Caps Lock", "?", "?", "?", "?", "?", "?", + "Escape", "?", "?", "?", "?", + "Space", "Page Up", "Page Down", "End", "Home", + "Left Arrow", "Up Arrow", "Right Arrow", "Down Arrow", + "?", "?", "?", "?", "Insert", "Delete", "?", + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "?", "?", "?", "?", "?", "?", "?", + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", + "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", + "Left Win", "Right Win", "Application", "?", "?", + "NumPad 0", "NumPad 1", "NumPad 2", "NumPad 3", "NumPad 4", + "NumPad 5", "NumPad 6", "NumPad 7", "NumPad 8", "NumPad 9", + "Multiply", "Add", "?", "Subtract", "Decimal", "Divide", + "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "Num Lock", "Scroll Lock", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "Semicolon", "Equals", "Comma", "Minus", "Period", "Slash", "Grave", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "?", "?", "?", "?", "?", "?", + "Left bracket", "Backslash", "Right bracket", "Apostrophe", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", + "?", "?", "?" +}; + + +static int SDLKeyToHGEKey(const int sdlkey) +{ + switch (sdlkey) + { + case SDLK_ESCAPE: return HGEK_ESCAPE; + case SDLK_BACKSPACE: return HGEK_BACKSPACE; + case SDLK_TAB: return HGEK_TAB; + case SDLK_RETURN: return HGEK_ENTER; + case SDLK_SPACE: return HGEK_SPACE; + case SDLK_LSHIFT: return HGEK_SHIFT; + case SDLK_RSHIFT: return HGEK_SHIFT; + case SDLK_LCTRL: return HGEK_CTRL; + case SDLK_RCTRL: return HGEK_CTRL; + case SDLK_LALT: return HGEK_ALT; + case SDLK_RALT: return HGEK_ALT; + case SDLK_LMETA: return HGEK_LWIN; + case SDLK_RMETA: return HGEK_RWIN; + //case SDLK_APPS: return HGEK_APPS; + case SDLK_PAUSE: return HGEK_PAUSE; + case SDLK_CAPSLOCK: return HGEK_CAPSLOCK; + case SDLK_NUMLOCK: return HGEK_NUMLOCK; + case SDLK_SCROLLOCK: return HGEK_SCROLLLOCK; + case SDLK_PAGEUP: return HGEK_PGUP; + case SDLK_PAGEDOWN: return HGEK_PGDN; + case SDLK_HOME: return HGEK_HOME; + case SDLK_END: return HGEK_END; + case SDLK_INSERT: return HGEK_INSERT; + case SDLK_DELETE: return HGEK_DELETE; + case SDLK_LEFT: return HGEK_LEFT; + case SDLK_UP: return HGEK_UP; + case SDLK_RIGHT: return HGEK_RIGHT; + case SDLK_DOWN: return HGEK_DOWN; + case SDLK_0: return HGEK_0; + case SDLK_1: return HGEK_1; + case SDLK_2: return HGEK_2; + case SDLK_3: return HGEK_3; + case SDLK_4: return HGEK_4; + case SDLK_5: return HGEK_5; + case SDLK_6: return HGEK_6; + case SDLK_7: return HGEK_7; + case SDLK_8: return HGEK_8; + case SDLK_9: return HGEK_9; + case SDLK_a: return HGEK_A; + case SDLK_b: return HGEK_B; + case SDLK_c: return HGEK_C; + case SDLK_d: return HGEK_D; + case SDLK_e: return HGEK_E; + case SDLK_f: return HGEK_F; + case SDLK_g: return HGEK_G; + case SDLK_h: return HGEK_H; + case SDLK_i: return HGEK_I; + case SDLK_j: return HGEK_J; + case SDLK_k: return HGEK_K; + case SDLK_l: return HGEK_L; + case SDLK_m: return HGEK_M; + case SDLK_n: return HGEK_N; + case SDLK_o: return HGEK_O; + case SDLK_p: return HGEK_P; + case SDLK_q: return HGEK_Q; + case SDLK_r: return HGEK_R; + case SDLK_s: return HGEK_S; + case SDLK_t: return HGEK_T; + case SDLK_u: return HGEK_U; + case SDLK_v: return HGEK_V; + case SDLK_w: return HGEK_W; + case SDLK_x: return HGEK_X; + case SDLK_y: return HGEK_Y; + case SDLK_z: return HGEK_Z; + //case SDLK_GRAVE: return HGEK_GRAVE; + case SDLK_MINUS: return HGEK_MINUS; + case SDLK_EQUALS: return HGEK_EQUALS; + case SDLK_BACKSLASH: return HGEK_BACKSLASH; + case SDLK_LEFTBRACKET: return HGEK_LBRACKET; + case SDLK_RIGHTBRACKET: return HGEK_RBRACKET; + case SDLK_SEMICOLON: return HGEK_SEMICOLON; + case SDLK_QUOTE: return HGEK_APOSTROPHE; + case SDLK_COMMA: return HGEK_COMMA; + case SDLK_PERIOD: return HGEK_PERIOD; + case SDLK_SLASH: return HGEK_SLASH; + case SDLK_KP0: return HGEK_NUMPAD0; + case SDLK_KP1: return HGEK_NUMPAD1; + case SDLK_KP2: return HGEK_NUMPAD2; + case SDLK_KP3: return HGEK_NUMPAD3; + case SDLK_KP4: return HGEK_NUMPAD4; + case SDLK_KP5: return HGEK_NUMPAD5; + case SDLK_KP6: return HGEK_NUMPAD6; + case SDLK_KP7: return HGEK_NUMPAD7; + case SDLK_KP8: return HGEK_NUMPAD8; + case SDLK_KP9: return HGEK_NUMPAD9; + case SDLK_KP_MULTIPLY: return HGEK_MULTIPLY; + case SDLK_KP_DIVIDE: return HGEK_DIVIDE; + case SDLK_KP_PLUS: return HGEK_ADD; + case SDLK_KP_MINUS: return HGEK_SUBTRACT; + case SDLK_KP_PERIOD: return HGEK_DECIMAL; + case SDLK_F1: return HGEK_F1; + case SDLK_F2: return HGEK_F2; + case SDLK_F3: return HGEK_F3; + case SDLK_F4: return HGEK_F4; + case SDLK_F5: return HGEK_F5; + case SDLK_F6: return HGEK_F6; + case SDLK_F7: return HGEK_F7; + case SDLK_F8: return HGEK_F8; + case SDLK_F9: return HGEK_F9; + case SDLK_F10: return HGEK_F10; + case SDLK_F11: return HGEK_F11; + case SDLK_F12: return HGEK_F12; + default: return -1; + } + + return -1; +} + + +bool CALL HGE_Impl::Input_GetEvent(hgeInputEvent *event) +{ + CInputEventList *eptr; + + if(queue) + { + eptr=queue; + memcpy(event, &eptr->event, sizeof(hgeInputEvent)); + queue=eptr->next; + delete eptr; + return true; + } + + return false; +} + +void CALL HGE_Impl::Input_GetMousePos(float *x, float *y) +{ + *x=Xpos; *y=Ypos; +} + + +void CALL HGE_Impl::Input_SetMousePos(float x, float y) +{ + SDL_WarpMouse(x, y); +} + +int CALL HGE_Impl::Input_GetMouseWheel() +{ + return Zpos; +} + +bool CALL HGE_Impl::Input_IsMouseOver() +{ + return bMouseOver; +} + +bool CALL HGE_Impl::Input_GetKeyState(int key) +{ + return (keyz[key] & 4) != 0; +} + +int CALL HGE_Impl::Input_GetKeyStateEx(int key)//New function +{ + if (!Input_GetKeyState(key)&&keylast[key])return HGEKST_RELEASE; + if (!Input_GetKeyState(key))return HGEKST_NONE; + if (Input_GetKeyState(key)&&!keylast[key])return HGEKST_HIT; + return HGEKST_KEEP; +} + +bool CALL HGE_Impl::Input_KeyDown(int key) +{ + return (keyz[key] & 1) != 0; +} + +bool CALL HGE_Impl::Input_KeyUp(int key) +{ + return (keyz[key] & 2) != 0; +} + +const char* CALL HGE_Impl::Input_GetKeyName(int key) +{ + return KeyNames[key]; +} + +int CALL HGE_Impl::Input_GetKey() +{ + return VKey; +} + +int CALL HGE_Impl::Input_GetChar() +{ + return Char; +} + + +//////// Implementation //////// + + +void HGE_Impl::_InputInit() +{ + Xpos = 0; // eh. + Ypos = 0; + memset(&keyz, 0, sizeof(keyz)); +} + +void HGE_Impl::_UpdateMouse() +{ + // no-op. +} + + +void HGE_Impl::_BuildEvent(int type, int key, int scan, int flags, int x, int y) +{ + CInputEventList *last, *eptr=new CInputEventList; + + eptr->event.type=type; + eptr->event.chr=0; + int ptx=x; + int pty=y; + + if(type==INPUT_KEYDOWN) + { + key = SDLKeyToHGEKey(key); + if ( (key < 0) || (key > (int)(sizeof (keyz) / sizeof (keyz[0]))) ) return; + keyz[key] |= 4; + if((flags & HGEINP_REPEAT) == 0) keyz[key] |= 1; + eptr->event.chr = (char) ((key >= 32) && (key <= 127)) ? key : 0; // these map to ASCII in sdl. + } + if(type==INPUT_KEYUP) + { + key = SDLKeyToHGEKey(key); + if ( (key < 0) || (key > (int)(sizeof (keyz) / sizeof (keyz[0]))) ) return; + keyz[key] &= ~4; + keyz[key] |= 2; + eptr->event.chr = (char) ((key >= 32) && (key <= 127)) ? key : 0; // these map to ASCII in sdl. + } + if(type==INPUT_MOUSEWHEEL) + { + eptr->event.key=0; eptr->event.wheel=key; + } + else { eptr->event.key=key; eptr->event.wheel=0; } + + if(type==INPUT_MBUTTONDOWN) + { + keyz[key] |= 1; + keyz[key] |= 4; + //SetCapture(hwnd); + bCaptured=true; + } + if(type==INPUT_MBUTTONUP) + { + keyz[key] |= 2; + keyz[key] &= ~4; + //ReleaseCapture(); + //Input_SetMousePos(Xpos, Ypos); + ptx=(int)Xpos; pty=(int)Ypos; + bCaptured=false; + } + + if(keymods & KMOD_SHIFT) flags|=HGEINP_SHIFT; + if(keymods & KMOD_CTRL) flags|=HGEINP_CTRL; + if(keymods & KMOD_ALT) flags|=HGEINP_ALT; + if(keymods & KMOD_CAPS) flags|=HGEINP_CAPSLOCK; + if(keymods & KMOD_MODE) flags|=HGEINP_SCROLLLOCK; + if(keymods & KMOD_NUM) flags|=HGEINP_NUMLOCK; + eptr->event.flags=flags; + + if(ptx==-1) { eptr->event.x=Xpos;eptr->event.y=Ypos; } + else + { + if(ptx<0) ptx=0; + if(pty<0) pty=0; + if(ptx>=nScreenWidth) ptx=nScreenWidth-1; + if(pty>=nScreenHeight) pty=nScreenHeight-1; + + eptr->event.x=(float)ptx; + eptr->event.y=(float)pty; + } + + eptr->next=0; + + if(!queue) queue=eptr; + else + { + last=queue; + while(last->next) last=last->next; + last->next=eptr; + } + + if(eptr->event.type==INPUT_KEYDOWN || eptr->event.type==INPUT_MBUTTONDOWN) + { + VKey=eptr->event.key;Char=eptr->event.chr; + } + else if(eptr->event.type==INPUT_MOUSEMOVE) + { + Xpos=eptr->event.x;Ypos=eptr->event.y; + } + else if(eptr->event.type==INPUT_MOUSEWHEEL) + { + Zpos+=eptr->event.wheel; + } +} + +void HGE_Impl::_ClearQueue() +{ + CInputEventList *nexteptr, *eptr=queue; + + //memset(&keyz, 0, sizeof(keyz)); + for (int i = 0; i < (int)(sizeof (keyz) / sizeof (keyz[0])); i++) + keyz[i] &= ~3; // only reset some of the bits. + + while(eptr) + { + nexteptr=eptr->next; + delete eptr; + eptr=nexteptr; + } + + queue=0; VKey=0; Char=0; Zpos=0; +} diff --git a/archive/hge/power.cpp b/archive/hge/power.cpp new file mode 100644 index 0000000..eabeeaa --- /dev/null +++ b/archive/hge/power.cpp @@ -0,0 +1,25 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: power status +*/ +//DO NOT USE THIS, USE "acpi". + +#include "hge_impl.h" + +void HGE_Impl::_InitPowerStatus() +{ + nPowerStatus = HGEPWR_UNSUPPORTED; +} + +void HGE_Impl::_UpdatePowerStatus() +{ + nPowerStatus = HGEPWR_UNSUPPORTED; +} + +void HGE_Impl::_DonePowerStatus() +{ + nPowerStatus = HGEPWR_UNSUPPORTED; +} diff --git a/archive/hge/random.cpp b/archive/hge/random.cpp new file mode 100644 index 0000000..ab9956a --- /dev/null +++ b/archive/hge/random.cpp @@ -0,0 +1,31 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: random number generation +*/ + + +#include "hge_impl.h" + +unsigned int g_seed=0; + +void CALL HGE_Impl::Random_Seed(int seed) +{ + if(!seed) g_seed=timeGetTime(); + else g_seed=seed; +} + +int CALL HGE_Impl::Random_Int(int min, int max) +{ + g_seed=214013*g_seed+2531011; + return min+(g_seed ^ g_seed>>15)%(max-min+1); +} + +float CALL HGE_Impl::Random_Float(float min, float max) +{ + g_seed=214013*g_seed+2531011; + //return min+g_seed*(1.0f/4294967295.0f)*(max-min); + return min+(g_seed>>16)*(1.0f/65535.0f)*(max-min); +} diff --git a/archive/hge/resource.cpp b/archive/hge/resource.cpp new file mode 100644 index 0000000..4937ee1 --- /dev/null +++ b/archive/hge/resource.cpp @@ -0,0 +1,394 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: resources management +*/ + +#include "hge_impl.h" + +#include <zlib.h> // the system version is better here. HGE's is out of date. + +#define NOCRYPT +//#define NOUNCRYPT +#include "ZLIB/unzip.h" + + +bool CALL HGE_Impl::Resource_AttachPack(const char *filename, const char *password) +{ + char *szName; + CResourceList *resItem=res; + unzFile zip; + + szName=Resource_MakePath(filename); + + while(resItem) + { + if(!strcmp(szName,resItem->filename)) return false; + resItem=resItem->next; + } + + zip=unzOpen(szName); + if(!zip) { + System_Log("Unable to unzip: %s", szName); + return false; + } + unzClose(zip); + + resItem=new CResourceList; + strcpy(resItem->filename, szName); + if(password) strcpy(resItem->password, password); + else resItem->password[0]=0; + resItem->next=res; + res=resItem; + + return true; +} + +void CALL HGE_Impl::Resource_RemovePack(const char *filename) +{ + char *szName; + CResourceList *resItem=res, *resPrev=0; + + szName=Resource_MakePath(filename); + + while(resItem) + { + if(!strcmp(szName,resItem->filename)) + { + if(resPrev) resPrev->next=resItem->next; + else res=resItem->next; + delete resItem; + break; + } + + resPrev=resItem; + resItem=resItem->next; + } +} + +void CALL HGE_Impl::Resource_RemoveAllPacks() +{ + CResourceList *resItem=res, *resNextItem; + + while(resItem) + { + resNextItem=resItem->next; + delete resItem; + resItem=resNextItem; + } + + res=0; +} + +void* CALL HGE_Impl::Resource_Load(const char *filename, DWORD *size) +{ + const char *res_err="Can't load resource: %s"; + + CResourceList *resItem=res; + char szName[_MAX_PATH]; + char szZipName[_MAX_PATH]; + unzFile zip; + unz_file_info file_info; + int done, i; + void *ptr; + FILE *hF; + + if(filename[0]=='\\' || filename[0]=='/' || filename[1]==':') goto _fromfile; // skip absolute paths + + // Load from pack + + strcpy(szName,filename); + for(i=0; szName[i]; i++) { if(szName[i]=='/') szName[i]='\\'; } + + while(resItem) + { + zip=unzOpen(resItem->filename); + done=unzGoToFirstFile(zip); + while(done==UNZ_OK) + { + unzGetCurrentFileInfo(zip, &file_info, szZipName, sizeof(szZipName), NULL, 0, NULL, 0); + for(i=0; szZipName[i]; i++) { if(szZipName[i]=='/') szZipName[i]='\\'; } + if(!strcmp(szName,szZipName)) + { + if(unzOpenCurrentFilePassword(zip, resItem->password[0] ? resItem->password : 0) != UNZ_OK) + { + unzClose(zip); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + ptr = malloc(file_info.uncompressed_size); + if(!ptr) + { + unzCloseCurrentFile(zip); + unzClose(zip); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + if(unzReadCurrentFile(zip, ptr, file_info.uncompressed_size) < 0) + { + unzCloseCurrentFile(zip); + unzClose(zip); + free(ptr); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + unzCloseCurrentFile(zip); + unzClose(zip); + if(size) *size=file_info.uncompressed_size; + return ptr; + } + + done=unzGoToNextFile(zip); + } + + unzClose(zip); + resItem=resItem->next; + } + + // Load from file +_fromfile: + + hF = fopen(Resource_MakePath(filename), "rb"); + if(hF == NULL) + { + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + struct stat statbuf; + if (fstat(fileno(hF), &statbuf) == -1) + { + fclose(hF); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + file_info.uncompressed_size = statbuf.st_size; + ptr = malloc(file_info.uncompressed_size); + if(!ptr) + { + fclose(hF); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + if(fread(ptr, file_info.uncompressed_size, 1, hF) != 1) + { + fclose(hF); + free(ptr); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + fclose(hF); + + if(size) *size=file_info.uncompressed_size; + return ptr; +} + + +void CALL HGE_Impl::Resource_Free(void *res) +{ + if(res) free(res); +} + +// this is from PhysicsFS originally ( http://icculus.org/physfs/ ) +// (also zlib-licensed.) +static int locateOneElement(char *buf) +{ + char *ptr = NULL; + DIR *dirp = NULL; + struct dirent *dent = NULL; + + if (access(buf, F_OK) == 0) + return 1; /* quick rejection: exists in current case. */ + + ptr = strrchr(buf, '/'); /* find entry at end of path. */ + if (ptr == NULL) + { + dirp = opendir("."); + ptr = buf; + } + else + { + *ptr = '\0'; + dirp = opendir(buf); + *ptr = '/'; + ptr++; /* point past dirsep to entry itself. */ + } + + while ((dent = readdir(dirp)) != NULL) + { + if (strcasecmp(dent->d_name, ptr) == 0) + { + strcpy(ptr, dent->d_name); /* found a match. Overwrite with this case. */ + closedir(dirp); + return 1; + } + } + + /* no match at all... */ + closedir(dirp); + return 0; +} + +static int locateCorrectCase(char *buf) +{ + char *ptr = buf; + + while ((ptr = strchr(ptr + 1, '/'))) + { + *ptr = '\0'; /* block this path section off */ + if (!locateOneElement(buf)) + { + *ptr = '/'; /* restore path separator */ + return -2; /* missing element in path. */ + } + *ptr = '/'; /* restore path separator */ + } + + /* check final element... */ + return locateOneElement(buf) ? 0 : -1; +} + +char* CALL HGE_Impl::Resource_MakePath(const char *filename) +{ + int i; + + if(!filename) + strcpy(szTmpFilename, szAppPath); + else if(filename[0]=='\\' || filename[0]=='/' || filename[1]==':') + strcpy(szTmpFilename, filename); + else + { + strcpy(szTmpFilename, szAppPath); + if(filename) strcat(szTmpFilename, filename); + } + + for(i=0; szTmpFilename[i]; i++) { if(szTmpFilename[i]=='\\') szTmpFilename[i]='/'; } + + locateCorrectCase(szTmpFilename); + + return szTmpFilename; +} + +// !!! FIXME: kinda messy, and probably doesn't get all the corner cases right. +bool HGE_Impl::_WildcardMatch(const char *str, const char *wildcard) +{ + if ((str == NULL) || (wildcard == NULL)) + return false; + + while ((*str) && (*wildcard)) + { + const char wildch = *wildcard; + const char strch = *str; + if (wildch == '?') + ; // okay. + else if (wildch == '*') + { + do { + wildcard++; + } while (((*wildcard == '*') || (*wildcard == '?')) && (*wildcard != '\0')); + const char newwild = *wildcard; + if (newwild == '\0') return true; + const char *ptr = str; + while (*ptr) // find the greediest match possible... + { + if (*ptr == newwild) + str = ptr; + ptr++; + } + } + else if ( (toupper(strch)) != (toupper(wildch)) ) + { + return false; + } + + str++; + wildcard++; + } + + while (*wildcard == '*') + wildcard++; + + return ((*str == '\0') && (*wildcard == '\0')); +} + +bool HGE_Impl::_PrepareFileEnum(const char *wildcard) +{ + if(hSearch) { closedir(hSearch); hSearch=0; } + char *madepath = Resource_MakePath(wildcard); + const char *fname = strrchr(madepath, '/'); + const char *dir = NULL; + if (fname == NULL) { + dir = "."; + fname = madepath; + } else { + dir = madepath; + char *ptr = (char *) fname; + *ptr = '\0'; // split dir and filename. + fname++; + } + + strcpy(szSearchDir, dir); + strcpy(szSearchWildcard, fname); + + hSearch=opendir(dir); + return (hSearch!=0); +} + +char *HGE_Impl::_DoEnumIteration(const bool wantdir) +{ + if(!hSearch) return 0; + while (true) + { + struct dirent *dent = readdir(hSearch); + if(dent == NULL) { closedir(hSearch); hSearch=0; return 0; } + if ((strcmp(dent->d_name, ".") == 0) || (strcmp(dent->d_name, "..") == 0)) + continue; + if (!_WildcardMatch(dent->d_name, szSearchWildcard)) + continue; + char fullpath[_MAX_PATH]; + snprintf(fullpath, sizeof (fullpath), "%s/%s", szSearchDir, dent->d_name); + struct stat statbuf; + if (stat(fullpath, &statbuf) == -1) // this follows symlinks. + continue; + const bool isdir = ((S_ISDIR(statbuf.st_mode)) != 0); + if (isdir == wantdir) // this treats pipes, devs, etc, as "files" ... + { + strcpy(szSearchResult, dent->d_name); + return szSearchResult; + } + } + return 0; +} + +char* CALL HGE_Impl::Resource_EnumFiles(const char *wildcard) +{ + if(wildcard) + { + if (!_PrepareFileEnum(wildcard)) + return 0; + } + return _DoEnumIteration(false); +} + +char* CALL HGE_Impl::Resource_EnumFolders(const char *wildcard) +{ + if(wildcard) + { + if (!_PrepareFileEnum(wildcard)) + return 0; + } + return _DoEnumIteration(true); +} diff --git a/archive/hge/sound.cpp b/archive/hge/sound.cpp new file mode 100644 index 0000000..9024652 --- /dev/null +++ b/archive/hge/sound.cpp @@ -0,0 +1,531 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: audio routines +*/ + + +// This is just enough to get Hammerfight working without using libBA$$. +// If you want a full HGE audio implementation, you should either use the +// code in sound_libbass.cpp (and maybe pay for a BA$$ licen$e), or improve +// this code. +// Well, this code is now improved by Chris Xiong, adding several new interfaces. +// (Such as seeking in sample...) +// Channel functions are fully supported now. However music and streaming are +// still not supported. Some APIs changed for OpenAL is different from BA$$. + +#include "hge_impl.h" + +#include "AL/al.h" +#include "AL/alc.h" +#include "AL/alext.h" +#include "ogg/ogg.h" +#include "vorbis/vorbisfile.h" +static const char* SOUND_SRC_FN="hge/sound.cpp"; +struct oggcbdata +{ + const BYTE *data; + DWORD size; + DWORD pos; +}; + +static size_t oggcb_read(void *ptr, size_t size, size_t nmemb, void *datasource) +{ + oggcbdata *data = (oggcbdata *) datasource; + const DWORD avail = data->size - data->pos; + size_t want = nmemb * size; + if (want > avail) + want = avail - (avail % size); + if (want > 0) + { + memcpy(ptr, data->data + data->pos, want); + data->pos += want; + } + return want / size; +} + +static int oggcb_seek(void *datasource, ogg_int64_t offset, int whence) +{ + oggcbdata *data = (oggcbdata *) datasource; + ogg_int64_t pos = 0; + switch (whence) + { + case SEEK_SET: pos = offset; break; + case SEEK_CUR: pos = ((ogg_int64_t) data->pos) + offset; break; + case SEEK_END: pos = ((ogg_int64_t) data->size) + offset; break; + default: return -1; + } + + if ( (pos < 0) || (pos > ((ogg_int64_t) data->size)) ) + return -1; + + data->pos = (DWORD) pos; + return 0; +} + +static int oggcb_close(void *datasource) +{ + return 0; +} + +static long oggcb_tell(void *datasource) +{ + oggcbdata *data = (oggcbdata *) datasource; + return (long) data->pos; +} + +static ov_callbacks oggcb = { oggcb_read, oggcb_seek, oggcb_close, oggcb_tell }; + +static void *decompress_vorbis(const BYTE *data, const DWORD size, ALsizei *decompressed_size, ALenum *fmt, ALsizei *freq) +{ +#ifdef __POWERPC__ + const int bigendian = 1; +#else + const int bigendian = 0; +#endif + + oggcbdata cbdata = { data, size, 0 }; + OggVorbis_File vf; + memset(&vf, '\0', sizeof (vf)); + if (ov_open_callbacks(&cbdata, &vf, NULL, 0, oggcb) == 0) + { + int bitstream = 0; + vorbis_info *info = ov_info(&vf, -1); + + *decompressed_size = 0; + *fmt = (info->channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; + *freq = info->rate; + + if ((info->channels != 1) && (info->channels != 2)) + { + ov_clear(&vf); + return NULL; + } + + char buf[1024 * 16]; + long rc = 0; + size_t allocated = 64 * 1024; + BYTE *retval = (ALubyte *) malloc(allocated); + while ( (rc = ov_read(&vf, buf, sizeof (buf), bigendian, 2, 1, &bitstream)) != 0 ) + { + if (rc > 0) + { + *decompressed_size += rc; + if ((unsigned)*decompressed_size >= allocated) + { + allocated *= 2; + ALubyte *tmp = (ALubyte *) realloc(retval, allocated); + if (tmp == NULL) + { + free(retval); + retval = NULL; + break; + } + retval = tmp; + } + memcpy(retval + (*decompressed_size - rc), buf, rc); + } + } + ov_clear(&vf); + return retval; + } + + return NULL; +} + +#define MAX_SIDS 128 +static int sidcount = 0; +static ALuint sids[MAX_SIDS]; + +static ALuint get_source() +{ + for (int i = 0; i < sidcount; i++) + { + ALint state = AL_PLAYING; + alGetSourceiv(sids[i], AL_SOURCE_STATE, &state); + if ((state != AL_PLAYING) && (state != AL_PAUSED)) + return sids[i]; + } + if (sidcount >= MAX_SIDS) + return 0; + + ALuint sid = 0; + alGenSources(1, &sid); + if (sid == 0) + return 0; + sids[sidcount++] = sid; + return sid; +} + + +HEFFECT CALL HGE_Impl::Effect_Load(const char *filename, DWORD size) +{ + DWORD _size; + void *data; + + if(hOpenAL) + { + if(bSilent) return 1; + + if(size) { data=(void *)filename; _size=size; } + else + { + data=Resource_Load(filename, &_size); + if(!data) return 0; + } + + const BYTE *magic = (const BYTE *) data; + const bool isOgg = ( (_size > 4) && + (magic[0] == 'O') && (magic[1] == 'g') && + (magic[2] == 'g') && (magic[3] == 'S') ); + if (!isOgg) + { + if(!size) Resource_Free(data); + return 0; + } + void *allocation_decompressed = NULL; + void *decompressed = NULL; + ALsizei decompressed_size = 0; + ALsizei freq = 0; + ALenum fmt = AL_FORMAT_STEREO16; + if (isOgg) + { + /*if (alIsExtensionPresent((const ALchar *) "AL_EXT_vorbis"))//useless + { + fmt = alGetEnumValue((const ALchar *) "AL_FORMAT_VORBIS_EXT"); + decompressed = data; + decompressed_size = _size; + } + else + {*/ + allocation_decompressed = decompress_vorbis((const BYTE *) data, _size, &decompressed_size, &fmt, &freq); + decompressed = allocation_decompressed; + //} + } + + ALuint bid = 0; + alGenBuffers(1, &bid); + alBufferData(bid, fmt, decompressed, decompressed_size, freq); + free(allocation_decompressed); // not delete[] ! + if(!size) Resource_Free(data); + return (HEFFECT) bid; + } + else return 0; +} + +HCHANNEL CALL HGE_Impl::Effect_Play(HEFFECT eff) +{ + return Effect_PlayEx(eff, 1.0f, 0, 1.0f, false); +} + +HCHANNEL CALL HGE_Impl::Effect_PlayEx(HEFFECT eff, float volume, float pan, float pitch, bool loop) +{ + if(hOpenAL) + { + const ALuint sid = get_source(); // find an unused sid, or generate a new one. + if (sid != 0) + { + if (volume < 0) volume = 0; else if (volume > 1.0) volume = 1.0; + if (pan < -1.0) pan = -1.0; else if (pan > 1.0) pan = 1.0; + alSourceStop(sid); + alSourcei(sid, AL_BUFFER, (ALint) eff); + alSourcef(sid, AL_GAIN, volume); + alSourcef(sid, AL_PITCH, pitch); + alSource3f(sid, AL_POSITION, pan, 0.0f, 0.0f); + alSourcei(sid, AL_LOOPING, loop ? AL_TRUE : AL_FALSE); + alSourcePlay(sid); + } + return sid; + } + else return 0; +} + +void CALL HGE_Impl::Effect_Free(HEFFECT eff) +{ + if(hOpenAL) + { + ALuint bid = (ALuint) eff; + alDeleteBuffers(1, &bid); + } +} +//Castrate!! +HMUSIC CALL HGE_Impl::Music_Load(const char *filename, DWORD size){return 0;} + +HCHANNEL CALL HGE_Impl::Music_Play(HMUSIC mus, bool loop, int volume, int order, int row){return 0;} + +void CALL HGE_Impl::Music_Free(HMUSIC mus){} + +void CALL HGE_Impl::Music_SetAmplification(HMUSIC music, int ampl){} + +int CALL HGE_Impl::Music_GetAmplification(HMUSIC music){return -1;} + +int CALL HGE_Impl::Music_GetLength(HMUSIC music){return -1;} + +void CALL HGE_Impl::Music_SetPos(HMUSIC music, int order, int row){} + +bool CALL HGE_Impl::Music_GetPos(HMUSIC music, int *order, int *row){return false;} + +void CALL HGE_Impl::Music_SetInstrVolume(HMUSIC music, int instr, int volume){} + +int CALL HGE_Impl::Music_GetInstrVolume(HMUSIC music, int instr){return -1;} + +void CALL HGE_Impl::Music_SetChannelVolume(HMUSIC music, int channel, int volume){} + +int CALL HGE_Impl::Music_GetChannelVolume(HMUSIC music, int channel){return -1;} + +HSTREAM CALL HGE_Impl::Stream_Load(const char *filename, DWORD size){return 0;} + +void CALL HGE_Impl::Stream_Free(HSTREAM stream){} + +HCHANNEL CALL HGE_Impl::Stream_Play(HSTREAM stream, bool loop, int volume){return 0;} + +void CALL HGE_Impl::Channel_SetPanning(HCHANNEL chn, float pan) +{ + if(pan>1.0)pan=1.0; + if(pan<-1.0)pan=-1.0; + if(hOpenAL) + { + alSource3f((ALuint) chn, AL_POSITION, pan, 0.0f, 0.0f); + } +} + +void CALL HGE_Impl::Channel_SetVolume(HCHANNEL chn, float volume) +{ + if(hOpenAL) + { + if (volume < 0) volume = 0; else if (volume > 1.0f) volume = 1.0f; + alSourcef((ALuint) chn, AL_GAIN, volume); + } +} + +void CALL HGE_Impl::Channel_SetPitch(HCHANNEL chn, float pitch) +{ + if(hOpenAL) + { + alSourcef((ALuint) chn, AL_PITCH, pitch); + } +} + +void CALL HGE_Impl::Channel_Pause(HCHANNEL chn) +{ + if(hOpenAL) + { + alSourcePause((ALuint) chn); + } +} + +void CALL HGE_Impl::Channel_Resume(HCHANNEL chn) +{ + if(hOpenAL) + { + alSourcePlay((ALuint) chn); + } +} + +void CALL HGE_Impl::Channel_Stop(HCHANNEL chn) +{ + if(hOpenAL) + { + alSourceStop((ALuint) chn); + } +} + +void CALL HGE_Impl::Channel_PauseAll() +{ + if(hOpenAL) + { + ALCcontext *ctx = alcGetCurrentContext(); + alcSuspendContext(ctx); + } +} + +void CALL HGE_Impl::Channel_ResumeAll() +{ + if(hOpenAL) + { + ALCcontext *ctx = alcGetCurrentContext(); + alcProcessContext(ctx); + } +} + +void CALL HGE_Impl::Channel_StopAll() +{ + if(hOpenAL) + { + for (int i = 0; i < sidcount; i++) + alSourceStop(sids[i]); + } +} + +bool CALL HGE_Impl::Channel_IsPlaying(HCHANNEL chn) +{ + if(hOpenAL) + { + ALint state = AL_STOPPED; + alGetSourceiv((ALuint) chn, AL_SOURCE_STATE, &state); + return state == AL_PLAYING; + } + else return false; +} +//The following features are ported to OpenAL by Chris +float CALL HGE_Impl::Channel_GetLength(HCHANNEL chn) +//WARNING!!:In OpenAL We pass HEFFECT insteat HCHANNEL in! +//This should be fixed. +{ + //Well, you developers should know this "by heart". + if (hOpenAL) + { + ALint sizeInBytes; + ALint channels; + ALint bits; + ALuint bufferID=chn; + alGetBufferi(bufferID, AL_SIZE, &sizeInBytes); + alGetBufferi(bufferID, AL_CHANNELS, &channels); + alGetBufferi(bufferID, AL_BITS, &bits); + int lengthInSamples = sizeInBytes * 8 / (channels * bits); + ALint frequency; + alGetBufferi(bufferID, AL_FREQUENCY, &frequency); + float durationInSeconds = (float)lengthInSamples / (float)frequency; + return durationInSeconds; + } + return -1; +} + +float CALL HGE_Impl::Channel_GetPos(HCHANNEL chn) +{ + if (hOpenAL) + { + ALfloat res; + alGetSourcef((ALuint)chn,AL_SEC_OFFSET,&res); + return (float)res; + } + else return -1.0f; +} + +void CALL HGE_Impl::Channel_SetPos(HCHANNEL chn, float fSeconds) +{ + if (hOpenAL) + { + alSourcef((ALuint)chn,AL_SEC_OFFSET,(ALfloat)fSeconds); + } +} + +int CALL HGE_Impl::Channel_GetPos_BySample(HCHANNEL chn) +{ + if (hOpenAL) + { + ALint res; + alGetSourcei((ALuint)chn,AL_SAMPLE_OFFSET,&res); + return (int)res; + } + else return -1; +} + +void CALL HGE_Impl::Channel_SetPos_BySample(HCHANNEL chn, int iSample) +{ + if (hOpenAL) + { + alSourcei((ALuint)chn,AL_SAMPLE_OFFSET,(ALint)iSample); + } +} + +void CALL HGE_Impl::Channel_SlideTo(HCHANNEL channel, float time, int volume, int pan, float pitch){} + +bool CALL HGE_Impl::Channel_IsSliding(HCHANNEL channel){return false;} + + +//////// Implementation //////// + + +bool HGE_Impl::_SoundInit() +{ + if(!bUseSound || hOpenAL) return true; + + bSilent=false; + + sidcount = 0; + memset(sids, '\0', sizeof (sids)); + + System_Log("%s: Starting OpenAL init",SOUND_SRC_FN); + + ALCdevice *dev = alcOpenDevice(NULL); + if (!dev) + { + System_Log("%s: alcOpenDevice(NULL) failed, using no sound",SOUND_SRC_FN); + bSilent=true; + return true; + } + + ALint caps[] = { ALC_FREQUENCY, nSampleRate, 0 }; + ALCcontext *ctx = alcCreateContext(dev, caps); + if (!ctx) + { + alcCloseDevice(dev); + System_Log("%s: alcCreateContext(NULL) failed, using no sound",SOUND_SRC_FN); + bSilent=true; + return true; + } + + alcMakeContextCurrent(ctx); + alcProcessContext(ctx); + + System_Log("%s: OpenAL initialized successfully.",SOUND_SRC_FN); + System_Log("%s: AL_VENDOR: %s",SOUND_SRC_FN, (char *) alGetString(AL_VENDOR)); + System_Log("%s: AL_RENDERER: %s",SOUND_SRC_FN, (char *) alGetString(AL_RENDERER)); + System_Log("%s: AL_VERSION: %s",SOUND_SRC_FN,(char *) alGetString(AL_VERSION)); + System_Log("%s: AL_EXTENSIONS: %s",SOUND_SRC_FN,(char *) alGetString(AL_EXTENSIONS)); + + hOpenAL = (void *) 0x1; // something non-NULL (!!! FIXME: this should eventually be a library handle). + + _SetFXVolume(nFXVolume); + //_SetMusVolume(nMusVolume); + //_SetStreamVolume(nStreamVolume); + + return true; +} + +void HGE_Impl::_SoundDone() +{ + CStreamList *stmItem=streams, *stmNext; + + if(hOpenAL) + { + for (int i = 0; i < sidcount; i++) + alSourceStop(sids[i]); + alDeleteSources(sidcount, sids); + sidcount = 0; + memset(sids, '\0', sizeof (sids)); + + ALCcontext *ctx = alcGetCurrentContext(); + ALCdevice *dev = alcGetContextsDevice(ctx); + alcMakeContextCurrent(NULL); + alcSuspendContext(ctx); + alcDestroyContext(ctx); + alcCloseDevice(dev); + + hOpenAL=0; + + while(stmItem) + { + stmNext=stmItem->next; + Resource_Free(stmItem->data); + delete stmItem; + stmItem=stmNext; + } + streams=0; + } +} + +void HGE_Impl::_SetMusVolume(int vol){} + +void HGE_Impl::_SetStreamVolume(int vol){} + +void HGE_Impl::_SetFXVolume(int vol) +{ + if(hOpenAL) + { + alListenerf(AL_GAIN, ((ALfloat) vol) / 100.0f); + } +} diff --git a/archive/hge/system.cpp b/archive/hge/system.cpp new file mode 100644 index 0000000..b32783b --- /dev/null +++ b/archive/hge/system.cpp @@ -0,0 +1,933 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core system functions for Unix. +*/ + + +#include "hge_impl.h" + +#if PLATFORM_MACOSX +#include <Carbon/Carbon.h> +#include <sys/types.h> +#include <sys/sysctl.h> +#endif + +#define LOWORDINT(n) ((int)((signed short)(LOWORD(n)))) +#define HIWORDINT(n) ((int)((signed short)(HIWORD(n)))) +static const char* SYSTEM_SRC_FN="hge/system.cpp"; +int nRef=0; +HGE_Impl* pHGE=0; + +HGE* CALL hgeCreate(int ver) +{ + if(ver==HGE_VERSION) + return (HGE*)HGE_Impl::_Interface_Get(); + else + return 0; +} + + +HGE_Impl* HGE_Impl::_Interface_Get() +{ + if(!pHGE) pHGE=new HGE_Impl(); + + nRef++; + + return pHGE; +} + + +void CALL HGE_Impl::Release() +{ + nRef--; + + if(!nRef) + { + if(pHGE->hwnd) pHGE->System_Shutdown(); + Resource_RemoveAllPacks(); + delete pHGE; + pHGE=0; + } +} + + +bool CALL HGE_Impl::System_Initiate() +{ + + // Log system info + + System_Log("%s: HGE Started...",SYSTEM_SRC_FN); + + System_Log("%s: hge-unix version: %X.%X", SYSTEM_SRC_FN, HGE_VERSION>>8, HGE_VERSION & 0xFF); + + time_t t = time(NULL); + System_Log("%s: Date: %s",SYSTEM_SRC_FN, asctime(localtime(&t))); + + System_Log("%s: Application: %s",SYSTEM_SRC_FN,szWinTitle); + + MacOSXVersion = 0x0000; + +#if PLATFORM_MACOSX + SInt32 ver = 0x0000; + char verbuf[16] = { '\0' }; + if (Gestalt(gestaltSystemVersion, &ver) == noErr) + { + SInt32 macver_minor = ((ver & 0xF0) >> 4); + SInt32 macver_patch = (ver & 0xF); + SInt32 macver_major = ((ver & 0xFF00) >> 8); + macver_major = (((macver_major / 16) * 10) + (macver_major % 16)); + MacOSXVersion = ver; + if (ver >= 0x1030) + { + Gestalt(gestaltSystemVersionMajor, &macver_major); + Gestalt(gestaltSystemVersionMinor, &macver_minor); + Gestalt(gestaltSystemVersionBugFix, &macver_patch); + } + snprintf(verbuf, sizeof (verbuf), "%d.%d.%d", + (int) macver_major, (int) macver_minor, (int) macver_patch); + } + + System_Log("OS: Mac OS X%s", verbuf); + + unsigned long phys = 0; + size_t len = sizeof (phys); + int mib[2] = { CTL_HW, HW_PHYSMEM }; + if ((sysctl(mib, 2, &phys, &len, NULL, 0) != 0) || (len != sizeof (phys))) + phys = 0; // oh well. + phys /= 1024; + System_Log("Memory: %ldK total",phys); + + // !!! FIXME: we shouldn't force this here, really, but the game I'm working + // !!! FIXME: on eats _hundreds_ of megabytes of texture memory. You'll basically + // !!! FIXME: lock the system up, swapping, if you don't force s3tc on low-memory boxes... + bForceTextureCompression = false; //((phys/1024) <= 512); + if (bForceTextureCompression) + { + System_Log("WARNING: we'll have to force texture compression for this system."); + System_Log("WARNING: adding more memory will make the game look better!"); + } + +#else + system("uname -svm > os.out"); + char osv[100];FILE* a=fopen("os.out","r");fgets(osv,50,a);fclose(a); + osv[strlen(osv)-1]='\0'; + System_Log("%s: OS: %s",SYSTEM_SRC_FN,osv); + system("rm os.out"); + a=fopen("/proc/meminfo","r"); + unsigned totalm,freem; + fscanf(a,"MemTotal: %d kB\n",&totalm); + fscanf(a,"MemFree: %d kB\n",&freem); + System_Log("%s: Memory: %ukB total, %ukB free\n",SYSTEM_SRC_FN,totalm,freem); + fclose(a); +#endif + + if (SDL_Init(SDL_INIT_VIDEO) == -1) { + char buffer[1024]; + snprintf(buffer, sizeof (buffer), "%s: SDL_Init() failed: %s\n",SYSTEM_SRC_FN,SDL_GetError()); + _PostError(buffer); + return false; + } + + if (SDL_GL_LoadLibrary(NULL) == -1) { + char buffer[1024]; + snprintf(buffer, sizeof (buffer), "%s: SDL_GL_LoadLibrary() failed: %s\n",SYSTEM_SRC_FN,SDL_GetError()); + _PostError(buffer); + SDL_Quit(); + return false; + } + + const SDL_VideoInfo *vidinfo = SDL_GetVideoInfo(); + nOrigScreenWidth = vidinfo->current_w; + nOrigScreenHeight = vidinfo->current_h; + System_Log("%s: Screen: %dx%d\n",SYSTEM_SRC_FN,nOrigScreenWidth,nOrigScreenHeight); + + // Create window + SDL_WM_SetCaption(szWinTitle, szWinTitle); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, nScreenBPP >= 32 ? 8 : 4); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, nScreenBPP >= 32 ? 8 : 4); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, nScreenBPP >= 32 ? 8 : 4); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, nScreenBPP >= 32 ? 8 : 4); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, bZBuffer ? 16 : 0); + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, bVsync ? 1 : 0); + Uint32 flags = SDL_OPENGL; + if (!bWindowed) + flags |= SDL_FULLSCREEN; + hwnd = SDL_SetVideoMode(nScreenWidth, nScreenHeight, nScreenBPP, flags); + if (!hwnd) + { + char buffer[1024]; + snprintf(buffer, sizeof (buffer), "SDL_SetVideoMode() failed: %s\n", SDL_GetError()); + _PostError(buffer); + SDL_Quit(); + return false; + } + + if (!bWindowed) + { + bMouseOver = true; + if (!pHGE->bActive) + pHGE->_FocusChange(true); + } + + SDL_ShowCursor(bHideMouse ? SDL_DISABLE : SDL_ENABLE); + +#if !PLATFORM_MACOSX + SDL_Surface *icon = SDL_LoadBMP("hgeicon.bmp"); // HACK. + if (icon) + { + SDL_SetColorKey(icon, SDL_SRCCOLORKEY, SDL_MapRGB(icon->format, 255, 0, 255)); + SDL_WM_SetIcon(icon, NULL); + SDL_FreeSurface(icon); + } +#endif + + // Init subsystems + + Random_Seed(); + _InitPowerStatus(); + _InputInit(); + if(!_GfxInit()) { System_Shutdown(); return false; } + if(!_SoundInit()) { System_Shutdown(); return false; } + + System_Log("%s: Init done.\n",SYSTEM_SRC_FN); + + fTime=0.0f; + t0=t0fps=SDL_GetTicks(); + dt=cfps=0; + nFPS=0; + nFPSf=0.0f; + Fcnt=0; + fUpdateFPSDelay=0.0f; + + // Show splash + +//#ifdef DEMO + + bool (*func)(); + bool (*rfunc)(); + HWND hwndTmp; + + if(/*pHGE->bDMO*/true) + { + SDL_Delay(200); + func=(bool(*)())pHGE->System_GetStateFunc(HGE_FRAMEFUNC); + rfunc=(bool(*)())pHGE->System_GetStateFunc(HGE_RENDERFUNC); + hwndTmp=hwndParent; hwndParent=0; + pHGE->System_SetStateFunc(HGE_FRAMEFUNC, DFrame); + pHGE->System_SetStateFunc(HGE_RENDERFUNC, 0); + DInit(); + pHGE->System_Start(); + DDone(); + hwndParent=hwndTmp; + pHGE->System_SetStateFunc(HGE_FRAMEFUNC, func); + pHGE->System_SetStateFunc(HGE_RENDERFUNC, rfunc); + } + +//#endif + + // Done + + return true; +} + +void CALL HGE_Impl::System_Shutdown() +{ + System_Log("\n%s: Closing session..",SYSTEM_SRC_FN); + + if(hSearch) { closedir(hSearch); hSearch=0; } + _ClearQueue(); + _SoundDone(); + _GfxDone(); + _DonePowerStatus(); + + SDL_Quit(); + hwnd=0; + + System_Log("%s: Session ended.",SYSTEM_SRC_FN); +} + + +bool CALL HGE_Impl::System_Start() +{ + if(!hwnd) + { + _PostError("System_Start: System_Initiate wasn't called"); + return false; + } + + if(!procFrameFunc) { + _PostError("System_Start: No frame function defined"); + return false; + } + + bActive=true; + + // MAIN LOOP + for(;;) + { + SDL_Event e; + bool keep_going = true; + while (SDL_PollEvent(&e) && keep_going) + keep_going = _ProcessSDLEvent(e); + + if (!keep_going) + break; + + // Check if mouse is over HGE window for Input_IsMouseOver + + _UpdateMouse(); + + // If HGE window is focused or we have the "don't suspend" state - process the main loop + + if(bActive || bDontSuspend) + { + Uint32 sdlticks; + // Ensure we have at least 1ms time step + // to not confuse user's code with 0 + + do { sdlticks=SDL_GetTicks(); dt = sdlticks - t0; } while(dt < 1); + + // If we reached the time for the next frame + // or we just run in unlimited FPS mode, then + // do the stuff + + if(dt >= nFixedDelta) + { + // fDeltaTime = time step in seconds returned by Timer_GetDelta + + fDeltaTime=dt/1000.0f; + + // Cap too large time steps usually caused by lost focus to avoid jerks + + if(fDeltaTime > 0.2f) + { + fDeltaTime = nFixedDelta ? nFixedDelta/1000.0f : 0.01f; + } + + // Update time counter returned Timer_GetTime + + fTime += fDeltaTime; + + // Store current time for the next frame + // and count FPS + + t0=sdlticks; + if(t0-t0fps <= 1000) cfps++; + else + { + nFPS=cfps; cfps=0; t0fps=t0; + _UpdatePowerStatus(); + } + ++Fcnt;fUpdateFPSDelay+=fDeltaTime; + if(fUpdateFPSDelay>1) + { + nFPSf=Fcnt/fUpdateFPSDelay; + fUpdateFPSDelay=0.0f; + Fcnt=0; + } + + // Do user's stuff + + if(procFrameFunc()) break; + if(procRenderFunc) procRenderFunc(); + + // If if "child mode" - return after processing single frame + + if(hwndParent) break; + + // Clean up input events that were generated by + // WindowProc and weren't handled by user's code + for (int i=1;i<=255;++i) + keylast[i]=Input_GetKeyState(i); + _ClearQueue(); + + // If we use VSYNC - we could afford a little + // sleep to lower CPU usage + + // if(!bWindowed && nHGEFPS==HGEFPS_VSYNC) Sleep(1); + } + + // If we have a fixed frame rate and the time + // for the next frame isn't too close, sleep a bit + + else + { + if(nFixedDelta && dt+3 < nFixedDelta) SDL_Delay(1); + } + } + + // If main loop is suspended - just sleep a bit + // (though not too much to allow instant window + // redraw if requested by OS) + + else SDL_Delay(1); + } + + _ClearQueue(); + + bActive=false; + + return true; +} + +void CALL HGE_Impl::System_SetStateBool(hgeBoolState state, bool value) +{ + switch(state) + { + case HGE_WINDOWED: if(VertArray || hwndParent) break; + if(pOpenGLDevice && bWindowed != value) + { + STUBBED("backbuffer format"); + //if(d3dppW.BackBufferFormat==D3DFMT_UNKNOWN || d3dppFS.BackBufferFormat==D3DFMT_UNKNOWN) break; + + bWindowed=value; + + //if(_format_id(d3dpp->BackBufferFormat) < 4) nScreenBPP=16; + //else nScreenBPP=32; + + Uint32 flags = SDL_OPENGL; + if (!bWindowed) + flags |= SDL_FULLSCREEN; + hwnd = SDL_SetVideoMode(nScreenWidth, nScreenHeight, nScreenBPP, flags); + _GfxRestore(); + if (!bWindowed) + { + bMouseOver = true; + if (!pHGE->bActive) + pHGE->_FocusChange(true); + } + } + else bWindowed=value; + break; + + case HGE_ZBUFFER: if(!pOpenGLDevice) bZBuffer=value; + break; + + case HGE_TEXTUREFILTER: if (bTextureFilter==value) break; + if(pOpenGLDevice) + _render_batch(); + bTextureFilter=value; + _SetTextureFilter(); + break; + + case HGE_USESOUND: if(bUseSound!=value) + { + bUseSound=value; + if(bUseSound) _SoundInit(); + if(!bUseSound) _SoundDone(); + } + break; + + case HGE_HIDEMOUSE: bHideMouse=value; if (pHGE->hwnd) SDL_ShowCursor(bHideMouse ? SDL_DISABLE : SDL_ENABLE); break; + + case HGE_DONTSUSPEND: bDontSuspend=value; break; + + #ifdef DEMO + case HGE_SHOWSPLASH: bDMO=value; break; + #endif + default:break; + } +} + +void CALL HGE_Impl::System_SetStateFunc(hgeFuncState state, hgeCallback value) +{ + switch(state) + { + case HGE_FRAMEFUNC: procFrameFunc=value; break; + case HGE_RENDERFUNC: procRenderFunc=value; break; + case HGE_FOCUSLOSTFUNC: procFocusLostFunc=value; break; + case HGE_FOCUSGAINFUNC: procFocusGainFunc=value; break; + case HGE_GFXRESTOREFUNC: procGfxRestoreFunc=value; break; + case HGE_EXITFUNC: procExitFunc=value; break; + default:break; + } +} + +void CALL HGE_Impl::System_SetStateHwnd(hgeHwndState state, HWND value) +{ + switch(state) + { + case HGE_HWNDPARENT: + if (value != 0) { + System_Log("WARNING: Trying to set HGE_HWNDPARENT is unsupported!\n"); + System_Log("WARNING: You will not get the behaviour you expect\n"); + } + if(!hwnd) + hwndParent=value; + break; + default:break; + } +} + +void CALL HGE_Impl::System_SetStateInt(hgeIntState state, int value) +{ + switch(state) + { + case HGE_SCREENWIDTH: if(!pOpenGLDevice) nScreenWidth=value; break; + + case HGE_SCREENHEIGHT: if(!pOpenGLDevice) nScreenHeight=value; break; + + case HGE_SCREENBPP: if(!pOpenGLDevice) nScreenBPP=value; break; + + case HGE_SAMPLERATE: if((!hOpenAL) && (!hBass)) nSampleRate=value; + break; + + case HGE_FXVOLUME: nFXVolume=value; + _SetFXVolume(nFXVolume); + break; + + case HGE_MUSVOLUME: nMusVolume=value; + _SetMusVolume(nMusVolume); + break; + + case HGE_STREAMVOLUME: nStreamVolume=value; + _SetStreamVolume(nStreamVolume); + break; + + case HGE_FPS: bVsync = (value==HGEFPS_VSYNC); + if(pOpenGLDevice) SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, bVsync ? 1 : 0); + nHGEFPS=value; + if(nHGEFPS>0) nFixedDelta=int(1000.0f/value); + else nFixedDelta=0; + break; + default:break; + } +} + +void CALL HGE_Impl::System_SetStateString(hgeStringState state, const char *value) +{ + FILE *hf; + + switch(state) + { + case HGE_ICON: szIcon=value; + STUBBED("icon"); + //if(pHGE->hwnd) SetClassLong(pHGE->hwnd, GCL_HICON, (LONG)LoadIcon(pHGE->hInstance, szIcon)); + break; + case HGE_TITLE: strcpy(szWinTitle,value); + if(pHGE->hwnd) SDL_WM_SetCaption(value, value); + break; + case HGE_INIFILE: if(value) { strcpy(szIniFile,Resource_MakePath(value)); _LoadIniFile(szIniFile); } + else szIniFile[0]=0; + break; + case HGE_LOGFILE: if(value) + { + strcpy(szLogFile,Resource_MakePath(value)); + hf=fopen(szLogFile, "w"); + if(!hf) szLogFile[0]=0; + else fclose(hf); + } + else szLogFile[0]=0; + break; + default:break; + } +} + +bool CALL HGE_Impl::System_GetStateBool(hgeBoolState state) +{ + switch(state) + { + case HGE_WINDOWED: return bWindowed; + case HGE_ZBUFFER: return bZBuffer; + case HGE_TEXTUREFILTER: return bTextureFilter; + case HGE_USESOUND: return bUseSound; + case HGE_DONTSUSPEND: return bDontSuspend; + case HGE_HIDEMOUSE: return bHideMouse; + + #ifdef DEMO + case HGE_SHOWSPLASH: return bDMO; + #endif + default:break; + } + + return false; +} + +hgeCallback CALL HGE_Impl::System_GetStateFunc(hgeFuncState state) +{ + switch(state) + { + case HGE_FRAMEFUNC: return procFrameFunc; + case HGE_RENDERFUNC: return procRenderFunc; + case HGE_FOCUSLOSTFUNC: return procFocusLostFunc; + case HGE_FOCUSGAINFUNC: return procFocusGainFunc; + case HGE_EXITFUNC: return procExitFunc; + default:break; + } + + return NULL; +} + +HWND CALL HGE_Impl::System_GetStateHwnd(hgeHwndState state) +{ + switch(state) + { + case HGE_HWND: return hwnd; + case HGE_HWNDPARENT: return hwndParent; + default:break; + } + + return 0; +} + +int CALL HGE_Impl::System_GetStateInt(hgeIntState state) +{ + switch(state) + { + case HGE_ORIGSCREENWIDTH: return nOrigScreenWidth; + case HGE_ORIGSCREENHEIGHT: return nOrigScreenHeight; + case HGE_SCREENWIDTH: return nScreenWidth; + case HGE_SCREENHEIGHT: return nScreenHeight; + case HGE_SCREENBPP: return nScreenBPP; + case HGE_SAMPLERATE: return nSampleRate; + case HGE_FXVOLUME: return nFXVolume; + case HGE_MUSVOLUME: return nMusVolume; + case HGE_STREAMVOLUME: return nStreamVolume; + case HGE_FPS: return nHGEFPS; + case HGE_POWERSTATUS: return nPowerStatus; + default:break; + } + + return 0; +} + +const char* CALL HGE_Impl::System_GetStateString(hgeStringState state) { + switch(state) { + case HGE_ICON: return szIcon; + case HGE_TITLE: return szWinTitle; + case HGE_INIFILE: if(szIniFile[0]) return szIniFile; + else return 0; + case HGE_LOGFILE: if(szLogFile[0]) return szLogFile; + else return 0; + default:break; + } + + return NULL; +} + +const char* CALL HGE_Impl::System_GetErrorMessage() +{ + return szError; +} + +void CALL HGE_Impl::System_Log(const char *szFormat, ...) +{ + FILE *hf = NULL; + va_list ap; + + if(!szLogFile[0]) return; + + hf = fopen(szLogFile, "a"); + if(!hf) return; + + va_start(ap, szFormat); + vfprintf(hf, szFormat, ap); + va_end(ap); + va_start(ap, szFormat); + vfprintf(stderr, szFormat, ap); + va_end(ap); + fprintf(hf, "\n"); + fprintf(stderr, "\n"); + + fclose(hf); +} + +bool CALL HGE_Impl::System_Launch(const char *url) +{ +#if PLATFORM_MACOSX + CFURLRef cfurl = CFURLCreateWithBytes(NULL, (const UInt8 *) url, + strlen(url), kCFStringEncodingUTF8, NULL); + const OSStatus err = LSOpenCFURLRef(cfurl, NULL); + CFRelease(cfurl); + return (err == noErr); +#else + char command[1024];sprintf(command,"xdg-open %s",url); + system(command); + return false; +#endif +} + +void CALL HGE_Impl::System_Snapshot(const char *filename) +{ + char *shotname, tempname[_MAX_PATH]; + int i; + + if(!filename) + { + i=0; + shotname=Resource_EnumFiles("shot???.bmp"); + while(shotname) + { + i++; + shotname=Resource_EnumFiles(); + } + sprintf(tempname, "shot%03d.bmp", i); + filename=Resource_MakePath(tempname); + } + + if(pOpenGLDevice) + { + #if SDL_BYTEORDER == SDL_BIG_ENDIAN + const Uint32 rmask = 0xFF0000; + const Uint32 gmask = 0x00FF00; + const Uint32 bmask = 0x0000FF; + #else + const Uint32 rmask = 0x0000FF; + const Uint32 gmask = 0x00FF00; + const Uint32 bmask = 0xFF0000; + #endif + + pOpenGLDevice->glFinish(); // make sure screenshot is ready. + SDL_Surface *screen = SDL_GetVideoSurface(); + SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, screen->w, screen->h, 24, rmask, gmask, bmask, 0); + pOpenGLDevice->glReadPixels(0, 0, screen->w, screen->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels); + //flip the image so that it won't be upside down... + _flipSDLSurface(surface->pitch,surface->h,surface->pixels); + SDL_SaveBMP(surface, filename); + SDL_FreeSurface(surface); + } +} + +//////// Implementation //////// + + +HGE_Impl::HGE_Impl() +{ + CurTexture=0; + + //hInstance=GetModuleHandle(0); + hwnd=0; + bActive=false; + szError[0]=0; + + pOpenGLDevice=0; + pTargets=0; + pCurTarget=0; + //pScreenSurf=0; + //pScreenDepth=0; + pVB=0; + pIB=0; + VertArray=0; + textures=0; + + hBass=0; + hOpenAL=0; + bSilent=false; + streams=0; + + hSearch=0; + res=0; + + queue=0; + Char=VKey=Zpos=0; + Xpos=Ypos=0.0f; + bMouseOver=true; + bCaptured=false; + + nHGEFPS=HGEFPS_UNLIMITED; + fTime=0.0f; + fUpdateFPSDelay=0.0f; + fDeltaTime=0.0f; + nFPS=0; + nFPSf=0.0f; + Fcnt=0; + + procFrameFunc=0; + procRenderFunc=0; + procFocusLostFunc=0; + procFocusGainFunc=0; + procGfxRestoreFunc=0; + procExitFunc=0; + szIcon=0; + strcpy(szWinTitle,"HGE"); + nOrigScreenWidth=800; + nOrigScreenHeight=600; + nScreenWidth=800; + nScreenHeight=600; + nScreenBPP=32; + bWindowed=false; + bVsync=false; + bZBuffer=false; + bTextureFilter=true; + szLogFile[0]=0; + szIniFile[0]=0; + bUseSound=true; + nSampleRate=44100; + nFXVolume=100; + nMusVolume=100; + nStreamVolume=100; + nFixedDelta=0; + bHideMouse=true; + bDontSuspend=false; + hwndParent=0; + keymods=KMOD_NONE; + + nPowerStatus=HGEPWR_UNSUPPORTED; + +#ifdef DEMO + bDMO=true; +#endif + + bForceTextureCompression = false; + + STUBBED("get basedir"); +// GetModuleFileName(GetModuleHandle(NULL), szAppPath, sizeof(szAppPath)); + szAppPath[0] = '\0'; + int i; + for(i=strlen(szAppPath)-1; i>0; i--) if(szAppPath[i]=='/') break; + szAppPath[i+1]=0; +} + +void HGE_Impl::_PostError(const char *error) +{ + System_Log(error); + strcpy(szError,error); +} + +void HGE_Impl::_FocusChange(bool bAct) +{ + bActive=bAct; + + if(bActive) + { + if(procFocusGainFunc) procFocusGainFunc(); + } + else + { + if(procFocusLostFunc) procFocusLostFunc(); + } +} + +bool HGE_Impl::_ProcessSDLEvent(const SDL_Event &e) +{ + switch(e.type) + { + case SDL_VIDEOEXPOSE: + if(pHGE->procRenderFunc && pHGE->bWindowed) procRenderFunc(); + break; + + case SDL_QUIT: + if(pHGE->procExitFunc && !pHGE->procExitFunc()) break; + return false; + + case SDL_ACTIVEEVENT: { + const bool bActivating = (e.active.gain != 0); + if (e.active.state & SDL_APPINPUTFOCUS) { + if(pHGE->bActive != bActivating) pHGE->_FocusChange(bActivating); + } + if (e.active.state & SDL_APPMOUSEFOCUS) { + bMouseOver = bActivating; + } + break; + } + + case SDL_KEYDOWN: + keymods = e.key.keysym.mod; + + #if PLATFORM_MACOSX // handle Apple-Q hotkey, etc. + if (keymods & KMOD_META) { + if (e.key.keysym.sym == SDLK_q) { + if(pHGE->procExitFunc && !pHGE->procExitFunc()) break; + return false; + } else if (e.key.keysym.sym == SDLK_m) { + _MacMinimizeWindow(); + break; + } else if (e.key.keysym.sym == SDLK_h) { + if (keymods & KMOD_ALT) + _MacHideOtherWindows(); + else + _MacHideWindow(); + break; + } + } + #endif + + //#if 0 // (my app handles this, actually.) + // hotkey to toggle fullscreen/windowed mode. + if ( (keymods & KMOD_ALT) && ((e.key.keysym.sym == SDLK_RETURN) || (e.key.keysym.sym == SDLK_KP_ENTER)) ) { + System_SetStateBool(HGE_WINDOWED, !bWindowed); + break; + } + //#endif + + pHGE->_BuildEvent(INPUT_KEYDOWN, e.key.keysym.sym, 0, 0 /*(lparam & 0x40000000) ? HGEINP_REPEAT:0*/, -1, -1); + break; + + case SDL_KEYUP: + keymods = e.key.keysym.mod; + pHGE->_BuildEvent(INPUT_KEYUP, e.key.keysym.sym, 0, 0, -1, -1); + break; + + case SDL_MOUSEBUTTONDOWN: + if (e.button.button == SDL_BUTTON_LEFT) + pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_LBUTTON, 0, 0, e.button.x, e.button.y); + else if (e.button.button == SDL_BUTTON_RIGHT) + pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_RBUTTON, 0, 0, e.button.x, e.button.y); + else if (e.button.button == SDL_BUTTON_MIDDLE) + pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_MBUTTON, 0, 0, e.button.x, e.button.y); + else if (e.button.button == SDL_BUTTON_WHEELUP) + pHGE->_BuildEvent(INPUT_MOUSEWHEEL, 1, 0, 0, e.button.x, e.button.y); + else if (e.button.button == SDL_BUTTON_WHEELDOWN) + pHGE->_BuildEvent(INPUT_MOUSEWHEEL, -1, 0, 0, e.button.x, e.button.y); + break; + +#if 0 + case WM_LBUTTONDBLCLK: + pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_LBUTTON, 0, HGEINP_REPEAT, LOWORDINT(lparam), HIWORDINT(lparam)); + return FALSE; + case WM_MBUTTONDBLCLK: + pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_MBUTTON, 0, HGEINP_REPEAT, LOWORDINT(lparam), HIWORDINT(lparam)); + return FALSE; + case WM_RBUTTONDBLCLK: + pHGE->_BuildEvent(INPUT_MBUTTONDOWN, HGEK_RBUTTON, 0, HGEINP_REPEAT, LOWORDINT(lparam), HIWORDINT(lparam)); + return FALSE; +#endif + + case SDL_MOUSEBUTTONUP: + if (e.button.button == SDL_BUTTON_LEFT) + pHGE->_BuildEvent(INPUT_MBUTTONUP, HGEK_LBUTTON, 0, 0, e.button.x, e.button.y); + else if (e.button.button == SDL_BUTTON_RIGHT) + pHGE->_BuildEvent(INPUT_MBUTTONUP, HGEK_RBUTTON, 0, 0, e.button.x, e.button.y); + else if (e.button.button == SDL_BUTTON_MIDDLE) + pHGE->_BuildEvent(INPUT_MBUTTONUP, HGEK_MBUTTON, 0, 0, e.button.x, e.button.y); + break; + + case SDL_MOUSEMOTION: + pHGE->_BuildEvent(INPUT_MOUSEMOVE, 0, 0, 0, e.motion.x, e.motion.y); + break; + + +#if 0 // !!! FIXME + case WM_SIZE: + if(pHGE->pD3D && wparam==SIZE_RESTORED) pHGE->_Resize(LOWORD(lparam), HIWORD(lparam)); + //return FALSE; + break; +#endif + } + + return true; +} +int HGE_Impl::_flipSDLSurface(int pitch, int height, void* image_pixels) +{ + int index; + void* temp_row; + int height_div_2; + + temp_row=(void *)malloc(pitch); + assert(temp_row); + height_div_2 = (int) (height * .5); + for(index = 0; index < height_div_2; index++) + { + memcpy((Uint8 *)temp_row,(Uint8 *)(image_pixels)+pitch*index,pitch); + memcpy((Uint8 *)(image_pixels)+pitch*index,(Uint8 *)(image_pixels)+pitch*(height-index-1),pitch); + memcpy((Uint8 *)(image_pixels)+pitch*(height-index-1),temp_row,pitch); + } + free(temp_row); + return 0; +} +// end of system_unix.cpp ... diff --git a/archive/hge/timer.cpp b/archive/hge/timer.cpp new file mode 100644 index 0000000..13711c7 --- /dev/null +++ b/archive/hge/timer.cpp @@ -0,0 +1,31 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: timer +*/ + + +#include "hge_impl.h" + + +float CALL HGE_Impl::Timer_GetTime() +{ + return fTime; +} + +float CALL HGE_Impl::Timer_GetDelta() +{ + return fDeltaTime; +} + +int CALL HGE_Impl::Timer_GetFPS() +{ + return nFPS; +} + +float CALL HGE_Impl::Timer_GetFPSf() +{ + return nFPSf; +} |