]> Creatis software - clitk.git/commitdiff
cosmetic
authortbaudier <thomas.baudier@creatis.insa-lyon.fr>
Wed, 30 Nov 2016 12:21:22 +0000 (13:21 +0100)
committertbaudier <thomas.baudier@creatis.insa-lyon.fr>
Wed, 30 Nov 2016 12:21:22 +0000 (13:21 +0100)
dos2unix

75 files changed:
itk/itkBinaryThinningImageFilter3D.h
registration/clitkBSplineDeformableTransformInitializer.txx
utilities/CxImage/CxImageDLL/CxImageCrtDll.cpp
utilities/CxImage/CxImageDLL/CxImageCrtDll.dsp
utilities/CxImage/CxImageDLL/CxImageCrtDll.rc
utilities/CxImage/CxImageDLL/CxImageDll.dsw
utilities/CxImage/CxImageDLL/CxImageMfcDll.clw
utilities/CxImage/CxImageDLL/CxImageMfcDll.cpp
utilities/CxImage/CxImageDLL/CxImageMfcDll.h
utilities/CxImage/CxImageDLL/CxImageMfcDll.rc
utilities/CxImage/CxImageDLL/StdAfx.cpp
utilities/CxImage/CxImageDLL/StdAfx.h
utilities/CxImage/CxImageDLL/StdCrt.h
utilities/CxImage/CxImageDLL/cximagemfcdll.dsp
utilities/CxImage/CxImageDLL/resource.h
utilities/CxImage/CxImageDLL/resrc1.h
utilities/CxImage/cximage.dsp
utilities/CxImage/cximage.dsw
utilities/CxImage/license.txt
utilities/CxImage/tif_xfile.cpp
utilities/CxImage/xfile.h
utilities/CxImage/ximabmp.cpp
utilities/CxImage/ximabmp.h
utilities/CxImage/ximacfg.h
utilities/CxImage/ximadef.h
utilities/CxImage/ximadsp.cpp
utilities/CxImage/ximaenc.cpp
utilities/CxImage/ximaexif.cpp
utilities/CxImage/ximage.cpp
utilities/CxImage/ximage.h
utilities/CxImage/ximagif.cpp
utilities/CxImage/ximagif.h
utilities/CxImage/ximahist.cpp
utilities/CxImage/ximaico.cpp
utilities/CxImage/ximaico.h
utilities/CxImage/ximainfo.cpp
utilities/CxImage/ximaint.cpp
utilities/CxImage/ximaiter.h
utilities/CxImage/ximajas.cpp
utilities/CxImage/ximajas.h
utilities/CxImage/ximajbg.cpp
utilities/CxImage/ximajbg.h
utilities/CxImage/ximajpg.cpp
utilities/CxImage/ximajpg.h
utilities/CxImage/ximalpha.cpp
utilities/CxImage/ximalyr.cpp
utilities/CxImage/ximamng.cpp
utilities/CxImage/ximamng.h
utilities/CxImage/ximapal.cpp
utilities/CxImage/ximapcx.cpp
utilities/CxImage/ximapcx.h
utilities/CxImage/ximapng.cpp
utilities/CxImage/ximapng.h
utilities/CxImage/ximaraw.cpp
utilities/CxImage/ximaraw.h
utilities/CxImage/ximasel.cpp
utilities/CxImage/ximaska.cpp
utilities/CxImage/ximaska.h
utilities/CxImage/ximatga.cpp
utilities/CxImage/ximatga.h
utilities/CxImage/ximath.cpp
utilities/CxImage/ximath.h
utilities/CxImage/ximatif.cpp
utilities/CxImage/ximatif.h
utilities/CxImage/ximatran.cpp
utilities/CxImage/ximawbmp.cpp
utilities/CxImage/ximawbmp.h
utilities/CxImage/ximawmf.cpp
utilities/CxImage/ximawmf.h
utilities/CxImage/ximawnd.cpp
utilities/CxImage/xiofile.h
utilities/CxImage/xmemfile.cpp
utilities/CxImage/xmemfile.h
vv/vvIcon.rc
vv/vvSlicerManager.cxx

index 12926e9bbee3f6dca4860191afa2991553c1b6be..f75d8834683d7dad62019931534913408ec5f96a 100644 (file)
   - BSD        See included LICENSE.txt file
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
 ===========================================================================*/
-#ifndef __itkBinaryThinningImageFilter3D_h\r
-#define __itkBinaryThinningImageFilter3D_h\r
-\r
-#include <itkNeighborhoodIterator.h>\r
-#include <itkImageToImageFilter.h>\r
-#include <itkImageRegionIteratorWithIndex.h>\r
-#include <itkConstantBoundaryCondition.h>\r
-\r
-namespace itk\r
-{\r
-/** \class BinaryThinningImageFilter3D\r
-*\r
-* \brief This filter computes one-pixel-wide skeleton of a 3D input image.\r
-*\r
-* This class is parametrized over the type of the input image\r
-* and the type of the output image.\r
-* \r
-* The input is assumed to be a binary image. All non-zero valued voxels\r
-* are set to 1 internally to simplify the computation. The filter will\r
-* produce a skeleton of the object.  The output background values are 0,\r
-* and the foreground values are 1.\r
-* \r
-* A 26-neighbourhood configuration is used for the foreground and a\r
-* 6-neighbourhood configuration for the background. Thinning is performed\r
-* symmetrically in order to guarantee that the skeleton lies medial within\r
-* the object.\r
-*\r
-* This filter is a parallel thinning algorithm and is an implementation\r
-* of the algorithm described in:\r
-* \r
-* T.C. Lee, R.L. Kashyap, and C.N. Chu.\r
-* Building skeleton models via 3-D medial surface/axis thinning algorithms.\r
-* Computer Vision, Graphics, and Image Processing, 56(6):462--478, 1994.\r
-* \r
-* To do: Make use of multi-threading.\r
-*\r
-* \author Hanno Homann, Oxford University, Wolfson Medical Vision Lab, UK.\r
-* \r
-* \sa MorphologyImageFilter\r
-* \ingroup ImageEnhancement MathematicalMorphologyImageFilters\r
-*/\r
-\r
-template <class TInputImage,class TOutputImage>\r
-class BinaryThinningImageFilter3D :\r
-    public ImageToImageFilter<TInputImage,TOutputImage>\r
-{\r
-public:\r
-  /** Standard class typedefs. */\r
-  typedef BinaryThinningImageFilter3D    Self;\r
-  typedef ImageToImageFilter<TInputImage,TOutputImage> Superclass;\r
-  typedef SmartPointer<Self> Pointer;\r
-  typedef SmartPointer<const Self> ConstPointer;\r
-\r
-  /** Method for creation through the object factory */\r
-  itkNewMacro(Self);\r
-\r
-  /** Run-time type information (and related methods). */\r
-  itkTypeMacro( BinaryThinningImageFilter3D, ImageToImageFilter );\r
-\r
-  /** Type for input image. */\r
-  typedef   TInputImage       InputImageType;\r
-\r
-  /** Type for output image: Skelenton of the object.  */\r
-  typedef   TOutputImage      OutputImageType;\r
-\r
-  /** Type for the region of the input image. */\r
-  typedef typename InputImageType::RegionType RegionType;\r
-\r
-  /** Type for the index of the input image. */\r
-  typedef typename RegionType::IndexType  IndexType;\r
-\r
-  /** Type for the pixel type of the input image. */\r
-  typedef typename InputImageType::PixelType InputImagePixelType ;\r
-\r
-  /** Type for the pixel type of the input image. */\r
-  typedef typename OutputImageType::PixelType OutputImagePixelType ;\r
-\r
-  /** Type for the size of the input image. */\r
-  typedef typename RegionType::SizeType SizeType;\r
-\r
-  /** Pointer Type for input image. */\r
-  typedef typename InputImageType::ConstPointer InputImagePointer;\r
-\r
-  /** Pointer Type for the output image. */\r
-  typedef typename OutputImageType::Pointer OutputImagePointer;\r
-  \r
-  /** Boundary condition type for the neighborhood iterator */\r
-  typedef ConstantBoundaryCondition< TInputImage > ConstBoundaryConditionType;\r
-  \r
-  /** Neighborhood iterator type */\r
-  typedef NeighborhoodIterator<TInputImage, ConstBoundaryConditionType> NeighborhoodIteratorType;\r
-  \r
-  /** Neighborhood type */\r
-  typedef typename NeighborhoodIteratorType::NeighborhoodType NeighborhoodType;\r
-\r
-  /** Get Skelenton by thinning image. */\r
-  OutputImageType * GetThinning(void);\r
-\r
-  /** ImageDimension enumeration   */\r
-  itkStaticConstMacro(InputImageDimension, unsigned int,\r
-                      TInputImage::ImageDimension );\r
-  itkStaticConstMacro(OutputImageDimension, unsigned int,\r
-                      TOutputImage::ImageDimension );\r
-\r
-#ifdef ITK_USE_CONCEPT_CHECKING\r
-  /** Begin concept checking */\r
-  itkConceptMacro(SameDimensionCheck,\r
-    (Concept::SameDimension<InputImageDimension, 3>));\r
-  itkConceptMacro(SameTypeCheck,\r
-    (Concept::SameType<InputImagePixelType, OutputImagePixelType>));\r
-  itkConceptMacro(InputAdditiveOperatorsCheck,\r
-    (Concept::AdditiveOperators<InputImagePixelType>));\r
-  itkConceptMacro(InputConvertibleToIntCheck,\r
-    (Concept::Convertible<InputImagePixelType, int>));\r
-  itkConceptMacro(IntConvertibleToInputCheck,\r
-    (Concept::Convertible<int, InputImagePixelType>));\r
-  itkConceptMacro(InputIntComparableCheck,\r
-    (Concept::Comparable<InputImagePixelType, int>));\r
-  /** End concept checking */\r
-#endif\r
-\r
-protected:\r
-  BinaryThinningImageFilter3D();\r
-  virtual ~BinaryThinningImageFilter3D() {};\r
-  void PrintSelf(std::ostream& os, Indent indent) const;\r
-\r
-  /** Compute thinning Image. */\r
-  void GenerateData();\r
-\r
-  /** Prepare data. */\r
-  void PrepareData();\r
-\r
-  /**  Compute thinning Image. */\r
-  void ComputeThinImage();\r
-  \r
-  /**  isEulerInvariant [Lee94] */\r
-  bool isEulerInvariant(NeighborhoodType neighbors, int *LUT);\r
-  void fillEulerLUT(int *LUT);  \r
-  /**  isSimplePoint [Lee94] */\r
-  bool isSimplePoint(NeighborhoodType neighbors);\r
-  /**  Octree_labeling [Lee94] */\r
-  void Octree_labeling(int octant, int label, int *cube);\r
-\r
-\r
-private:   \r
-  BinaryThinningImageFilter3D(const Self&); //purposely not implemented\r
-  void operator=(const Self&); //purposely not implemented\r
-\r
-}; // end of BinaryThinningImageFilter3D class\r
-\r
-} //end namespace itk\r
-\r
-#ifndef ITK_MANUAL_INSTANTIATION\r
-#include "itkBinaryThinningImageFilter3D.txx"\r
-#endif\r
-\r
-#endif\r
+#ifndef __itkBinaryThinningImageFilter3D_h
+#define __itkBinaryThinningImageFilter3D_h
+
+#include <itkNeighborhoodIterator.h>
+#include <itkImageToImageFilter.h>
+#include <itkImageRegionIteratorWithIndex.h>
+#include <itkConstantBoundaryCondition.h>
+
+namespace itk
+{
+/** \class BinaryThinningImageFilter3D
+*
+* \brief This filter computes one-pixel-wide skeleton of a 3D input image.
+*
+* This class is parametrized over the type of the input image
+* and the type of the output image.
+* 
+* The input is assumed to be a binary image. All non-zero valued voxels
+* are set to 1 internally to simplify the computation. The filter will
+* produce a skeleton of the object.  The output background values are 0,
+* and the foreground values are 1.
+* 
+* A 26-neighbourhood configuration is used for the foreground and a
+* 6-neighbourhood configuration for the background. Thinning is performed
+* symmetrically in order to guarantee that the skeleton lies medial within
+* the object.
+*
+* This filter is a parallel thinning algorithm and is an implementation
+* of the algorithm described in:
+* 
+* T.C. Lee, R.L. Kashyap, and C.N. Chu.
+* Building skeleton models via 3-D medial surface/axis thinning algorithms.
+* Computer Vision, Graphics, and Image Processing, 56(6):462--478, 1994.
+* 
+* To do: Make use of multi-threading.
+*
+* \author Hanno Homann, Oxford University, Wolfson Medical Vision Lab, UK.
+* 
+* \sa MorphologyImageFilter
+* \ingroup ImageEnhancement MathematicalMorphologyImageFilters
+*/
+
+template <class TInputImage,class TOutputImage>
+class BinaryThinningImageFilter3D :
+    public ImageToImageFilter<TInputImage,TOutputImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef BinaryThinningImageFilter3D    Self;
+  typedef ImageToImageFilter<TInputImage,TOutputImage> Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+
+  /** Method for creation through the object factory */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( BinaryThinningImageFilter3D, ImageToImageFilter );
+
+  /** Type for input image. */
+  typedef   TInputImage       InputImageType;
+
+  /** Type for output image: Skelenton of the object.  */
+  typedef   TOutputImage      OutputImageType;
+
+  /** Type for the region of the input image. */
+  typedef typename InputImageType::RegionType RegionType;
+
+  /** Type for the index of the input image. */
+  typedef typename RegionType::IndexType  IndexType;
+
+  /** Type for the pixel type of the input image. */
+  typedef typename InputImageType::PixelType InputImagePixelType ;
+
+  /** Type for the pixel type of the input image. */
+  typedef typename OutputImageType::PixelType OutputImagePixelType ;
+
+  /** Type for the size of the input image. */
+  typedef typename RegionType::SizeType SizeType;
+
+  /** Pointer Type for input image. */
+  typedef typename InputImageType::ConstPointer InputImagePointer;
+
+  /** Pointer Type for the output image. */
+  typedef typename OutputImageType::Pointer OutputImagePointer;
+  
+  /** Boundary condition type for the neighborhood iterator */
+  typedef ConstantBoundaryCondition< TInputImage > ConstBoundaryConditionType;
+  
+  /** Neighborhood iterator type */
+  typedef NeighborhoodIterator<TInputImage, ConstBoundaryConditionType> NeighborhoodIteratorType;
+  
+  /** Neighborhood type */
+  typedef typename NeighborhoodIteratorType::NeighborhoodType NeighborhoodType;
+
+  /** Get Skelenton by thinning image. */
+  OutputImageType * GetThinning(void);
+
+  /** ImageDimension enumeration   */
+  itkStaticConstMacro(InputImageDimension, unsigned int,
+                      TInputImage::ImageDimension );
+  itkStaticConstMacro(OutputImageDimension, unsigned int,
+                      TOutputImage::ImageDimension );
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+  /** Begin concept checking */
+  itkConceptMacro(SameDimensionCheck,
+    (Concept::SameDimension<InputImageDimension, 3>));
+  itkConceptMacro(SameTypeCheck,
+    (Concept::SameType<InputImagePixelType, OutputImagePixelType>));
+  itkConceptMacro(InputAdditiveOperatorsCheck,
+    (Concept::AdditiveOperators<InputImagePixelType>));
+  itkConceptMacro(InputConvertibleToIntCheck,
+    (Concept::Convertible<InputImagePixelType, int>));
+  itkConceptMacro(IntConvertibleToInputCheck,
+    (Concept::Convertible<int, InputImagePixelType>));
+  itkConceptMacro(InputIntComparableCheck,
+    (Concept::Comparable<InputImagePixelType, int>));
+  /** End concept checking */
+#endif
+
+protected:
+  BinaryThinningImageFilter3D();
+  virtual ~BinaryThinningImageFilter3D() {};
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** Compute thinning Image. */
+  void GenerateData();
+
+  /** Prepare data. */
+  void PrepareData();
+
+  /**  Compute thinning Image. */
+  void ComputeThinImage();
+  
+  /**  isEulerInvariant [Lee94] */
+  bool isEulerInvariant(NeighborhoodType neighbors, int *LUT);
+  void fillEulerLUT(int *LUT);  
+  /**  isSimplePoint [Lee94] */
+  bool isSimplePoint(NeighborhoodType neighbors);
+  /**  Octree_labeling [Lee94] */
+  void Octree_labeling(int octant, int label, int *cube);
+
+
+private:   
+  BinaryThinningImageFilter3D(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+}; // end of BinaryThinningImageFilter3D class
+
+} //end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkBinaryThinningImageFilter3D.txx"
+#endif
+
+#endif
index 59af63c7d211c98d4b4e8a40c29a1b5de3a91f4e..5dce7858863aecb94897834086bd96e9a82a3468 100644 (file)
@@ -1,4 +1,4 @@
-/*=========================================================================
+/*=========================================================================
   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
 
   Authors belong to: 
index ad468ed0f74fb8875539d136ef8f9695e96faf18..d4e022fda5b8dbb1c9831af00e7359d7ee508550 100644 (file)
@@ -1,13 +1,13 @@
-// CxImageCrtDll.cpp : Defines the entry point for the CxImageCrtDll application.\r
-//\r
-\r
-#include "stdcrt.h"\r
-\r
-BOOL APIENTRY DllMain( HANDLE /*hModule*/, \r
-                       DWORD  /*ul_reason_for_call*/, \r
-                       LPVOID /*lpReserved*/\r
-                                        )\r
-{\r
-    return TRUE;\r
-}\r
-\r
+// CxImageCrtDll.cpp : Defines the entry point for the CxImageCrtDll application.
+//
+
+#include "stdcrt.h"
+
+BOOL APIENTRY DllMain( HANDLE /*hModule*/, 
+                       DWORD  /*ul_reason_for_call*/, 
+                       LPVOID /*lpReserved*/
+                                        )
+{
+    return TRUE;
+}
+
index 09d1c69e3db9ea860855a30755514dae10047de3..f92cfb9edc9e535c6c17093b9acb8275c2698632 100644 (file)
-# Microsoft Developer Studio Project File - Name="CxImageCrtDll" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
-\r
-CFG=CxImageCrtDll - Win32 Unicode Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "CxImageCrtDll.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "CxImageCrtDll.mak" CFG="CxImageCrtDll - Win32 Unicode Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "CxImageCrtDll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "CxImageCrtDll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "CxImageCrtDll - Win32 Unicode Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "CxImageCrtDll - Win32 Unicode Release" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-MTL=midl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "CxImageCrtDll - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRCxImageCrtDll" /D "CxImageCrtDll_EXPORTS" /Yu"stdafx.h" /FD /GZ /c\r
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /FD /GZ /c\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# ADD RSC /l 0x809 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept /CxImageCrtDll\r
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/cximagecrtd.dll" /pdbtype:sept\r
-# SUBTRACT LINK32 /pdb:none\r
-\r
-!ELSEIF  "$(CFG)" == "CxImageCrtDll - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRCxImageCrtDll" /D "CxImageCrtDll_EXPORTS" /Yu"stdafx.h" /FD /c\r
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /FD /c\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
-# ADD RSC /l 0x809 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 /CxImageCrtDll\r
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /machine:I386 /out:"../../bin/cximagecrt.dll"\r
-# SUBTRACT LINK32 /pdb:none\r
-\r
-!ELSEIF  "$(CFG)" == "CxImageCrtDll - Win32 Unicode Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "CxImageCrtDll___Win32_Unicode_Debug"\r
-# PROP BASE Intermediate_Dir "CxImageCrtDll___Win32_Unicode_Debug"\r
-# PROP BASE Ignore_Export_Lib 0\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Unicode_Debug"\r
-# PROP Intermediate_Dir "Unicode_Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /FD /GZ /c\r
-# SUBTRACT BASE CPP /YX /Yc /Yu\r
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "_WINDOWS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NON_CONFORMING_SWPRINTFS" /FD /GZ /c\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# ADD RSC /l 0x809 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/cximagecrtd.dll" /pdbtype:sept\r
-# SUBTRACT BASE LINK32 /pdb:none\r
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/cximagecrtdu.dll" /pdbtype:sept\r
-# SUBTRACT LINK32 /pdb:none\r
-\r
-!ELSEIF  "$(CFG)" == "CxImageCrtDll - Win32 Unicode Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "CxImageCrtDll___Win32_Unicode_Release"\r
-# PROP BASE Intermediate_Dir "CxImageCrtDll___Win32_Unicode_Release"\r
-# PROP BASE Ignore_Export_Lib 0\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Unicode_Release"\r
-# PROP Intermediate_Dir "Unicode_Release"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /FD /c\r
-# SUBTRACT BASE CPP /YX /Yc /Yu\r
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "_WINDOWS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NON_CONFORMING_SWPRINTFS" /FD /c\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
-# ADD RSC /l 0x809 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /machine:I386 /out:"../../bin/cximagecrt.dll"\r
-# SUBTRACT BASE LINK32 /pdb:none\r
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /machine:I386 /out:"../../bin/cximagecrtu.dll"\r
-# SUBTRACT LINK32 /pdb:none\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "CxImageCrtDll - Win32 Debug"\r
-# Name "CxImageCrtDll - Win32 Release"\r
-# Name "CxImageCrtDll - Win32 Unicode Debug"\r
-# Name "CxImageCrtDll - Win32 Unicode Release"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\CxImageCrtDll.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\CxImageCrtDll.rc\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\tif_xfile.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximabmp.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximadsp.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaenc.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaexif.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximage.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximagif.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximahist.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaico.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximainfo.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaint.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajas.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajbg.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajpg.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximalpha.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximalyr.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximamng.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapal.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapcx.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapng.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaraw.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximasel.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaska.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatga.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximath.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatif.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatran.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawbmp.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawmf.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawnd.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\xmemfile.cpp\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\StdCrt.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\xfile.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximabmp.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximadefs.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\xImage.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximagif.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaico.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaiter.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajas.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajbg.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajpg.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximamng.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapcx.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapng.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaraw.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatga.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximath.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatif.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawbmp.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawmf.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\xiofile.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\xmemfile.h\r
-# End Source File\r
-# End Group\r
-# Begin Group "Resource Files"\r
-\r
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
-# End Group\r
-# End Target\r
-# End Project\r
+# Microsoft Developer Studio Project File - Name="CxImageCrtDll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=CxImageCrtDll - Win32 Unicode Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "CxImageCrtDll.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "CxImageCrtDll.mak" CFG="CxImageCrtDll - Win32 Unicode Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "CxImageCrtDll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "CxImageCrtDll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "CxImageCrtDll - Win32 Unicode Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "CxImageCrtDll - Win32 Unicode Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "CxImageCrtDll - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRCxImageCrtDll" /D "CxImageCrtDll_EXPORTS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /debug /machine:I386 /pdbtype:sept /CxImageCrtDll
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/cximagecrtd.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "CxImageCrtDll - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRCxImageCrtDll" /D "CxImageCrtDll_EXPORTS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /machine:I386 /CxImageCrtDll
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /machine:I386 /out:"../../bin/cximagecrt.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "CxImageCrtDll - Win32 Unicode Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "CxImageCrtDll___Win32_Unicode_Debug"
+# PROP BASE Intermediate_Dir "CxImageCrtDll___Win32_Unicode_Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Unicode_Debug"
+# PROP Intermediate_Dir "Unicode_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /FD /GZ /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "_WINDOWS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NON_CONFORMING_SWPRINTFS" /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/cximagecrtd.dll" /pdbtype:sept
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/cximagecrtdu.dll" /pdbtype:sept
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF  "$(CFG)" == "CxImageCrtDll - Win32 Unicode Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "CxImageCrtDll___Win32_Unicode_Release"
+# PROP BASE Intermediate_Dir "CxImageCrtDll___Win32_Unicode_Release"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Unicode_Release"
+# PROP Intermediate_Dir "Unicode_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /FD /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "_WINDOWS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NON_CONFORMING_SWPRINTFS" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /machine:I386 /out:"../../bin/cximagecrt.dll"
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /dll /machine:I386 /out:"../../bin/cximagecrtu.dll"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF 
+
+# Begin Target
+
+# Name "CxImageCrtDll - Win32 Debug"
+# Name "CxImageCrtDll - Win32 Release"
+# Name "CxImageCrtDll - Win32 Unicode Debug"
+# Name "CxImageCrtDll - Win32 Unicode Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\CxImageCrtDll.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CxImageCrtDll.rc
+# End Source File
+# Begin Source File
+
+SOURCE=..\tif_xfile.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximabmp.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximadsp.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaenc.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaexif.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximage.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximagif.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximahist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaico.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximainfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaint.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajas.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajbg.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajpg.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximalpha.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximalyr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximamng.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapal.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapcx.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapng.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaraw.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximasel.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaska.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatga.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatif.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatran.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawbmp.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawmf.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawnd.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# Begin Source File
+
+SOURCE=..\xmemfile.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\StdCrt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\xfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximabmp.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximadefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\xImage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximagif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaico.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaiter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajbg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajpg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximamng.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapcx.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapng.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaraw.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatga.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawbmp.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawmf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\xiofile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\xmemfile.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
index 98adb207d0bfd2241f85f51fbb880271cc5acee2..4db01c19618e25ce9fb723b1ef1ec4435ad08098 100644 (file)
-//Microsoft Developer Studio generated resource script.\r
-//\r
-#include "resrc1.h"\r
-\r
-#define APSTUDIO_READONLY_SYMBOLS\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Generated from the TEXTINCLUDE 2 resource.\r
-//\r
-#include "resource.h"\r
-#include "winres.h"\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-#undef APSTUDIO_READONLY_SYMBOLS\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Neutral resources\r
-\r
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)\r
-#ifdef _WIN32\r
-LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL\r
-#pragma code_page(1252)\r
-#endif //_WIN32\r
-\r
-#ifndef _MAC\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Version\r
-//\r
-\r
-VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 6,0,0,0\r
- PRODUCTVERSION 6,0,0,0\r
- FILEFLAGSMASK 0x3fL\r
-#ifdef _DEBUG\r
- FILEFLAGS 0x1L\r
-#else\r
- FILEFLAGS 0x0L\r
-#endif\r
- FILEOS 0x4L\r
- FILETYPE 0x2L\r
- FILESUBTYPE 0x0L\r
-BEGIN\r
-    BLOCK "StringFileInfo"\r
-    BEGIN\r
-        BLOCK "000004b0"\r
-        BEGIN\r
-            VALUE "Comments", "CxImage 6.0.0.0 CRT DLL\0"\r
-            VALUE "CompanyName", "Pizzolato Davide - www.xdp.it\0"\r
-            VALUE "FileDescription", "cximage\0"\r
-            VALUE "FileVersion", "6, 0, 0, 0\0"\r
-            VALUE "InternalName", "cximage\0"\r
-            VALUE "LegalCopyright", "Copyright Â© 2001 - 2008\0"\r
-            VALUE "LegalTrademarks", "\0"\r
-            VALUE "OriginalFilename", "cximagecrt.dll\0"\r
-            VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "cximage\0"\r
-            VALUE "ProductVersion", "6, 0, 0, 0\0"\r
-            VALUE "SpecialBuild", "\0"\r
-        END\r
-    END\r
-    BLOCK "VarFileInfo"\r
-    BEGIN\r
-        VALUE "Translation", 0x0, 1200\r
-    END\r
-END\r
-\r
-#endif    // !_MAC\r
-\r
-#endif    // Neutral resources\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Italian (Italy) resources\r
-\r
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)\r
-#ifdef _WIN32\r
-LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN\r
-#pragma code_page(1252)\r
-#endif //_WIN32\r
-\r
-#ifdef APSTUDIO_INVOKED\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// TEXTINCLUDE\r
-//\r
-\r
-1 TEXTINCLUDE DISCARDABLE \r
-BEGIN\r
-    "resrc1.h\0"\r
-END\r
-\r
-2 TEXTINCLUDE DISCARDABLE \r
-BEGIN\r
-    "#include ""resource.h""\r\n"\r
-    "#include ""winresrc.h""\r\n"\r
-    "\0"\r
-END\r
-\r
-3 TEXTINCLUDE DISCARDABLE \r
-BEGIN\r
-    "\r\n"\r
-    "\0"\r
-END\r
-\r
-#endif    // APSTUDIO_INVOKED\r
-\r
-#endif    // Italian (Italy) resources\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
-\r
-\r
-#ifndef APSTUDIO_INVOKED\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Generated from the TEXTINCLUDE 3 resource.\r
-//\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-#endif    // not APSTUDIO_INVOKED\r
-\r
+//Microsoft Developer Studio generated resource script.
+//
+#include "resrc1.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "resource.h"
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 6,0,0,0
+ PRODUCTVERSION 6,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "000004b0"
+        BEGIN
+            VALUE "Comments", "CxImage 6.0.0.0 CRT DLL\0"
+            VALUE "CompanyName", "Pizzolato Davide - www.xdp.it\0"
+            VALUE "FileDescription", "cximage\0"
+            VALUE "FileVersion", "6, 0, 0, 0\0"
+            VALUE "InternalName", "cximage\0"
+            VALUE "LegalCopyright", "Copyright Â© 2001 - 2008\0"
+            VALUE "LegalTrademarks", "\0"
+            VALUE "OriginalFilename", "cximagecrt.dll\0"
+            VALUE "PrivateBuild", "\0"
+            VALUE "ProductName", "cximage\0"
+            VALUE "ProductVersion", "6, 0, 0, 0\0"
+            VALUE "SpecialBuild", "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0, 1200
+    END
+END
+
+#endif    // !_MAC
+
+#endif    // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Italian (Italy) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
+#ifdef _WIN32
+LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resrc1.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""resource.h""\r\n"
+    "#include ""winresrc.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+#endif    // Italian (Italy) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
index afdd4ba06f7e691c2d933757e839863768a4205f..45f97d59bf61e10b0e8fc1d3fe66c42b385e4ece 100644 (file)
-Microsoft Developer Studio Workspace File, Format Version 6.00\r
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
-\r
-###############################################################################\r
-\r
-Project: "CxImageCrtDll"=.\CxImageCrtDll.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-    Begin Project Dependency\r
-    Project_Dep_Name j2000\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name jbig\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name jpeg\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name png\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name tiff\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name zlib\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name j2k\r
-    End Project Dependency\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Project: "CxImageMfcDll"=.\cximagemfcdll.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-    Begin Project Dependency\r
-    Project_Dep_Name j2k\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name jbig\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name jpeg\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name png\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name tiff\r
-    End Project Dependency\r
-    Begin Project Dependency\r
-    Project_Dep_Name zlib\r
-    End Project Dependency\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Project: "j2k"=..\..\j2k\j2k.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Project: "jbig"=..\..\jbig\jbig.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Project: "jpeg"=..\..\jpeg\Jpeg.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Project: "png"=..\..\png\png.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Project: "tiff"=..\..\tiff\Tiff.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Project: "zlib"=..\..\zlib\zlib.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Global:\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<3>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "CxImageCrtDll"=.\CxImageCrtDll.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name j2000
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name jbig
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name jpeg
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name png
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name tiff
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name zlib
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name j2k
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "CxImageMfcDll"=.\cximagemfcdll.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+    Begin Project Dependency
+    Project_Dep_Name j2k
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name jbig
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name jpeg
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name png
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name tiff
+    End Project Dependency
+    Begin Project Dependency
+    Project_Dep_Name zlib
+    End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "j2k"=..\..\j2k\j2k.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "jbig"=..\..\jbig\jbig.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "jpeg"=..\..\jpeg\Jpeg.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "png"=..\..\png\png.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "tiff"=..\..\tiff\Tiff.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "zlib"=..\..\zlib\zlib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
index 349133d3cbd3729a7caff31dcdfae5e8a0640ff8..c14615cd5cf4166e8189bbd6506bdad3ceb2cd28 100644 (file)
@@ -1,16 +1,16 @@
-; CLW file contains information for the MFC ClassWizard\r
-\r
-[General Info]\r
-Version=1\r
-ClassCount=1\r
-Class1=CcximagemfcdllApp\r
-LastClass=CcximagemfcdllApp\r
-NewFileInclude2=#include "cximagemfcdll.h"\r
-ResourceCount=0\r
-NewFileInclude1=#include "stdafx.h"\r
-\r
-[CLS:CcximagemfcdllApp]\r
-Type=0\r
-HeaderFile=cximagemfcdll.h\r
-ImplementationFile=cximagemfcdll.cpp\r
-Filter=N\r
+; CLW file contains information for the MFC ClassWizard
+
+[General Info]
+Version=1
+ClassCount=1
+Class1=CcximagemfcdllApp
+LastClass=CcximagemfcdllApp
+NewFileInclude2=#include "cximagemfcdll.h"
+ResourceCount=0
+NewFileInclude1=#include "stdafx.h"
+
+[CLS:CcximagemfcdllApp]
+Type=0
+HeaderFile=cximagemfcdll.h
+ImplementationFile=cximagemfcdll.cpp
+Filter=N
index ff4e12ebc78945aa74154ac6260582d1db75758d..092514b5d02e6681bd6e6088a78a2c980d62a9f5 100644 (file)
@@ -1,62 +1,62 @@
-// cximagemfcdll.cpp : Defines the initialization routines for the DLL.\r
-//\r
-\r
-#include "stdafx.h"\r
-#include "cximagemfcdll.h"\r
-\r
-#ifdef _DEBUG\r
-#define new DEBUG_NEW\r
-#undef THIS_FILE\r
-static char THIS_FILE[] = __FILE__;\r
-#endif\r
-\r
-//\r
-//     Note!\r
-//\r
-//             If this DLL is dynamically linked against the MFC\r
-//             DLLs, any functions exported from this DLL which\r
-//             call into MFC must have the AFX_MANAGE_STATE macro\r
-//             added at the very beginning of the function.\r
-//\r
-//             For example:\r
-//\r
-//             extern "C" BOOL PASCAL EXPORT ExportedFunction()\r
-//             {\r
-//                     AFX_MANAGE_STATE(AfxGetStaticModuleState());\r
-//                     // normal function body here\r
-//             }\r
-//\r
-//             It is very important that this macro appear in each\r
-//             function, prior to any calls into MFC.  This means that\r
-//             it must appear as the first statement within the \r
-//             function, even before any object variable declarations\r
-//             as their constructors may generate calls into the MFC\r
-//             DLL.\r
-//\r
-//             Please see MFC Technical Notes 33 and 58 for additional\r
-//             details.\r
-//\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// CcximagemfcdllApp\r
-\r
-BEGIN_MESSAGE_MAP(CcximagemfcdllApp, CWinApp)\r
-       //{{AFX_MSG_MAP(CcximagemfcdllApp)\r
-               // NOTE - the ClassWizard will add and remove mapping macros here.\r
-               //    DO NOT EDIT what you see in these blocks of generated code!\r
-       //}}AFX_MSG_MAP\r
-END_MESSAGE_MAP()\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// CcximagemfcdllApp construction\r
-\r
-CcximagemfcdllApp::CcximagemfcdllApp()\r
-{\r
-       // TODO: add construction code here,\r
-       // Place all significant initialization in InitInstance\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// The one and only CcximagemfcdllApp object\r
-\r
-CcximagemfcdllApp theApp;\r
+// cximagemfcdll.cpp : Defines the initialization routines for the DLL.
+//
+
+#include "stdafx.h"
+#include "cximagemfcdll.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+//
+//     Note!
+//
+//             If this DLL is dynamically linked against the MFC
+//             DLLs, any functions exported from this DLL which
+//             call into MFC must have the AFX_MANAGE_STATE macro
+//             added at the very beginning of the function.
+//
+//             For example:
+//
+//             extern "C" BOOL PASCAL EXPORT ExportedFunction()
+//             {
+//                     AFX_MANAGE_STATE(AfxGetStaticModuleState());
+//                     // normal function body here
+//             }
+//
+//             It is very important that this macro appear in each
+//             function, prior to any calls into MFC.  This means that
+//             it must appear as the first statement within the 
+//             function, even before any object variable declarations
+//             as their constructors may generate calls into the MFC
+//             DLL.
+//
+//             Please see MFC Technical Notes 33 and 58 for additional
+//             details.
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CcximagemfcdllApp
+
+BEGIN_MESSAGE_MAP(CcximagemfcdllApp, CWinApp)
+       //{{AFX_MSG_MAP(CcximagemfcdllApp)
+               // NOTE - the ClassWizard will add and remove mapping macros here.
+               //    DO NOT EDIT what you see in these blocks of generated code!
+       //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CcximagemfcdllApp construction
+
+CcximagemfcdllApp::CcximagemfcdllApp()
+{
+       // TODO: add construction code here,
+       // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CcximagemfcdllApp object
+
+CcximagemfcdllApp theApp;
index 43d62cf1982c65aad5fa5977483a3e0d7f4177bf..681d5778e73c060bc43d8c303e9432ad74ac35ba 100644 (file)
@@ -1,45 +1,45 @@
-// cximagemfcdll.h : main header file for the cximagemfcdll DLL\r
-//\r
-\r
-#if !defined(AFX_cximagemfcdll_H__E98F71A6_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_)\r
-#define AFX_cximagemfcdll_H__E98F71A6_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_\r
-\r
-#if _MSC_VER > 1000\r
-#pragma once\r
-#endif // _MSC_VER > 1000\r
-\r
-#ifndef __AFXWIN_H__\r
-       #error include 'stdafx.h' before including this file for PCH\r
-#endif\r
-\r
-#include "resource.h"          // main symbols\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// CcximagemfcdllApp\r
-// See cximagemfcdll.cpp for the implementation of this class\r
-//\r
-\r
-class CcximagemfcdllApp : public CWinApp\r
-{\r
-public:\r
-       CcximagemfcdllApp();\r
-\r
-// Overrides\r
-       // ClassWizard generated virtual function overrides\r
-       //{{AFX_VIRTUAL(CcximagemfcdllApp)\r
-       //}}AFX_VIRTUAL\r
-\r
-       //{{AFX_MSG(CcximagemfcdllApp)\r
-               // NOTE - the ClassWizard will add and remove member functions here.\r
-               //    DO NOT EDIT what you see in these blocks of generated code !\r
-       //}}AFX_MSG\r
-       DECLARE_MESSAGE_MAP()\r
-};\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
-//{{AFX_INSERT_LOCATION}}\r
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.\r
-\r
-#endif // !defined(AFX_cximagemfcdll_H__E98F71A6_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_)\r
+// cximagemfcdll.h : main header file for the cximagemfcdll DLL
+//
+
+#if !defined(AFX_cximagemfcdll_H__E98F71A6_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_)
+#define AFX_cximagemfcdll_H__E98F71A6_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#ifndef __AFXWIN_H__
+       #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h"          // main symbols
+
+/////////////////////////////////////////////////////////////////////////////
+// CcximagemfcdllApp
+// See cximagemfcdll.cpp for the implementation of this class
+//
+
+class CcximagemfcdllApp : public CWinApp
+{
+public:
+       CcximagemfcdllApp();
+
+// Overrides
+       // ClassWizard generated virtual function overrides
+       //{{AFX_VIRTUAL(CcximagemfcdllApp)
+       //}}AFX_VIRTUAL
+
+       //{{AFX_MSG(CcximagemfcdllApp)
+               // NOTE - the ClassWizard will add and remove member functions here.
+               //    DO NOT EDIT what you see in these blocks of generated code !
+       //}}AFX_MSG
+       DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_cximagemfcdll_H__E98F71A6_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_)
index 2210599644129c8b0140005bad2e04831b73364e..ad1b6117cc9437b0df3b7e4b68877e94fab0d564 100644 (file)
-//Microsoft Developer Studio generated resource script.\r
-//\r
-#include "resrc1.h"\r
-\r
-#define APSTUDIO_READONLY_SYMBOLS\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Generated from the TEXTINCLUDE 2 resource.\r
-//\r
-#include "resource.h"\r
-#include "afxres.h"\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-#undef APSTUDIO_READONLY_SYMBOLS\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Neutral resources\r
-\r
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)\r
-#ifdef _WIN32\r
-LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL\r
-#pragma code_page(1252)\r
-#endif //_WIN32\r
-\r
-#ifndef _MAC\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Version\r
-//\r
-\r
-VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 6,0,0,0\r
- PRODUCTVERSION 6,0,0,0\r
- FILEFLAGSMASK 0x3fL\r
-#ifdef _DEBUG\r
- FILEFLAGS 0x1L\r
-#else\r
- FILEFLAGS 0x0L\r
-#endif\r
- FILEOS 0x4L\r
- FILETYPE 0x2L\r
- FILESUBTYPE 0x0L\r
-BEGIN\r
-    BLOCK "StringFileInfo"\r
-    BEGIN\r
-        BLOCK "000004b0"\r
-        BEGIN\r
-            VALUE "Comments", "CxImage 6.0.0.0  MFC DLL\0"\r
-            VALUE "CompanyName", "Pizzolato Davide - www.xdp.it\0"\r
-            VALUE "FileDescription", "cximage\0"\r
-            VALUE "FileVersion", "6, 0, 0, 0\0"\r
-            VALUE "InternalName", "cximage\0"\r
-            VALUE "LegalCopyright", "Copyright Â© 2001 - 2008\0"\r
-            VALUE "LegalTrademarks", "\0"\r
-            VALUE "OriginalFilename", "cximage.dll\0"\r
-            VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "cximage\0"\r
-            VALUE "ProductVersion", "6, 0, 0, 0\0"\r
-            VALUE "SpecialBuild", "\0"\r
-        END\r
-    END\r
-    BLOCK "VarFileInfo"\r
-    BEGIN\r
-        VALUE "Translation", 0x0, 1200\r
-    END\r
-END\r
-\r
-#endif    // !_MAC\r
-\r
-#endif    // Neutral resources\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Italian (Italy) resources\r
-\r
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)\r
-#ifdef _WIN32\r
-LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN\r
-#pragma code_page(1252)\r
-#endif //_WIN32\r
-\r
-#ifdef APSTUDIO_INVOKED\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// TEXTINCLUDE\r
-//\r
-\r
-1 TEXTINCLUDE DISCARDABLE \r
-BEGIN\r
-    "resrc1.h\0"\r
-END\r
-\r
-2 TEXTINCLUDE DISCARDABLE \r
-BEGIN\r
-    "#include ""resource.h""\r\n"\r
-    "#include ""afxres.h""\r\n"\r
-    "\0"\r
-END\r
-\r
-3 TEXTINCLUDE DISCARDABLE \r
-BEGIN\r
-    "\r\n"\r
-    "\0"\r
-END\r
-\r
-#endif    // APSTUDIO_INVOKED\r
-\r
-#endif    // Italian (Italy) resources\r
-/////////////////////////////////////////////////////////////////////////////\r
-\r
-\r
-\r
-#ifndef APSTUDIO_INVOKED\r
-/////////////////////////////////////////////////////////////////////////////\r
-//\r
-// Generated from the TEXTINCLUDE 3 resource.\r
-//\r
-\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-#endif    // not APSTUDIO_INVOKED\r
-\r
+//Microsoft Developer Studio generated resource script.
+//
+#include "resrc1.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "resource.h"
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 6,0,0,0
+ PRODUCTVERSION 6,0,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "000004b0"
+        BEGIN
+            VALUE "Comments", "CxImage 6.0.0.0  MFC DLL\0"
+            VALUE "CompanyName", "Pizzolato Davide - www.xdp.it\0"
+            VALUE "FileDescription", "cximage\0"
+            VALUE "FileVersion", "6, 0, 0, 0\0"
+            VALUE "InternalName", "cximage\0"
+            VALUE "LegalCopyright", "Copyright Â© 2001 - 2008\0"
+            VALUE "LegalTrademarks", "\0"
+            VALUE "OriginalFilename", "cximage.dll\0"
+            VALUE "PrivateBuild", "\0"
+            VALUE "ProductName", "cximage\0"
+            VALUE "ProductVersion", "6, 0, 0, 0\0"
+            VALUE "SpecialBuild", "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0, 1200
+    END
+END
+
+#endif    // !_MAC
+
+#endif    // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Italian (Italy) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ITA)
+#ifdef _WIN32
+LANGUAGE LANG_ITALIAN, SUBLANG_ITALIAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resrc1.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""resource.h""\r\n"
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+#endif    // Italian (Italy) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
index a5e4a0861a4b4dc73cf89dc4a39101545442aa52..fb2fa8c1a1944232f0ea7d0e77346059bd5d7810 100644 (file)
@@ -1,8 +1,8 @@
-// stdafx.cpp : source file that includes just the standard includes\r
-//     cximagemfcdll.pch will be the pre-compiled header\r
-//     stdafx.obj will contain the pre-compiled type information\r
-\r
-#include "stdafx.h"\r
-\r
-\r
-\r
+// stdafx.cpp : source file that includes just the standard includes
+//     cximagemfcdll.pch will be the pre-compiled header
+//     stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
+
index ad71840f5bbbda97bf48208bdf9ed1f0f231cfa6..261544bcb894f4e5a7ae6441ac700ab77b87f3b3 100644 (file)
@@ -1,46 +1,46 @@
-// stdafx.h : include file for standard system include files,\r
-//  or project specific include files that are used frequently, but\r
-//      are changed infrequently\r
-//\r
-\r
-#if !defined(AFX_STDAFX_H__E98F71A8_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_)\r
-#define AFX_STDAFX_H__E98F71A8_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_\r
-\r
-#if _MSC_VER > 1000\r
-#pragma once\r
-#endif // _MSC_VER > 1000\r
-\r
-#define VC_EXTRALEAN           // Exclude rarely-used stuff from Windows headers\r
-\r
-#ifndef WINVER\r
-#define WINVER 0x0400\r
-#endif\r
-\r
-#include <afxwin.h>         // MFC core and standard components\r
-#include <afxext.h>         // MFC extensions\r
-\r
-#ifndef _AFX_NO_OLE_SUPPORT\r
-#include <afxole.h>         // MFC OLE classes\r
-#include <afxodlgs.h>       // MFC OLE dialog classes\r
-#include <afxdisp.h>        // MFC Automation classes\r
-#endif // _AFX_NO_OLE_SUPPORT\r
-\r
-\r
-#ifndef _AFX_NO_DB_SUPPORT\r
-#include <afxdb.h>                     // MFC ODBC database classes\r
-#endif // _AFX_NO_DB_SUPPORT\r
-\r
-#ifndef _AFX_NO_DAO_SUPPORT\r
-#include <afxdao.h>                    // MFC DAO database classes\r
-#endif // _AFX_NO_DAO_SUPPORT\r
-\r
-#include <afxdtctl.h>          // MFC support for Internet Explorer 4 Common Controls\r
-#ifndef _AFX_NO_AFXCMN_SUPPORT\r
-#include <afxcmn.h>                    // MFC support for Windows Common Controls\r
-#endif // _AFX_NO_AFXCMN_SUPPORT\r
-\r
-\r
-//{{AFX_INSERT_LOCATION}}\r
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.\r
-\r
-#endif // !defined(AFX_STDAFX_H__E98F71A8_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_)\r
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__E98F71A8_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_)
+#define AFX_STDAFX_H__E98F71A8_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define VC_EXTRALEAN           // Exclude rarely-used stuff from Windows headers
+
+#ifndef WINVER
+#define WINVER 0x0400
+#endif
+
+#include <afxwin.h>         // MFC core and standard components
+#include <afxext.h>         // MFC extensions
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxole.h>         // MFC OLE classes
+#include <afxodlgs.h>       // MFC OLE dialog classes
+#include <afxdisp.h>        // MFC Automation classes
+#endif // _AFX_NO_OLE_SUPPORT
+
+
+#ifndef _AFX_NO_DB_SUPPORT
+#include <afxdb.h>                     // MFC ODBC database classes
+#endif // _AFX_NO_DB_SUPPORT
+
+#ifndef _AFX_NO_DAO_SUPPORT
+#include <afxdao.h>                    // MFC DAO database classes
+#endif // _AFX_NO_DAO_SUPPORT
+
+#include <afxdtctl.h>          // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>                    // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__E98F71A8_B361_11D6_BB83_CAEE2E1CB77B__INCLUDED_)
index 60e3632ab4149d6b3e077311987ff92b54268f59..b252a8f00f50c365012bafc82fc8e29205b223f4 100644 (file)
@@ -1,24 +1,24 @@
-// stdafx.h : include file for standard system include files,\r
-//  or project specific include files that are used frequently, but\r
-//      are changed infrequently\r
-//\r
-\r
-#if !defined(AFX_STDAFX_H__F30A8A60_284F_4DF6_9431_6283105686F6__INCLUDED_)\r
-#define AFX_STDAFX_H__F30A8A60_284F_4DF6_9431_6283105686F6__INCLUDED_\r
-\r
-#if _MSC_VER > 1000\r
-#pragma once\r
-#endif // _MSC_VER > 1000\r
-\r
-\r
-// Insert your headers here\r
-#define WIN32_LEAN_AND_MEAN            // Exclude rarely-used stuff from Windows headers\r
-\r
-#include <windows.h>\r
-\r
-// TODO: reference additional headers your program requires here\r
-\r
-//{{AFX_INSERT_LOCATION}}\r
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.\r
-\r
-#endif // !defined(AFX_STDAFX_H__F30A8A60_284F_4DF6_9431_6283105686F6__INCLUDED_)\r
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__F30A8A60_284F_4DF6_9431_6283105686F6__INCLUDED_)
+#define AFX_STDAFX_H__F30A8A60_284F_4DF6_9431_6283105686F6__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+// Insert your headers here
+#define WIN32_LEAN_AND_MEAN            // Exclude rarely-used stuff from Windows headers
+
+#include <windows.h>
+
+// TODO: reference additional headers your program requires here
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__F30A8A60_284F_4DF6_9431_6283105686F6__INCLUDED_)
index 26a150dcda3179565da728468a2ca042b5e3a190..21321b69c49c448c09a339ad7adae5dbdcdca832 100644 (file)
-# Microsoft Developer Studio Project File - Name="CxImageMfcDll" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
-\r
-CFG=CxImageMfcDll - Win32 Unicode Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "cximagemfcdll.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "cximagemfcdll.mak" CFG="CxImageMfcDll - Win32 Unicode Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "CxImageMfcDll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "CxImageMfcDll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "CxImageMfcDll - Win32 Unicode Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "CxImageMfcDll - Win32 Unicode Release" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-MTL=midl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "CxImageMfcDll - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 6\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 6\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c\r
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /D _WIN32_IE=0x0400 /FD /GZ /c\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x410 /d "_DEBUG" /d "_AFXDLL"\r
-# ADD RSC /l 0x809 /d "_DEBUG" /d "_AFXDLL"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept\r
-# ADD LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../bin/cximaged.dll" /pdbtype:sept\r
-\r
-!ELSEIF  "$(CFG)" == "CxImageMfcDll - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 6\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 6\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /c\r
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /D _WIN32_IE=0x0400 /FD /c\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x410 /d "NDEBUG" /d "_AFXDLL"\r
-# ADD RSC /l 0x809 /d "NDEBUG" /d "_AFXDLL"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 /nologo /subsystem:windows /dll /machine:I386\r
-# ADD LINK32 /nologo /subsystem:windows /dll /machine:I386 /out:"../../bin/cximage.dll"\r
-\r
-!ELSEIF  "$(CFG)" == "CxImageMfcDll - Win32 Unicode Debug"\r
-\r
-# PROP BASE Use_MFC 6\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "CxImageMfcDll___Win32_Unicode_Debug"\r
-# PROP BASE Intermediate_Dir "CxImageMfcDll___Win32_Unicode_Debug"\r
-# PROP BASE Ignore_Export_Lib 0\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 6\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Unicode_Debug"\r
-# PROP Intermediate_Dir "Unicode_Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /FD /GZ /c\r
-# SUBTRACT BASE CPP /YX /Yc /Yu\r
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D _WIN32_IE=0x0400 /FD /GZ /c\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x410 /d "_DEBUG" /d "_AFXDLL"\r
-# ADD RSC /l 0x809 /d "_DEBUG" /d "_AFXDLL"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../bin/cximaged.dll" /pdbtype:sept\r
-# ADD LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../bin/cximagedu.dll" /pdbtype:sept\r
-\r
-!ELSEIF  "$(CFG)" == "CxImageMfcDll - Win32 Unicode Release"\r
-\r
-# PROP BASE Use_MFC 6\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "CxImageMfcDll___Win32_Unicode_Release"\r
-# PROP BASE Intermediate_Dir "CxImageMfcDll___Win32_Unicode_Release"\r
-# PROP BASE Ignore_Export_Lib 0\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 6\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Unicode_Release"\r
-# PROP Intermediate_Dir "Unicode_Release"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /FD /c\r
-# SUBTRACT BASE CPP /YX /Yc /Yu\r
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D _WIN32_IE=0x0400 /FD /c\r
-# SUBTRACT CPP /YX /Yc /Yu\r
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x410 /d "NDEBUG" /d "_AFXDLL"\r
-# ADD RSC /l 0x809 /d "NDEBUG" /d "_AFXDLL"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 /nologo /subsystem:windows /dll /machine:I386 /out:"../../bin/cximage.dll"\r
-# ADD LINK32 /nologo /subsystem:windows /dll /machine:I386 /out:"../../bin/cximageu.dll"\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "CxImageMfcDll - Win32 Debug"\r
-# Name "CxImageMfcDll - Win32 Release"\r
-# Name "CxImageMfcDll - Win32 Unicode Debug"\r
-# Name "CxImageMfcDll - Win32 Unicode Release"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\cximagemfcdll.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\cximagemfcdll.rc\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\StdAfx.cpp\r
-# ADD CPP /Yc"stdafx.h"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\tif_xfile.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximabmp.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximadsp.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaenc.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaexif.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximage.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximagif.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximahist.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaico.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximainfo.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaint.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajas.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajbg.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajpg.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximalpha.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximalyr.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximamng.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapal.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapcx.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapng.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaraw.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximasel.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaska.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatga.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximath.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatif.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatran.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawbmp.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawmf.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawnd.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\xmemfile.cpp\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\cximagemfcdll.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\Resource.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\StdAfx.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\xfile.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximabmp.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximadefs.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximage.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximagif.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaico.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaiter.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajas.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximajpg.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximamng.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapcx.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximapng.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximaska.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatga.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximath.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximatif.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawbmp.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\ximawmf.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\xiofile.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\xmemfile.h\r
-# End Source File\r
-# End Group\r
-# Begin Group "Resource Files"\r
-\r
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
-# End Group\r
-# End Target\r
-# End Project\r
+# Microsoft Developer Studio Project File - Name="CxImageMfcDll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=CxImageMfcDll - Win32 Unicode Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "cximagemfcdll.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "cximagemfcdll.mak" CFG="CxImageMfcDll - Win32 Unicode Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "CxImageMfcDll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "CxImageMfcDll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "CxImageMfcDll - Win32 Unicode Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "CxImageMfcDll - Win32 Unicode Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "CxImageMfcDll - Win32 Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /D _WIN32_IE=0x0400 /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x410 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x809 /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../bin/cximaged.dll" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "CxImageMfcDll - Win32 Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /D _WIN32_IE=0x0400 /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x410 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x809 /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 /nologo /subsystem:windows /dll /machine:I386 /out:"../../bin/cximage.dll"
+
+!ELSEIF  "$(CFG)" == "CxImageMfcDll - Win32 Unicode Debug"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "CxImageMfcDll___Win32_Unicode_Debug"
+# PROP BASE Intermediate_Dir "CxImageMfcDll___Win32_Unicode_Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Unicode_Debug"
+# PROP Intermediate_Dir "Unicode_Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /FD /GZ /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../zlib" /I "../../jasper/include" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D _WIN32_IE=0x0400 /FD /GZ /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x410 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x809 /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../bin/cximaged.dll" /pdbtype:sept
+# ADD LINK32 /nologo /subsystem:windows /dll /debug /machine:I386 /out:"../../bin/cximagedu.dll" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "CxImageMfcDll - Win32 Unicode Release"
+
+# PROP BASE Use_MFC 6
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "CxImageMfcDll___Win32_Unicode_Release"
+# PROP BASE Intermediate_Dir "CxImageMfcDll___Win32_Unicode_Release"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Unicode_Release"
+# PROP Intermediate_Dir "Unicode_Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_MBCS" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /FD /c
+# SUBTRACT BASE CPP /YX /Yc /Yu
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../zlib" /I "../../jasper/include" /D "_WINDOWS" /D "_WINDLL" /D "_AFXDLL" /D "_USRDLL" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D _WIN32_IE=0x0400 /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x410 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x809 /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /dll /machine:I386 /out:"../../bin/cximage.dll"
+# ADD LINK32 /nologo /subsystem:windows /dll /machine:I386 /out:"../../bin/cximageu.dll"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "CxImageMfcDll - Win32 Debug"
+# Name "CxImageMfcDll - Win32 Release"
+# Name "CxImageMfcDll - Win32 Unicode Debug"
+# Name "CxImageMfcDll - Win32 Unicode Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\cximagemfcdll.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\cximagemfcdll.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"stdafx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=..\tif_xfile.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximabmp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximadsp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaenc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaexif.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximage.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximagif.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximahist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaico.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximainfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaint.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajas.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajbg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajpg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximalpha.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximalyr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximamng.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapal.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapcx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapng.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaraw.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximasel.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaska.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatga.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatif.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatran.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawbmp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawmf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawnd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\xmemfile.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\cximagemfcdll.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\xfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximabmp.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximadefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximagif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaico.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaiter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajas.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximajpg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximamng.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapcx.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximapng.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximaska.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatga.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximatif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawbmp.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\ximawmf.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\xiofile.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\xmemfile.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
index cc1626b582e5535b6676e6702bbf283dc73b0141..4a5384e72a00c92a5a8ae0a6b039660ba68db607 100644 (file)
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by CxImageMFCdll.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        6000\r
-#define _APS_NEXT_COMMAND_VALUE         32771\r
-#define _APS_NEXT_CONTROL_VALUE         6000\r
-#define _APS_NEXT_SYMED_VALUE           6000\r
-#endif\r
-#endif\r
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by CxImageMFCdll.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        6000
+#define _APS_NEXT_COMMAND_VALUE         32771
+#define _APS_NEXT_CONTROL_VALUE         6000
+#define _APS_NEXT_SYMED_VALUE           6000
+#endif
+#endif
index 39ff26ed0dbc9e12f85adf33dde33cabde06c1ae..0f1dd487700545476b79ae9bcc72f60a3001cbec 100644 (file)
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by CxImageCrtDll.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        6000\r
-#define _APS_NEXT_COMMAND_VALUE         32771\r
-#define _APS_NEXT_CONTROL_VALUE         6000\r
-#define _APS_NEXT_SYMED_VALUE           6000\r
-#endif\r
-#endif\r
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by CxImageCrtDll.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        6000
+#define _APS_NEXT_COMMAND_VALUE         32771
+#define _APS_NEXT_CONTROL_VALUE         6000
+#define _APS_NEXT_SYMED_VALUE           6000
+#endif
+#endif
index c93da4fb25148f93b3429660fa24d58f9eab10c4..78b9b9d1dbcadd0f4fb708c92226100191ef9aa3 100644 (file)
-# Microsoft Developer Studio Project File - Name="CxImage" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Static Library" 0x0104\r
-\r
-CFG=CxImage - Win32 Unicode Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "cximage.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "cximage.mak" CFG="CxImage - Win32 Unicode Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "CxImage - Win32 Debug" (based on "Win32 (x86) Static Library")\r
-!MESSAGE "CxImage - Win32 Release" (based on "Win32 (x86) Static Library")\r
-!MESSAGE "CxImage - Win32 Unicode Debug" (based on "Win32 (x86) Static Library")\r
-!MESSAGE "CxImage - Win32 Unicode Release" (based on "Win32 (x86) Static Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "CxImage - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 2\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "WIN32" /D "_DEBUG" /D "_LIB" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /FD /GZ /c\r
-# SUBTRACT CPP /Fr /YX\r
-# ADD BASE RSC /l 0x410 /d "_DEBUG"\r
-# ADD RSC /l 0x809 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LIB32=link.exe -lib\r
-# ADD BASE LIB32 /nologo\r
-# ADD LIB32 /nologo\r
-\r
-!ELSEIF  "$(CFG)" == "CxImage - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 2\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "WIN32" /D "NDEBUG" /D "_LIB" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /FD /c\r
-# SUBTRACT CPP /YX\r
-# ADD BASE RSC /l 0x410 /d "NDEBUG"\r
-# ADD RSC /l 0x809 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LIB32=link.exe -lib\r
-# ADD BASE LIB32 /nologo\r
-# ADD LIB32 /nologo\r
-\r
-!ELSEIF  "$(CFG)" == "CxImage - Win32 Unicode Debug"\r
-\r
-# PROP BASE Use_MFC 2\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "CxImage___Win32_Unicode_Debug"\r
-# PROP BASE Intermediate_Dir "CxImage___Win32_Unicode_Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 2\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Unicode_Debug"\r
-# PROP Intermediate_Dir "Unicode_Debug"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "_AFXDLL" /D "JAS_WIN_MSVC_BUILD" /FD /GZ /c\r
-# SUBTRACT BASE CPP /Fr /YX\r
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "_LIB" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NON_CONFORMING_SWPRINTFS" /FD /GZ /c\r
-# SUBTRACT CPP /Fr /YX\r
-# ADD BASE RSC /l 0x410 /d "_DEBUG" /d "_AFXDLL"\r
-# ADD RSC /l 0x809 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LIB32=link.exe -lib\r
-# ADD BASE LIB32 /nologo\r
-# ADD LIB32 /nologo\r
-\r
-!ELSEIF  "$(CFG)" == "CxImage - Win32 Unicode Release"\r
-\r
-# PROP BASE Use_MFC 2\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "CxImage___Win32_Unicode_Release"\r
-# PROP BASE Intermediate_Dir "CxImage___Win32_Unicode_Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 2\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Unicode_Release"\r
-# PROP Intermediate_Dir "Unicode_Release"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_AFXDLL" /D "JAS_WIN_MSVC_BUILD" /FD /c\r
-# SUBTRACT BASE CPP /YX\r
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "_LIB" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NON_CONFORMING_SWPRINTFS" /FD /c\r
-# SUBTRACT CPP /YX\r
-# ADD BASE RSC /l 0x410 /d "NDEBUG" /d "_AFXDLL"\r
-# ADD RSC /l 0x809 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LIB32=link.exe -lib\r
-# ADD BASE LIB32 /nologo\r
-# ADD LIB32 /nologo\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "CxImage - Win32 Debug"\r
-# Name "CxImage - Win32 Release"\r
-# Name "CxImage - Win32 Unicode Debug"\r
-# Name "CxImage - Win32 Unicode Release"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\tif_xfile.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximabmp.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximadsp.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaenc.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaexif.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\xImage.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximagif.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximahist.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaico.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximainfo.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaint.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximajas.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximajbg.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximajpg.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximalpha.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximalyr.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximamng.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximapal.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximapcx.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximapng.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaraw.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximasel.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaska.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximatga.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximath.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximatif.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximatran.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximawbmp.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximawmf.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximawnd.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\xmemfile.cpp\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\xfile.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximabmp.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximacfg.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximadef.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximage.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximagif.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaico.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaiter.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximajas.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximajbg.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximajpg.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximamng.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximapcx.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximapng.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaraw.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximaska.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximatga.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximath.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximatif.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximawbmp.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\ximawmf.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\xiofile.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\xmemfile.h\r
-# End Source File\r
-# End Group\r
-# End Target\r
-# End Project\r
+# Microsoft Developer Studio Project File - Name="CxImage" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=CxImage - Win32 Unicode Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "cximage.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "cximage.mak" CFG="CxImage - Win32 Unicode Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "CxImage - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "CxImage - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "CxImage - Win32 Unicode Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "CxImage - Win32 Unicode Release" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "CxImage - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "WIN32" /D "_DEBUG" /D "_LIB" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /FD /GZ /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x410 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "CxImage - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "WIN32" /D "NDEBUG" /D "_LIB" /D "JAS_WIN_MSVC_BUILD" /D "_CRT_SECURE_NO_DEPRECATE" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x410 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "CxImage - Win32 Unicode Debug"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "CxImage___Win32_Unicode_Debug"
+# PROP BASE Intermediate_Dir "CxImage___Win32_Unicode_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Unicode_Debug"
+# PROP Intermediate_Dir "Unicode_Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "_AFXDLL" /D "JAS_WIN_MSVC_BUILD" /FD /GZ /c
+# SUBTRACT BASE CPP /Fr /YX
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "_LIB" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "_DEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NON_CONFORMING_SWPRINTFS" /FD /GZ /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x410 /d "_DEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF  "$(CFG)" == "CxImage - Win32 Unicode Release"
+
+# PROP BASE Use_MFC 2
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "CxImage___Win32_Unicode_Release"
+# PROP BASE Intermediate_Dir "CxImage___Win32_Unicode_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 2
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Unicode_Release"
+# PROP Intermediate_Dir "Unicode_Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "_AFXDLL" /D "JAS_WIN_MSVC_BUILD" /FD /c
+# SUBTRACT BASE CPP /YX
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\jpeg" /I "..\png" /I "..\zlib" /I "..\mng" /I "..\tiff" /I "..\j2k" /I "..\jasper\include" /D "_LIB" /D "JAS_WIN_MSVC_BUILD" /D "WIN32" /D "NDEBUG" /D "_UNICODE" /D "UNICODE" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NON_CONFORMING_SWPRINTFS" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x410 /d "NDEBUG" /d "_AFXDLL"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF 
+
+# Begin Target
+
+# Name "CxImage - Win32 Debug"
+# Name "CxImage - Win32 Release"
+# Name "CxImage - Win32 Unicode Debug"
+# Name "CxImage - Win32 Unicode Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\tif_xfile.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximabmp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximadsp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaenc.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaexif.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\xImage.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximagif.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximahist.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaico.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximainfo.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaint.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximajas.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximajbg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximajpg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximalpha.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximalyr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximamng.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximapal.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximapcx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximapng.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaraw.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximasel.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaska.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximatga.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximatif.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximatran.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximawbmp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximawmf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximawnd.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmemfile.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\xfile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximabmp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximacfg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximadef.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximage.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximagif.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaico.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaiter.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximajas.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximajbg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximajpg.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximamng.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximapcx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximapng.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaraw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximaska.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximatga.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximath.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximatif.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximawbmp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ximawmf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xiofile.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmemfile.h
+# End Source File
+# End Group
+# End Target
+# End Project
index d855b5f0813f3372a3144f9bf63e4e5eddc88b70..cace8f0707e3fab6b3175b9094a56a9ad5b579cf 100644 (file)
@@ -1,29 +1,29 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00\r
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
-\r
-###############################################################################\r
-\r
-Project: "CxImage"=.\CxImage.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Global:\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<3>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "CxImage"=.\CxImage.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
index 8cf0659845d73a6393f1aba23992c58f5f7ee1f2..8cc0197bbfbe71e1beb280d1a330e474d581f232 100644 (file)
@@ -1,48 +1,48 @@
-This copy of the CxImage notices is provided for your convenience. In case of\r
-any discrepancy between this copy and the notices in the file ximage.h that is\r
-included in the CxImage distribution, the latter shall prevail.\r
-\r
-If you modify CxImage you may insert additional notices immediately following\r
-this sentence.\r
-\r
---------------------------------------------------------------------------------\r
-\r
-COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:\r
-\r
-CxImage version 6.0.0 02/Feb/2008\r
-\r
-CxImage : Copyright (C) 2001 - 2008, Davide Pizzolato\r
-\r
-Original CImage and CImageIterator implementation are:\r
-Copyright (C) 1995, Alejandro Aguilar Sierra (asierra(at)servidor(dot)unam(dot)mx)\r
-\r
-Covered code is provided under this license on an "as is" basis, without warranty\r
-of any kind, either expressed or implied, including, without limitation, warranties\r
-that the covered code is free of defects, merchantable, fit for a particular purpose\r
-or non-infringing. The entire risk as to the quality and performance of the covered\r
-code is with you. Should any covered code prove defective in any respect, you (not\r
-the initial developer or any other contributor) assume the cost of any necessary\r
-servicing, repair or correction. This disclaimer of warranty constitutes an essential\r
-part of this license. No use of any covered code is authorized hereunder except under\r
-this disclaimer.\r
-\r
-Permission is hereby granted to use, copy, modify, and distribute this\r
-source code, or portions hereof, for any purpose, including commercial applications,\r
-freely and without fee, subject to the following restrictions: \r
-\r
-1. The origin of this software must not be misrepresented; you must not\r
-claim that you wrote the original software. If you use this software\r
-in a product, an acknowledgment in the product documentation would be\r
-appreciated but is not required.\r
-\r
-2. Altered source versions must be plainly marked as such, and must not be\r
-misrepresented as being the original software.\r
-\r
-3. This notice may not be removed or altered from any source distribution.\r
-\r
---------------------------------------------------------------------------------\r
-\r
-Other information: about CxImage, and the latest version, can be found at the\r
-CxImage home page: http://www.xdp.it\r
-\r
---------------------------------------------------------------------------------\r
+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 6.0.0 02/Feb/2008
+
+CxImage : Copyright (C) 2001 - 2008, 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
+
+--------------------------------------------------------------------------------
index 98c83c1bf52df9e352ec9cde4f0bda486ea7191a..ac92c954b00e17ff44cd91f14a7009ca0d3338e6 100644 (file)
-/*\r
- * TIFF file IO, using CxFile.\r
- */\r
-\r
-#ifdef WIN32\r
- #include <windows.h>\r
-#endif\r
-#include <stdio.h>\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_TIF\r
-\r
-#include "../tiff/tiffiop.h"\r
-\r
-#include "xfile.h"\r
-\r
-static tsize_t \r
-_tiffReadProcEx(thandle_t fd, tdata_t buf, tsize_t size)\r
-{\r
-       return (tsize_t)((CxFile*)fd)->Read(buf, 1, size);\r
-}\r
-\r
-static tsize_t\r
-_tiffWriteProcEx(thandle_t fd, tdata_t buf, tsize_t size)\r
-{\r
-       return (tsize_t)((CxFile*)fd)->Write(buf, 1, size);\r
-}\r
-\r
-static toff_t\r
-_tiffSeekProcEx(thandle_t fd, toff_t off, int whence)\r
-{\r
-       if ( off == 0xFFFFFFFF ) \r
-               return 0xFFFFFFFF;\r
-       if (!((CxFile*)fd)->Seek(off, whence))\r
-               return 0xFFFFFFFF;\r
-       if (whence == SEEK_SET)\r
-               return off;\r
-\r
-       return (toff_t)((CxFile*)fd)->Tell();\r
-}\r
-\r
-// Return nonzero if error\r
-static int\r
-_tiffCloseProcEx(thandle_t /*fd*/)\r
-{\r
-//     return !((CxFile*)fd)->Close(); // "//" needed for memory files <DP>\r
-       return 0;\r
-}\r
-\r
-#include <sys/stat.h>\r
-\r
-static toff_t\r
-_tiffSizeProcEx(thandle_t fd)\r
-{\r
-       return ((CxFile*)fd)->Size();\r
-}\r
-\r
-static int\r
-_tiffMapProcEx(thandle_t /*fd*/, tdata_t* /*pbase*/, toff_t* /*psize*/)\r
-{\r
-       return (0);\r
-}\r
-\r
-static void\r
-_tiffUnmapProcEx(thandle_t /*fd*/, tdata_t /*base*/, toff_t /*size*/)\r
-{\r
-}\r
-\r
-// Open a TIFF file descriptor for read/writing.\r
-/*\r
-TIFF*\r
-TIFFOpen(const char* name, const char* mode)\r
-{\r
-       static const char module[] = "TIFFOpen";\r
-   FILE* stream = fopen(name, mode);\r
-       if (stream == NULL) \r
-   {\r
-               TIFFError(module, "%s: Cannot open", name);\r
-               return NULL;\r
-       }\r
-       return (TIFFFdOpen((int)stream, name, mode));\r
-}\r
-*/\r
-\r
-TIFF*\r
-_TIFFFdOpen(void* fd, const char* name, const char* mode)\r
-{\r
-       TIFF* tif;\r
-\r
-       tif = TIFFClientOpen(name, mode,\r
-           (thandle_t) fd,\r
-           _tiffReadProcEx, _tiffWriteProcEx, _tiffSeekProcEx, _tiffCloseProcEx,\r
-           _tiffSizeProcEx, _tiffMapProcEx, _tiffUnmapProcEx);\r
-       if (tif)\r
-               tif->tif_fd = fd;\r
-       return (tif);\r
-}\r
-\r
-extern "C" TIFF* _TIFFOpenEx(CxFile* stream, const char* mode)\r
-{\r
-       return (_TIFFFdOpen(stream, "TIFF IMAGE", mode));\r
-}\r
-\r
-#ifdef __GNUC__\r
-extern char* malloc();\r
-extern char* realloc();\r
-#else\r
-#include <malloc.h>\r
-#endif\r
-\r
-tdata_t\r
-_TIFFmalloc(tsize_t s)\r
-{\r
-       return (malloc((size_t) s));\r
-}\r
-\r
-void\r
-_TIFFfree(tdata_t p)\r
-{\r
-       free(p);\r
-}\r
-\r
-tdata_t\r
-_TIFFrealloc(tdata_t p, tsize_t s)\r
-{\r
-       return (realloc(p, (size_t) s));\r
-}\r
-\r
-void\r
-_TIFFmemset(tdata_t p, int v, tsize_t c)\r
-{\r
-       memset(p, v, (size_t) c);\r
-}\r
-\r
-void\r
-_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)\r
-{\r
-       memcpy(d, s, (size_t) c);\r
-}\r
-\r
-int\r
-_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)\r
-{\r
-       return (memcmp(p1, p2, (size_t) c));\r
-}\r
-\r
-#ifndef UNICODE\r
-#define DbgPrint wvsprintf\r
-#define DbgPrint2 wsprintf\r
-#define DbgMsgBox MessageBox\r
-#else\r
-#define DbgPrint wvsprintfA\r
-#define DbgPrint2 wsprintfA\r
-#define DbgMsgBox MessageBoxA\r
-#endif\r
-\r
-static void\r
-Win32WarningHandler(const char* module, const char* fmt, va_list ap)\r
-{\r
-#ifdef _DEBUG\r
-#if (!defined(_CONSOLE) && !defined(_WIN32_WCE) && defined(WIN32))\r
-       LPSTR szTitle;\r
-       LPSTR szTmp;\r
-       LPCSTR szTitleText = "%s Warning";\r
-       LPCSTR szDefaultModule = "TIFFLIB";\r
-       szTmp = (module == NULL) ? (LPSTR)szDefaultModule : (LPSTR)module;\r
-       if ((szTitle = (LPSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmp) +\r
-                       strlen(szTitleText) + strlen(fmt) + 128))) == NULL)\r
-               return;\r
-       DbgPrint2(szTitle, szTitleText, szTmp);\r
-       szTmp = szTitle + (strlen(szTitle)+2);\r
-       DbgPrint(szTmp, fmt, ap);\r
-       DbgMsgBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION);\r
-       LocalFree(szTitle);\r
-       return;\r
-#else\r
-       if (module != NULL)\r
-               fprintf(stderr, "%s: ", module);\r
-       fprintf(stderr, "Warning, ");\r
-       vfprintf(stderr, fmt, ap);\r
-       fprintf(stderr, ".\n");\r
-#endif\r
-#endif\r
-}\r
-TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;\r
-\r
-static void\r
-Win32ErrorHandler(const char* module, const char* fmt, va_list ap)\r
-{\r
-#ifdef _DEBUG\r
-#if (!defined(_CONSOLE) && !defined(_WIN32_WCE) && defined(WIN32))\r
-       LPSTR szTitle;\r
-       LPSTR szTmp;\r
-       LPCSTR szTitleText = "%s Error";\r
-       LPCSTR szDefaultModule = "TIFFLIB";\r
-       szTmp = (module == NULL) ? (LPSTR)szDefaultModule : (LPSTR)module;\r
-       if ((szTitle = (LPSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmp) +\r
-                       strlen(szTitleText) + strlen(fmt) + 128))) == NULL)\r
-               return;\r
-       DbgPrint2(szTitle, szTitleText, szTmp);\r
-       szTmp = szTitle + (strlen(szTitle)+2);\r
-       DbgPrint(szTmp, fmt, ap);\r
-       DbgMsgBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION);\r
-       LocalFree(szTitle);\r
-       return;\r
-#else\r
-       if (module != NULL)\r
-               fprintf(stderr, "%s: ", module);\r
-       vfprintf(stderr, fmt, ap);\r
-       fprintf(stderr, ".\n");\r
-#endif\r
-#endif\r
-}\r
-TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;\r
-\r
-#endif\r
-\r
+/*
+ * 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 "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 = 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
+
index c0e4e2239f2fdd2e3d7618fe74b1ec37434c3862..b64594ee97bde042b9a5ca62e3239267df622edb 100644 (file)
@@ -1,79 +1,79 @@
-/*\r
- * File:       xfile.h\r
- * Purpose:    General Purpose File Class \r
- */\r
-/*\r
-  --------------------------------------------------------------------------------\r
-\r
-       COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:\r
-\r
-       CxFile (c)  11/May/2002 Davide Pizzolato - www.xdp.it\r
-       CxFile version 2.00 23/Aug/2002\r
-       CxFile version 2.10 16/Dec/2007\r
-       \r
-       Special thanks to Chris Shearer Cooper for new features, enhancements and bugfixes\r
-\r
-       Covered code is provided under this license on an "as is" basis, without warranty\r
-       of any kind, either expressed or implied, including, without limitation, warranties\r
-       that the covered code is free of defects, merchantable, fit for a particular purpose\r
-       or non-infringing. The entire risk as to the quality and performance of the covered\r
-       code is with you. Should any covered code prove defective in any respect, you (not\r
-       the initial developer or any other contributor) assume the cost of any necessary\r
-       servicing, repair or correction. This disclaimer of warranty constitutes an essential\r
-       part of this license. No use of any covered code is authorized hereunder except under\r
-       this disclaimer.\r
-\r
-       Permission is hereby granted to use, copy, modify, and distribute this\r
-       source code, or portions hereof, for any purpose, including commercial applications,\r
-       freely and without fee, subject to the following restrictions: \r
-\r
-       1. The origin of this software must not be misrepresented; you must not\r
-       claim that you wrote the original software. If you use this software\r
-       in a product, an acknowledgment in the product documentation would be\r
-       appreciated but is not required.\r
-\r
-       2. Altered source versions must be plainly marked as such, and must not be\r
-       misrepresented as being the original software.\r
-\r
-       3. This notice may not be removed or altered from any source distribution.\r
-  --------------------------------------------------------------------------------\r
- */\r
-#if !defined(__xfile_h)\r
-#define __xfile_h\r
-\r
-#if defined (WIN32) || defined (_WIN32_WCE)\r
- #include <windows.h>\r
-#endif\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-\r
-#include "ximadef.h"\r
-\r
-class DLL_EXP CxFile\r
-{\r
-public:\r
-       CxFile(void) { };\r
-       virtual ~CxFile() { };\r
-\r
-       virtual bool    Close() = 0;\r
-       virtual size_t  Read(void *buffer, size_t size, size_t count) = 0;\r
-       virtual size_t  Write(const void *buffer, size_t size, size_t count) = 0;\r
-       virtual bool    Seek(long offset, int origin) = 0;\r
-       virtual long    Tell() = 0;\r
-       virtual long    Size() = 0;\r
-       virtual bool    Flush() = 0;\r
-       virtual bool    Eof() = 0;\r
-       virtual long    Error() = 0;\r
-       virtual bool    PutC(unsigned char c)\r
-               {\r
-               // Default implementation\r
-               size_t nWrote = Write(&c, 1, 1);\r
-               return (bool)(nWrote == 1);\r
-               }\r
-       virtual long    GetC() = 0;\r
-       virtual char *  GetS(char *string, int n) = 0;\r
-       virtual long    Scanf(const char *format, void* output) = 0;\r
-};\r
-\r
-#endif //__xfile_h\r
+/*
+ * 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(long offset, int origin) = 0;
+       virtual long    Tell() = 0;
+       virtual long    Size() = 0;
+       virtual bool    Flush() = 0;
+       virtual bool    Eof() = 0;
+       virtual long    Error() = 0;
+       virtual bool    PutC(unsigned char c)
+               {
+               // Default implementation
+               size_t nWrote = Write(&c, 1, 1);
+               return (bool)(nWrote == 1);
+               }
+       virtual long    GetC() = 0;
+       virtual char *  GetS(char *string, int n) = 0;
+       virtual long    Scanf(const char *format, void* output) = 0;
+};
+
+#endif //__xfile_h
index 4793707bfa4bc7884e4bbaca33ae6572e501faf3..a621ba5586d3ff97699a6718118e5839d4755e21 100644 (file)
-/*\r
- * File:       ximabmp.cpp\r
- * Purpose:    Platform Independent BMP Image Class Loader and Writer\r
- * 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximabmp.h"\r
-\r
-#if CXIMAGE_SUPPORT_BMP\r
-\r
-#include "ximaiter.h" \r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageBMP::Encode(CxFile * hFile)\r
-{\r
-\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       BITMAPFILEHEADER        hdr;\r
-\r
-       hdr.bfType = 0x4d42;   // 'BM' WINDOWS_BITMAP_SIGNATURE\r
-       hdr.bfSize = GetSize() + 14 /*sizeof(BITMAPFILEHEADER)*/;\r
-       hdr.bfReserved1 = hdr.bfReserved2 = 0;\r
-       hdr.bfOffBits = 14 /*sizeof(BITMAPFILEHEADER)*/ + head.biSize + GetPaletteSize();\r
-\r
-       hdr.bfType = ntohs(hdr.bfType); \r
-       hdr.bfSize = ntohl(hdr.bfSize); \r
-       hdr.bfOffBits = ntohl(hdr.bfOffBits); \r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (GetNumColors()==0 && AlphaIsValid()){\r
-       \r
-               BITMAPINFOHEADER  infohdr;\r
-               memcpy(&infohdr,&head,sizeof(BITMAPINFOHEADER));\r
-               infohdr.biCompression = BI_RGB;\r
-               infohdr.biBitCount = 32;\r
-               DWORD dwEffWidth = ((((infohdr.biBitCount * infohdr.biWidth) + 31) / 32) * 4);\r
-               infohdr.biSizeImage = dwEffWidth * infohdr.biHeight;\r
-\r
-               hdr.bfSize = infohdr.biSize + infohdr.biSizeImage + 14 /*sizeof(BITMAPFILEHEADER)*/;\r
-\r
-               hdr.bfSize = ntohl(hdr.bfSize);\r
-               bihtoh(&infohdr);\r
-\r
-               // Write the file header\r
-               hFile->Write(&hdr,min(14,sizeof(BITMAPFILEHEADER)),1);\r
-               hFile->Write(&infohdr,sizeof(BITMAPINFOHEADER),1);\r
-                //and DIB+ALPHA interlaced\r
-               BYTE *srcalpha = AlphaGetPointer();\r
-               for(long y = 0; y < infohdr.biHeight; ++y){\r
-                       BYTE *srcdib = GetBits(y);\r
-                       for(long x = 0; x < infohdr.biWidth; ++x){\r
-                               hFile->Write(srcdib,3,1);\r
-                               hFile->Write(srcalpha,1,1);\r
-                               srcdib += 3;\r
-                               ++srcalpha;\r
-                       }\r
-               }\r
-\r
-       } else \r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       {\r
-               // Write the file header\r
-               hFile->Write(&hdr,min(14,sizeof(BITMAPFILEHEADER)),1);\r
-               //copy attributes\r
-               memcpy(pDib,&head,sizeof(BITMAPINFOHEADER));\r
-               bihtoh((BITMAPINFOHEADER*)pDib);\r
-               // Write the DIB header and the pixels\r
-               hFile->Write(pDib,GetSize(),1);\r
-               bihtoh((BITMAPINFOHEADER*)pDib);\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageBMP::Decode(CxFile * hFile)\r
-{\r
-       if (hFile == NULL) return false;\r
-\r
-       BITMAPFILEHEADER   bf;\r
-       DWORD off = hFile->Tell(); //<CSC>\r
-  cx_try {\r
-       if (hFile->Read(&bf,min(14,sizeof(bf)),1)==0) cx_throw("Not a BMP");\r
-\r
-       bf.bfSize = ntohl(bf.bfSize); \r
-       bf.bfOffBits = ntohl(bf.bfOffBits); \r
-\r
-    if (bf.bfType != BFT_BITMAP) { //do we have a RC HEADER?\r
-        bf.bfOffBits = 0L;\r
-        hFile->Seek(off,SEEK_SET);\r
-    }\r
-\r
-       BITMAPINFOHEADER bmpHeader;\r
-       if (!DibReadBitmapInfo(hFile,&bmpHeader)) cx_throw("Error reading BMP info");\r
-       DWORD dwCompression=bmpHeader.biCompression;\r
-       DWORD dwBitCount=bmpHeader.biBitCount; //preserve for BI_BITFIELDS compression <Thomas Ernst>\r
-       bool bIsOldBmp = bmpHeader.biSize == sizeof(BITMAPCOREHEADER);\r
-\r
-       bool bTopDownDib = bmpHeader.biHeight<0; //<Flanders> check if it's a top-down bitmap\r
-       if (bTopDownDib) bmpHeader.biHeight=-bmpHeader.biHeight;\r
-\r
-       if (info.nEscape == -1) {\r
-               // Return output dimensions only\r
-               head.biWidth = bmpHeader.biWidth;\r
-               head.biHeight = bmpHeader.biHeight;\r
-               info.dwType = CXIMAGE_FORMAT_BMP;\r
-               cx_throw("output dimensions returned");\r
-       }\r
-\r
-       if (!Create(bmpHeader.biWidth,bmpHeader.biHeight,bmpHeader.biBitCount,CXIMAGE_FORMAT_BMP))\r
-               cx_throw("");\r
-\r
-       SetXDPI((long) floor(bmpHeader.biXPelsPerMeter * 254.0 / 10000.0 + 0.5));\r
-       SetYDPI((long) floor(bmpHeader.biYPelsPerMeter * 254.0 / 10000.0 + 0.5));\r
-\r
-       if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding\r
-\r
-    RGBQUAD *pRgb = GetPalette();\r
-    if (pRgb){\r
-        if (bIsOldBmp){\r
-             // convert a old color table (3 byte entries) to a new\r
-             // color table (4 byte entries)\r
-            hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBTRIPLE),1);\r
-            for (int i=DibNumColors(&head)-1; i>=0; i--){\r
-                pRgb[i].rgbRed      = ((RGBTRIPLE *)pRgb)[i].rgbtRed;\r
-                pRgb[i].rgbBlue     = ((RGBTRIPLE *)pRgb)[i].rgbtBlue;\r
-                pRgb[i].rgbGreen    = ((RGBTRIPLE *)pRgb)[i].rgbtGreen;\r
-                pRgb[i].rgbReserved = (BYTE)0;\r
-            }\r
-        } else {\r
-            hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1);\r
-                       //force rgbReserved=0, to avoid problems with some WinXp bitmaps\r
-                       for (unsigned int i=0; i<head.biClrUsed; i++) pRgb[i].rgbReserved=0;\r
-        }\r
-    }\r
-\r
-       if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding\r
-\r
-       switch (dwBitCount) {\r
-               case 32 :\r
-                       DWORD bfmask[3];\r
-                       if (dwCompression == BI_BITFIELDS)\r
-                       {\r
-                               hFile->Read(bfmask, 12, 1);\r
-                       } else {\r
-                               bfmask[0]=0x00FF0000;\r
-                               bfmask[1]=0x0000FF00;\r
-                               bfmask[2]=0x000000FF;\r
-                       }\r
-                       if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);\r
-                       if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB){\r
-                               long imagesize=4*head.biHeight*head.biWidth;\r
-                               BYTE* buff32=(BYTE*)malloc(imagesize);\r
-                               if (buff32){\r
-                                       hFile->Read(buff32, imagesize,1); // read in the pixels\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       if (dwCompression == BI_RGB){\r
-                                               AlphaCreate();\r
-                                               if (AlphaIsValid()){\r
-                                                       bool bAlphaOk = false;\r
-                                                       BYTE* p;\r
-                                                       for (long y=0; y<head.biHeight; y++){\r
-                                                               p = buff32 + 3 + head.biWidth * 4 * y;\r
-                                                               for (long x=0; x<head.biWidth; x++){\r
-                                                                       if (*p) bAlphaOk = true;\r
-                                                                       AlphaSet(x,y,*p);\r
-                                                                       p+=4;\r
-                                                               }\r
-                                                       }\r
-                                                       // fix if alpha pixels are all zero\r
-                                                       if (!bAlphaOk) AlphaInvert();\r
-                                               }\r
-                                       }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-                                       Bitfield2RGB(buff32,bfmask[0],bfmask[1],bfmask[2],32);\r
-                                       free(buff32);\r
-                               } else cx_throw("can't allocate memory");\r
-                       } else cx_throw("unknown compression");\r
-                       break;\r
-               case 24 :\r
-                       if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);\r
-                       if (dwCompression == BI_RGB){\r
-                               hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels\r
-                       } else cx_throw("unknown compression");\r
-                       break;\r
-               case 16 :\r
-               {\r
-                       DWORD bfmask[3];\r
-                       if (dwCompression == BI_BITFIELDS)\r
-                       {\r
-                               hFile->Read(bfmask, 12, 1);\r
-                       } else {\r
-                               bfmask[0]=0x7C00; bfmask[1]=0x3E0; bfmask[2]=0x1F; //RGB555\r
-                       }\r
-                       // bf.bfOffBits required after the bitfield mask <Cui Ying Jie>\r
-                       if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);\r
-                       // read in the pixels\r
-                       hFile->Read(info.pImage, head.biHeight*((head.biWidth+1)/2)*4,1);\r
-                       // transform into RGB\r
-                       Bitfield2RGB(info.pImage,bfmask[0],bfmask[1],bfmask[2],16);\r
-                       break;\r
-               }\r
-               case 8 :\r
-               case 4 :\r
-               case 1 :\r
-               if (bf.bfOffBits != 0L) hFile->Seek(off + bf.bfOffBits,SEEK_SET);\r
-               switch (dwCompression) {\r
-                       case BI_RGB :\r
-                               hFile->Read(info.pImage, head.biSizeImage,1); // read in the pixels\r
-                               break;\r
-                       case BI_RLE4 :\r
-                       {\r
-                               BYTE status_byte = 0;\r
-                               BYTE second_byte = 0;\r
-                               int scanline = 0;\r
-                               int bits = 0;\r
-                               BOOL low_nibble = FALSE;\r
-                               CImageIterator iter(this);\r
-\r
-                               for (BOOL bContinue = TRUE; bContinue && hFile->Read(&status_byte, sizeof(BYTE), 1);) {\r
-                                       \r
-                                       switch (status_byte) {\r
-                                               case RLE_COMMAND :\r
-                                                       hFile->Read(&status_byte, sizeof(BYTE), 1);\r
-                                                       switch (status_byte) {\r
-                                                               case RLE_ENDOFLINE :\r
-                                                                       bits = 0;\r
-                                                                       scanline++;\r
-                                                                       low_nibble = FALSE;\r
-                                                                       break;\r
-                                                               case RLE_ENDOFBITMAP :\r
-                                                                       bContinue=FALSE;\r
-                                                                       break;\r
-                                                               case RLE_DELTA :\r
-                                                               {\r
-                                                                       // read the delta values\r
-                                                                       BYTE delta_x;\r
-                                                                       BYTE delta_y;\r
-                                                                       hFile->Read(&delta_x, sizeof(BYTE), 1);\r
-                                                                       hFile->Read(&delta_y, sizeof(BYTE), 1);\r
-                                                                       // apply them\r
-                                                                       bits       += delta_x / 2;\r
-                                                                       scanline   += delta_y;\r
-                                                                       break;\r
-                                                               }\r
-                                                               default :\r
-                                                                       hFile->Read(&second_byte, sizeof(BYTE), 1);\r
-                                                                       BYTE *sline = iter.GetRow(scanline);\r
-                                                                       for (int i = 0; i < status_byte; i++) {\r
-                                                                               if ((BYTE*)(sline+bits) < (BYTE*)(info.pImage+head.biSizeImage)){\r
-                                                                                       if (low_nibble) {\r
-                                                                                               if (i&1)\r
-                                                                                                       *(sline + bits) |= (second_byte & 0x0f);\r
-                                                                                               else\r
-                                                                                                       *(sline + bits) |= (second_byte & 0xf0)>>4;\r
-                                                                                               bits++;\r
-                                                                                       } else {\r
-                                                                                               if (i&1)\r
-                                                                                                       *(sline + bits) = (BYTE)(second_byte & 0x0f)<<4;\r
-                                                                                               else\r
-                                                                                                       *(sline + bits) = (BYTE)(second_byte & 0xf0);\r
-                                                                                       }\r
-                                                                               }\r
-\r
-                                                                               if ((i & 1) && (i != (status_byte - 1)))\r
-                                                                                       hFile->Read(&second_byte, sizeof(BYTE), 1);\r
-\r
-                                                                               low_nibble = !low_nibble;\r
-                                                                       }\r
-                                                                       if ((((status_byte+1) >> 1) & 1 ) == 1)\r
-                                                                               hFile->Read(&second_byte, sizeof(BYTE), 1);                                                                                             \r
-                                                                       break;\r
-                                                       };\r
-                                                       break;\r
-                                               default :\r
-                                               {\r
-                                                       BYTE *sline = iter.GetRow(scanline);\r
-                                                       hFile->Read(&second_byte, sizeof(BYTE), 1);\r
-                                                       for (unsigned i = 0; i < status_byte; i++) {\r
-                                                               if ((BYTE*)(sline+bits) < (BYTE*)(info.pImage+head.biSizeImage)){\r
-                                                                       if (low_nibble) {\r
-                                                                               if (i&1)\r
-                                                                                       *(sline + bits) |= (second_byte & 0x0f);\r
-                                                                               else\r
-                                                                                       *(sline + bits) |= (second_byte & 0xf0)>>4;\r
-                                                                               bits++;\r
-                                                                       } else {\r
-                                                                               if (i&1)\r
-                                                                                       *(sline + bits) = (BYTE)(second_byte & 0x0f)<<4;\r
-                                                                               else\r
-                                                                                       *(sline + bits) = (BYTE)(second_byte & 0xf0);\r
-                                                                       }\r
-                                                               }\r
-                                                               low_nibble = !low_nibble;\r
-                                                       }\r
-                                               }\r
-                                               break;\r
-                                       };\r
-                               }\r
-                               break;\r
-                       }\r
-                       case BI_RLE8 :\r
-                       {\r
-                               BYTE status_byte = 0;\r
-                               BYTE second_byte = 0;\r
-                               int scanline = 0;\r
-                               int bits = 0;\r
-                               CImageIterator iter(this);\r
-\r
-                               for (BOOL bContinue = TRUE; bContinue && hFile->Read(&status_byte, sizeof(BYTE), 1);) {\r
-                                       switch (status_byte) {\r
-                                               case RLE_COMMAND :\r
-                                                       hFile->Read(&status_byte, sizeof(BYTE), 1);\r
-                                                       switch (status_byte) {\r
-                                                               case RLE_ENDOFLINE :\r
-                                                                       bits = 0;\r
-                                                                       scanline++;\r
-                                                                       break;\r
-                                                               case RLE_ENDOFBITMAP :\r
-                                                                       bContinue=FALSE;\r
-                                                                       break;\r
-                                                               case RLE_DELTA :\r
-                                                               {\r
-                                                                       // read the delta values\r
-                                                                       BYTE delta_x;\r
-                                                                       BYTE delta_y;\r
-                                                                       hFile->Read(&delta_x, sizeof(BYTE), 1);\r
-                                                                       hFile->Read(&delta_y, sizeof(BYTE), 1);\r
-                                                                       // apply them\r
-                                                                       bits     += delta_x;\r
-                                                                       scanline += delta_y;\r
-                                                                       break;\r
-                                                               }\r
-                                                               default :\r
-                                                                       hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(BYTE) * status_byte, 1);\r
-                                                                       // align run length to even number of bytes \r
-                                                                       if ((status_byte & 1) == 1)\r
-                                                                               hFile->Read(&second_byte, sizeof(BYTE), 1);                                                                                             \r
-                                                                       bits += status_byte;                                                                                                    \r
-                                                                       break;                                                          \r
-                                                       };\r
-                                                       break;\r
-                                               default :\r
-                                                       BYTE *sline = iter.GetRow(scanline);\r
-                                                       hFile->Read(&second_byte, sizeof(BYTE), 1);\r
-                                                       for (unsigned i = 0; i < status_byte; i++) {\r
-                                                               if ((DWORD)bits<info.dwEffWidth){\r
-                                                                       *(sline + bits) = second_byte;\r
-                                                                       bits++;                                 \r
-                                                               } else {\r
-                                                                       break;\r
-                                                               }\r
-                                                       }\r
-                                                       break;\r
-                                       };\r
-                               }\r
-                               break;\r
-                       }\r
-                       default :                                                               \r
-                               cx_throw("compression type not supported");\r
-               }\r
-       }\r
-\r
-       if (bTopDownDib) Flip(); //<Flanders>\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_BMP) return true;\r
-       return false;\r
-  }\r
-    return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/*  ReadDibBitmapInfo()\r
- *\r
- *  Will read a file in DIB format and return a global HANDLE to its\r
- *  BITMAPINFO.  This function will work with both "old" and "new"\r
- *  bitmap formats, but will always return a "new" BITMAPINFO.\r
- */\r
-bool CxImageBMP::DibReadBitmapInfo(CxFile* fh, BITMAPINFOHEADER *pdib)\r
-{\r
-       if ((fh==NULL)||(pdib==NULL)) return false;\r
-\r
-    if (fh->Read(pdib,sizeof(BITMAPINFOHEADER),1)==0) return false;\r
-\r
-       bihtoh(pdib);\r
-\r
-    switch (pdib->biSize) // what type of bitmap info is this?\r
-    {\r
-        case sizeof(BITMAPINFOHEADER):\r
-            break;\r
-\r
-               case 64: //sizeof(OS2_BMP_HEADER):\r
-            fh->Seek((long)(64 - sizeof(BITMAPINFOHEADER)),SEEK_CUR);\r
-                       break;\r
-\r
-        case sizeof(BITMAPCOREHEADER):\r
-               {\r
-            BITMAPCOREHEADER bc = *(BITMAPCOREHEADER*)pdib;\r
-            pdib->biSize               = bc.bcSize;\r
-            pdib->biWidth              = (DWORD)bc.bcWidth;\r
-            pdib->biHeight             = (DWORD)bc.bcHeight;\r
-            pdib->biPlanes             =  bc.bcPlanes;\r
-            pdib->biBitCount           =  bc.bcBitCount;\r
-            pdib->biCompression        = BI_RGB;\r
-            pdib->biSizeImage          = 0;\r
-            pdib->biXPelsPerMeter      = 0;\r
-            pdib->biYPelsPerMeter      = 0;\r
-            pdib->biClrUsed            = 0;\r
-            pdib->biClrImportant       = 0;\r
-\r
-                       fh->Seek((long)(sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER)), SEEK_CUR);\r
-               }\r
-            break;\r
-        default:\r
-                       //give a last chance\r
-                        if (pdib->biSize>(sizeof(BITMAPINFOHEADER))&&\r
-                               (pdib->biSizeImage>=(unsigned long)(pdib->biHeight*((((pdib->biBitCount*pdib->biWidth)+31)/32)*4)))&&\r
-                               (pdib->biPlanes==1)&&(pdib->biClrUsed==0))\r
-                        {\r
-                    if (pdib->biCompression==BI_RGB)\r
-                                        fh->Seek((long)(pdib->biSize - sizeof(BITMAPINFOHEADER)),SEEK_CUR);\r
-                                break;\r
-                        }\r
-                       return false;\r
-    }\r
-\r
-    FixBitmapInfo(pdib);\r
-\r
-    return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif         // CXIMAGE_SUPPORT_BMP\r
-////////////////////////////////////////////////////////////////////////////////\r
+/*
+ * File:       ximabmp.cpp
+ * Purpose:    Platform Independent BMP Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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 = ntohs(hdr.bfType); 
+       hdr.bfSize = ntohl(hdr.bfSize); 
+       hdr.bfOffBits = 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;
+               DWORD dwEffWidth = ((((infohdr.biBitCount * infohdr.biWidth) + 31) / 32) * 4);
+               infohdr.biSizeImage = dwEffWidth * infohdr.biHeight;
+
+               hdr.bfSize = infohdr.biSize + infohdr.biSizeImage + 14 /*sizeof(BITMAPFILEHEADER)*/;
+
+               hdr.bfSize = 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
+               BYTE *srcalpha = AlphaGetPointer();
+               for(long y = 0; y < infohdr.biHeight; ++y){
+                       BYTE *srcdib = GetBits(y);
+                       for(long 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;
+       DWORD off = hFile->Tell(); //<CSC>
+  cx_try {
+       if (hFile->Read(&bf,min(14,sizeof(bf)),1)==0) cx_throw("Not a BMP");
+
+       bf.bfSize = ntohl(bf.bfSize); 
+       bf.bfOffBits = ntohl(bf.bfOffBits); 
+
+    if (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");
+       DWORD dwCompression=bmpHeader.biCompression;
+       DWORD 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((long) floor(bmpHeader.biXPelsPerMeter * 254.0 / 10000.0 + 0.5));
+       SetYDPI((long) 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 (int 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 = (BYTE)0;
+            }
+        } else {
+            hFile->Read((void*)pRgb,DibNumColors(&bmpHeader) * sizeof(RGBQUAD),1);
+                       //force rgbReserved=0, to avoid problems with some WinXp bitmaps
+                       for (unsigned int i=0; i<head.biClrUsed; i++) pRgb[i].rgbReserved=0;
+        }
+    }
+
+       if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding
+
+       switch (dwBitCount) {
+               case 32 :
+                       DWORD 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){
+                               long imagesize=4*head.biHeight*head.biWidth;
+                               BYTE* buff32=(BYTE*)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;
+                                                       BYTE* p;
+                                                       for (long y=0; y<head.biHeight; y++){
+                                                               p = buff32 + 3 + head.biWidth * 4 * y;
+                                                               for (long 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 :
+               {
+                       DWORD 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 :
+                       {
+                               BYTE status_byte = 0;
+                               BYTE second_byte = 0;
+                               int scanline = 0;
+                               int bits = 0;
+                               BOOL low_nibble = FALSE;
+                               CImageIterator iter(this);
+
+                               for (BOOL bContinue = TRUE; bContinue && hFile->Read(&status_byte, sizeof(BYTE), 1);) {
+                                       
+                                       switch (status_byte) {
+                                               case RLE_COMMAND :
+                                                       hFile->Read(&status_byte, sizeof(BYTE), 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
+                                                                       BYTE delta_x;
+                                                                       BYTE delta_y;
+                                                                       hFile->Read(&delta_x, sizeof(BYTE), 1);
+                                                                       hFile->Read(&delta_y, sizeof(BYTE), 1);
+                                                                       // apply them
+                                                                       bits       += delta_x / 2;
+                                                                       scanline   += delta_y;
+                                                                       break;
+                                                               }
+                                                               default :
+                                                                       hFile->Read(&second_byte, sizeof(BYTE), 1);
+                                                                       BYTE *sline = iter.GetRow(scanline);
+                                                                       for (int i = 0; i < status_byte; i++) {
+                                                                               if ((BYTE*)(sline+bits) < (BYTE*)(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) = (BYTE)(second_byte & 0x0f)<<4;
+                                                                                               else
+                                                                                                       *(sline + bits) = (BYTE)(second_byte & 0xf0);
+                                                                                       }
+                                                                               }
+
+                                                                               if ((i & 1) && (i != (status_byte - 1)))
+                                                                                       hFile->Read(&second_byte, sizeof(BYTE), 1);
+
+                                                                               low_nibble = !low_nibble;
+                                                                       }
+                                                                       if ((((status_byte+1) >> 1) & 1 ) == 1)
+                                                                               hFile->Read(&second_byte, sizeof(BYTE), 1);                                                                                             
+                                                                       break;
+                                                       };
+                                                       break;
+                                               default :
+                                               {
+                                                       BYTE *sline = iter.GetRow(scanline);
+                                                       hFile->Read(&second_byte, sizeof(BYTE), 1);
+                                                       for (unsigned i = 0; i < status_byte; i++) {
+                                                               if ((BYTE*)(sline+bits) < (BYTE*)(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) = (BYTE)(second_byte & 0x0f)<<4;
+                                                                               else
+                                                                                       *(sline + bits) = (BYTE)(second_byte & 0xf0);
+                                                                       }
+                                                               }
+                                                               low_nibble = !low_nibble;
+                                                       }
+                                               }
+                                               break;
+                                       };
+                               }
+                               break;
+                       }
+                       case BI_RLE8 :
+                       {
+                               BYTE status_byte = 0;
+                               BYTE second_byte = 0;
+                               int scanline = 0;
+                               int bits = 0;
+                               CImageIterator iter(this);
+
+                               for (BOOL bContinue = TRUE; bContinue && hFile->Read(&status_byte, sizeof(BYTE), 1);) {
+                                       switch (status_byte) {
+                                               case RLE_COMMAND :
+                                                       hFile->Read(&status_byte, sizeof(BYTE), 1);
+                                                       switch (status_byte) {
+                                                               case RLE_ENDOFLINE :
+                                                                       bits = 0;
+                                                                       scanline++;
+                                                                       break;
+                                                               case RLE_ENDOFBITMAP :
+                                                                       bContinue=FALSE;
+                                                                       break;
+                                                               case RLE_DELTA :
+                                                               {
+                                                                       // read the delta values
+                                                                       BYTE delta_x;
+                                                                       BYTE delta_y;
+                                                                       hFile->Read(&delta_x, sizeof(BYTE), 1);
+                                                                       hFile->Read(&delta_y, sizeof(BYTE), 1);
+                                                                       // apply them
+                                                                       bits     += delta_x;
+                                                                       scanline += delta_y;
+                                                                       break;
+                                                               }
+                                                               default :
+                                                                       hFile->Read((void *)(iter.GetRow(scanline) + bits), sizeof(BYTE) * status_byte, 1);
+                                                                       // align run length to even number of bytes 
+                                                                       if ((status_byte & 1) == 1)
+                                                                               hFile->Read(&second_byte, sizeof(BYTE), 1);                                                                                             
+                                                                       bits += status_byte;                                                                                                    
+                                                                       break;                                                          
+                                                       };
+                                                       break;
+                                               default :
+                                                       BYTE *sline = iter.GetRow(scanline);
+                                                       hFile->Read(&second_byte, sizeof(BYTE), 1);
+                                                       for (unsigned i = 0; i < status_byte; i++) {
+                                                               if ((DWORD)bits<info.dwEffWidth){
+                                                                       *(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((long)(64 - sizeof(BITMAPINFOHEADER)),SEEK_CUR);
+                       break;
+
+        case sizeof(BITMAPCOREHEADER):
+               {
+            BITMAPCOREHEADER bc = *(BITMAPCOREHEADER*)pdib;
+            pdib->biSize               = bc.bcSize;
+            pdib->biWidth              = (DWORD)bc.bcWidth;
+            pdib->biHeight             = (DWORD)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((long)(sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER)), SEEK_CUR);
+               }
+            break;
+        default:
+                       //give a last chance
+                        if (pdib->biSize>(sizeof(BITMAPINFOHEADER))&&
+                               (pdib->biSizeImage>=(unsigned long)(pdib->biHeight*((((pdib->biBitCount*pdib->biWidth)+31)/32)*4)))&&
+                               (pdib->biPlanes==1)&&(pdib->biClrUsed==0))
+                        {
+                    if (pdib->biCompression==BI_RGB)
+                                        fh->Seek((long)(pdib->biSize - sizeof(BITMAPINFOHEADER)),SEEK_CUR);
+                                break;
+                        }
+                       return false;
+    }
+
+    FixBitmapInfo(pdib);
+
+    return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#endif         // CXIMAGE_SUPPORT_BMP
+////////////////////////////////////////////////////////////////////////////////
index 3b794d944cffc94cec68b669d09384cfea644676..2bda4feba5de9ce185d175351464f26e19d4af93 100644 (file)
@@ -1,79 +1,79 @@
-/*\r
- * File:       ximabmp.h\r
- * Purpose:    BMP Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageBMP (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes\r
- *\r
- * original CImageBMP  and CImageIterator implementation are:\r
- * Copyright:  (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>\r
- *\r
- * ==========================================================\r
- */\r
-\r
-#if !defined(__ximaBMP_h)\r
-#define __ximaBMP_h\r
-\r
-#include "ximage.h"\r
-\r
-const int RLE_COMMAND     = 0;\r
-const int RLE_ENDOFLINE   = 0;\r
-const int RLE_ENDOFBITMAP = 1;\r
-const int RLE_DELTA       = 2;\r
-\r
-#if !defined(BI_RLE8)\r
- #define BI_RLE8  1L\r
-#endif\r
-#if !defined(BI_RLE4)\r
- #define BI_RLE4  2L\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_BMP\r
-\r
-class CxImageBMP: public CxImage\r
-{\r
-public:\r
-       CxImageBMP(): CxImage(CXIMAGE_FORMAT_BMP) {};\r
-\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-\r
-protected:\r
-       bool DibReadBitmapInfo(CxFile* fh, BITMAPINFOHEADER *pdib);\r
-};\r
-\r
-#define BFT_ICON   0x4349   /* 'IC' */\r
-#define BFT_BITMAP 0x4d42   /* 'BM' */\r
-#define BFT_CURSOR 0x5450   /* 'PT' */\r
-\r
-#ifndef WIDTHBYTES\r
-#define WIDTHBYTES(i)           ((unsigned)((i+31)&(~31))/8)  /* ULONG aligned ! */\r
-#endif\r
-\r
-#endif\r
-\r
-#define DibWidthBytesN(lpbi, n) (UINT)WIDTHBYTES((UINT)(lpbi)->biWidth * (UINT)(n))\r
-#define DibWidthBytes(lpbi)     DibWidthBytesN(lpbi, (lpbi)->biBitCount)\r
-\r
-#define DibSizeImage(lpbi)      ((lpbi)->biSizeImage == 0 \\r
-                                    ? ((DWORD)(UINT)DibWidthBytes(lpbi) * (DWORD)(UINT)(lpbi)->biHeight) \\r
-                                    : (lpbi)->biSizeImage)\r
-\r
-#define DibNumColors(lpbi)      ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \\r
-                                    ? (int)(1 << (int)(lpbi)->biBitCount)          \\r
-                                    : (int)(lpbi)->biClrUsed)\r
-\r
-#define FixBitmapInfo(lpbi)     if ((lpbi)->biSizeImage == 0)                 \\r
-                                                                                               (lpbi)->biSizeImage = DibSizeImage(lpbi); \\r
-                                if ((lpbi)->biClrUsed == 0)                   \\r
-                                    (lpbi)->biClrUsed = DibNumColors(lpbi);   \\r
-\r
-#endif\r
+/*
+ * 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 int RLE_COMMAND     = 0;
+const int RLE_ENDOFLINE   = 0;
+const int RLE_ENDOFBITMAP = 1;
+const int 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) (UINT)WIDTHBYTES((UINT)(lpbi)->biWidth * (UINT)(n))
+#define DibWidthBytes(lpbi)     DibWidthBytesN(lpbi, (lpbi)->biBitCount)
+
+#define DibSizeImage(lpbi)      ((lpbi)->biSizeImage == 0 \
+                                    ? ((DWORD)(UINT)DibWidthBytes(lpbi) * (DWORD)(UINT)(lpbi)->biHeight) \
+                                    : (lpbi)->biSizeImage)
+
+#define DibNumColors(lpbi)      ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
+                                    ? (int)(1 << (int)(lpbi)->biBitCount)          \
+                                    : (int)(lpbi)->biClrUsed)
+
+#define FixBitmapInfo(lpbi)     if ((lpbi)->biSizeImage == 0)                 \
+                                                                                               (lpbi)->biSizeImage = DibSizeImage(lpbi); \
+                                if ((lpbi)->biClrUsed == 0)                   \
+                                    (lpbi)->biClrUsed = DibNumColors(lpbi);   \
+
+#endif
index ef89b227098bbc846a0ec98cf7d57e7390780987..92a6cb6f8627ef9753af77d3184b62d046235105 100644 (file)
@@ -1,78 +1,78 @@
-#if !defined(__ximaCFG_h)\r
-#define __ximaCFG_h\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// Protability issues\r
-#ifdef ntohs\r
-#  undef ntohs\r
-#endif\r
-#ifdef ntohl\r
-#  undef ntohl\r
-#endif\r
-#ifndef _tfopen\r
-#  define _tfopen fopen\r
-#endif\r
-#ifndef LPCTSTR\r
-#  define LPCTSTR char*\r
-#endif\r
-#ifndef HDC\r
-#  define HDC void*\r
-#endif\r
-#ifndef _tcsnicmp\r
-#  define _tcsnicmp strncasecmp\r
-#endif\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// CxImage supported features\r
-#define CXIMAGE_SUPPORT_ALPHA          1\r
-#define CXIMAGE_SUPPORT_SELECTION      1\r
-#define CXIMAGE_SUPPORT_TRANSFORMATION 1\r
-#define CXIMAGE_SUPPORT_DSP            0\r
-#define CXIMAGE_SUPPORT_LAYERS            1\r
-#define CXIMAGE_SUPPORT_INTERPOLATION  0\r
-\r
-#define CXIMAGE_SUPPORT_DECODE 1\r
-#define CXIMAGE_SUPPORT_ENCODE 1               //<vho><T.Peck>\r
-#define        CXIMAGE_SUPPORT_WINDOWS 0\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// CxImage supported formats\r
-#define CXIMAGE_SUPPORT_BMP 0\r
-#define CXIMAGE_SUPPORT_GIF 1\r
-#define CXIMAGE_SUPPORT_JPG 0\r
-#define CXIMAGE_SUPPORT_PNG 0\r
-#define CXIMAGE_SUPPORT_ICO 0\r
-#define CXIMAGE_SUPPORT_TIF 0\r
-#define CXIMAGE_SUPPORT_TGA 0\r
-#define CXIMAGE_SUPPORT_PCX 0\r
-#define CXIMAGE_SUPPORT_WBMP 0\r
-#define CXIMAGE_SUPPORT_WMF 0\r
-\r
-#define CXIMAGE_SUPPORT_JP2 0\r
-#define CXIMAGE_SUPPORT_JPC 0\r
-#define CXIMAGE_SUPPORT_PGX 0\r
-#define CXIMAGE_SUPPORT_PNM 0\r
-#define CXIMAGE_SUPPORT_RAS 0\r
-\r
-#define CXIMAGE_SUPPORT_JBG 0          // GPL'd see ../jbig/copying.txt & ../jbig/patents.htm\r
-\r
-#define CXIMAGE_SUPPORT_MNG 0\r
-#define CXIMAGE_SUPPORT_SKA 0\r
-#define CXIMAGE_SUPPORT_RAW 0\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-#define        CXIMAGE_MAX_MEMORY 268435456\r
-\r
-#define CXIMAGE_DEFAULT_DPI 96\r
-\r
-#define CXIMAGE_ERR_NOFILE "null file handler"\r
-#define CXIMAGE_ERR_NOIMAGE "null image!!!"\r
-\r
-#define CXIMAGE_SUPPORT_EXCEPTION_HANDLING 1\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-//color to grey mapping <H. Muelner> <jurgene>\r
-//#define RGB2GRAY(r,g,b) (((b)*114 + (g)*587 + (r)*299)/1000)\r
-#define RGB2GRAY(r,g,b) (((b)*117 + (g)*601 + (r)*306) >> 10)\r
-\r
-#endif\r
+#if !defined(__ximaCFG_h)
+#define __ximaCFG_h
+
+/////////////////////////////////////////////////////////////////////////////
+// Protability issues
+#ifdef ntohs
+#  undef ntohs
+#endif
+#ifdef ntohl
+#  undef ntohl
+#endif
+#ifndef _tfopen
+#  define _tfopen fopen
+#endif
+#ifndef LPCTSTR
+#  define LPCTSTR char*
+#endif
+#ifndef HDC
+#  define HDC void*
+#endif
+#ifndef _tcsnicmp
+#  define _tcsnicmp strncasecmp
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported features
+#define CXIMAGE_SUPPORT_ALPHA          1
+#define CXIMAGE_SUPPORT_SELECTION      1
+#define CXIMAGE_SUPPORT_TRANSFORMATION 1
+#define CXIMAGE_SUPPORT_DSP            0
+#define CXIMAGE_SUPPORT_LAYERS            1
+#define CXIMAGE_SUPPORT_INTERPOLATION  0
+
+#define CXIMAGE_SUPPORT_DECODE 1
+#define CXIMAGE_SUPPORT_ENCODE 1               //<vho><T.Peck>
+#define        CXIMAGE_SUPPORT_WINDOWS 0
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported formats
+#define CXIMAGE_SUPPORT_BMP 0
+#define CXIMAGE_SUPPORT_GIF 1
+#define CXIMAGE_SUPPORT_JPG 0
+#define CXIMAGE_SUPPORT_PNG 0
+#define CXIMAGE_SUPPORT_ICO 0
+#define CXIMAGE_SUPPORT_TIF 0
+#define CXIMAGE_SUPPORT_TGA 0
+#define CXIMAGE_SUPPORT_PCX 0
+#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_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
+
+/////////////////////////////////////////////////////////////////////////////
+//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
index f73bcd2a64a558bab419c5f31bdf9bc199ba6f15..b388b2b81f4c8cad255c990374545c446305aea4 100644 (file)
-#if !defined(__ximadefs_h)\r
-#define __ximadefs_h\r
-\r
-#include "ximacfg.h"\r
-\r
-#if defined(_AFXDLL)||defined(_USRDLL)\r
- #define DLL_EXP __declspec(dllexport)\r
-#elif defined(_MSC_VER)&&(_MSC_VER<1200)\r
- #define DLL_EXP __declspec(dllimport)\r
-#else\r
- #define DLL_EXP\r
-#endif\r
-\r
-\r
-#if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-  #define cx_try try\r
-  #define cx_throw(message) throw(message)\r
-  #define cx_catch catch (const char *message)\r
-#else\r
-  #define cx_try bool cx_error=false;\r
-  #define cx_throw(message) {cx_error=true; if(strcmp(message,"")) strncpy(info.szLastError,message,255); goto cx_error_catch;}\r
-  #define cx_catch cx_error_catch: char message[]=""; if(cx_error)\r
-#endif\r
-\r
-\r
-#if CXIMAGE_SUPPORT_JP2 || CXIMAGE_SUPPORT_JPC || CXIMAGE_SUPPORT_PGX || CXIMAGE_SUPPORT_PNM || CXIMAGE_SUPPORT_RAS\r
- #define CXIMAGE_SUPPORT_JASPER 1\r
-#else\r
- #define CXIMAGE_SUPPORT_JASPER 0\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_DSP\r
-#undef CXIMAGE_SUPPORT_TRANSFORMATION\r
- #define CXIMAGE_SUPPORT_TRANSFORMATION 1\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_TRANSFORMATION || CXIMAGE_SUPPORT_TIF || CXIMAGE_SUPPORT_TGA || CXIMAGE_SUPPORT_BMP || CXIMAGE_SUPPORT_WINDOWS\r
- #define CXIMAGE_SUPPORT_BASICTRANSFORMATIONS 1\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_DSP || CXIMAGE_SUPPORT_TRANSFORMATION\r
-#undef CXIMAGE_SUPPORT_INTERPOLATION\r
- #define CXIMAGE_SUPPORT_INTERPOLATION 1\r
-#endif\r
-\r
-#if defined (_WIN32_WCE)\r
- #undef CXIMAGE_SUPPORT_WMF\r
- #define CXIMAGE_SUPPORT_WMF 0\r
-#endif\r
-\r
-#if !defined(WIN32) && !defined(_WIN32_WCE)\r
- #undef CXIMAGE_SUPPORT_WINDOWS\r
- #define CXIMAGE_SUPPORT_WINDOWS 0\r
-#endif\r
-\r
-#ifndef min\r
-#define min(a,b) (((a)<(b))?(a):(b))\r
-#endif\r
-#ifndef max\r
-#define max(a,b) (((a)>(b))?(a):(b))\r
-#endif\r
-\r
-#ifndef PI\r
- #define PI 3.141592653589793f\r
-#endif\r
-\r
-\r
-#if defined(WIN32) || defined(_WIN32_WCE)\r
-#include <windows.h>\r
-#include <tchar.h>\r
-#endif\r
-\r
-#include <stdio.h>\r
-#include <math.h>\r
-\r
-#ifdef __BORLANDC__\r
-\r
-#ifndef _COMPLEX_DEFINED\r
-\r
-typedef struct tagcomplex {\r
-       double x,y;\r
-} _complex;\r
-\r
-#endif\r
-\r
-#define _cabs(c) sqrt(c.x*c.x+c.y*c.y)\r
-\r
-#endif\r
-\r
-\r
-#if !defined(WIN32) && !defined(_WIN32_WCE)\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-\r
-typedef unsigned char  BYTE;\r
-typedef unsigned short WORD;\r
-typedef unsigned long  DWORD;\r
-typedef unsigned int   UINT;\r
-\r
-typedef DWORD          COLORREF;\r
-typedef unsigned int   HANDLE;\r
-typedef void*          HRGN;\r
-\r
-#ifndef BOOL\r
-#define        BOOL bool\r
-#endif\r
-\r
-#ifndef TRUE\r
-#define        TRUE true\r
-#endif\r
-\r
-#ifndef FALSE\r
-#define        FALSE false\r
-#endif\r
-\r
-#ifndef TCHAR\r
-#define TCHAR char\r
-#define _T\r
-#endif\r
-\r
-typedef struct tagRECT\r
-{\r
-       long    left;\r
-       long    top;\r
-       long    right;\r
-       long    bottom;\r
-} RECT;\r
-\r
-typedef struct tagPOINT\r
-{\r
-       long  x;\r
-       long  y;\r
-} POINT;\r
-\r
-typedef struct tagRGBQUAD {\r
-       BYTE    rgbBlue;\r
-       BYTE    rgbGreen;\r
-       BYTE    rgbRed;\r
-       BYTE    rgbReserved;\r
-} RGBQUAD;\r
-\r
-#pragma pack(1)\r
-\r
-typedef struct tagBITMAPINFOHEADER{\r
-       DWORD      biSize;\r
-       long       biWidth;\r
-       long       biHeight;\r
-       WORD       biPlanes;\r
-       WORD       biBitCount;\r
-       DWORD      biCompression;\r
-       DWORD      biSizeImage;\r
-       long       biXPelsPerMeter;\r
-       long       biYPelsPerMeter;\r
-       DWORD      biClrUsed;\r
-       DWORD      biClrImportant;\r
-} BITMAPINFOHEADER;\r
-\r
-typedef struct tagBITMAPFILEHEADER {\r
-       WORD    bfType;\r
-       DWORD   bfSize;\r
-       WORD    bfReserved1;\r
-       WORD    bfReserved2;\r
-       DWORD   bfOffBits;\r
-} BITMAPFILEHEADER;\r
-\r
-typedef struct tagBITMAPCOREHEADER {\r
-       DWORD   bcSize;\r
-       WORD    bcWidth;\r
-       WORD    bcHeight;\r
-       WORD    bcPlanes;\r
-       WORD    bcBitCount;\r
-} BITMAPCOREHEADER;\r
-\r
-typedef struct tagRGBTRIPLE {\r
-       BYTE    rgbtBlue;\r
-       BYTE    rgbtGreen;\r
-       BYTE    rgbtRed;\r
-} RGBTRIPLE;\r
-\r
-#pragma pack()\r
-\r
-#define BI_RGB        0L\r
-#define BI_RLE8       1L\r
-#define BI_RLE4       2L\r
-#define BI_BITFIELDS  3L\r
-\r
-#define GetRValue(rgb)      ((BYTE)(rgb))\r
-#define GetGValue(rgb)      ((BYTE)(((WORD)(rgb)) >> 8))\r
-#define GetBValue(rgb)      ((BYTE)((rgb)>>16))\r
-#define RGB(r,g,b)          ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))\r
-\r
-#ifndef _COMPLEX_DEFINED\r
-\r
-typedef struct tagcomplex {\r
-       double x,y;\r
-} _complex;\r
-\r
-#endif\r
-\r
-#define _cabs(c) sqrt(c.x*c.x+c.y*c.y)\r
-\r
-#endif\r
-\r
-#endif //__ximadefs\r
+#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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+typedef unsigned char  BYTE;
+typedef unsigned short WORD;
+typedef unsigned long  DWORD;
+typedef unsigned int   UINT;
+
+typedef DWORD          COLORREF;
+typedef unsigned int   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
+{
+       long    left;
+       long    top;
+       long    right;
+       long    bottom;
+} RECT;
+
+typedef struct tagPOINT
+{
+       long  x;
+       long  y;
+} POINT;
+
+typedef struct tagRGBQUAD {
+       BYTE    rgbBlue;
+       BYTE    rgbGreen;
+       BYTE    rgbRed;
+       BYTE    rgbReserved;
+} RGBQUAD;
+
+#pragma pack(1)
+
+typedef struct tagBITMAPINFOHEADER{
+       DWORD      biSize;
+       long       biWidth;
+       long       biHeight;
+       WORD       biPlanes;
+       WORD       biBitCount;
+       DWORD      biCompression;
+       DWORD      biSizeImage;
+       long       biXPelsPerMeter;
+       long       biYPelsPerMeter;
+       DWORD      biClrUsed;
+       DWORD      biClrImportant;
+} BITMAPINFOHEADER;
+
+typedef struct tagBITMAPFILEHEADER {
+       WORD    bfType;
+       DWORD   bfSize;
+       WORD    bfReserved1;
+       WORD    bfReserved2;
+       DWORD   bfOffBits;
+} BITMAPFILEHEADER;
+
+typedef struct tagBITMAPCOREHEADER {
+       DWORD   bcSize;
+       WORD    bcWidth;
+       WORD    bcHeight;
+       WORD    bcPlanes;
+       WORD    bcBitCount;
+} BITMAPCOREHEADER;
+
+typedef struct tagRGBTRIPLE {
+       BYTE    rgbtBlue;
+       BYTE    rgbtGreen;
+       BYTE    rgbtRed;
+} RGBTRIPLE;
+
+#pragma pack()
+
+#define BI_RGB        0L
+#define BI_RLE8       1L
+#define BI_RLE4       2L
+#define BI_BITFIELDS  3L
+
+#define GetRValue(rgb)      ((BYTE)(rgb))
+#define GetGValue(rgb)      ((BYTE)(((WORD)(rgb)) >> 8))
+#define GetBValue(rgb)      ((BYTE)((rgb)>>16))
+#define RGB(r,g,b)          ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(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
index 68695db813a18147e89b10d34a5988145aca747a..1623d5ae0ac72f5077d18a6a58f12875788b96b7 100644 (file)
-// xImaDsp.cpp : DSP functions\r
-/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-#include "ximaiter.h"\r
-\r
-#if CXIMAGE_SUPPORT_DSP\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Converts the image to B&W.\r
- * The OptimalThreshold() function can be used for calculating the optimal threshold.\r
- * \param level: the lightness threshold.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Threshold(BYTE level)\r
-{\r
-       if (!pDib) return false;\r
-       if (head.biBitCount == 1) return true;\r
-\r
-       GrayScale();\r
-\r
-       CxImage tmp(head.biWidth,head.biHeight,1);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       for (long y=0;y<head.biHeight;y++){\r
-               info.nProgress = (long)(100*y/head.biHeight);\r
-               if (info.nEscape) break;\r
-               for (long x=0;x<head.biWidth;x++){\r
-                       if (BlindGetPixelIndex(x,y)>level)\r
-                               tmp.BlindSetPixelIndex(x,y,1);\r
-                       else\r
-                               tmp.BlindSetPixelIndex(x,y,0);\r
-               }\r
-       }\r
-       tmp.SetPaletteColor(0,0,0,0);\r
-       tmp.SetPaletteColor(1,255,255,255);\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Converts the image to B&W, using a threshold mask\r
- * \param pThresholdMask: the lightness threshold mask.\r
- * the pThresholdMask image must be grayscale with same with and height of the current image\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Threshold(CxImage* pThresholdMask)\r
-{\r
-       if (!pDib) return false;\r
-       if (head.biBitCount == 1) return true;\r
-\r
-       if (!pThresholdMask) return false;\r
-       \r
-       if (!pThresholdMask->IsValid() ||\r
-               !pThresholdMask->IsGrayScale() ||\r
-               pThresholdMask->GetWidth() != GetWidth() ||\r
-               pThresholdMask->GetHeight() != GetHeight()){\r
-               strcpy(info.szLastError,"invalid ThresholdMask");\r
-               return false;\r
-       }\r
-\r
-       GrayScale();\r
-\r
-       CxImage tmp(head.biWidth,head.biHeight,1);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       for (long y=0;y<head.biHeight;y++){\r
-               info.nProgress = (long)(100*y/head.biHeight);\r
-               if (info.nEscape) break;\r
-               for (long x=0;x<head.biWidth;x++){\r
-                       if (BlindGetPixelIndex(x,y)>pThresholdMask->BlindGetPixelIndex(x,y))\r
-                               tmp.BlindSetPixelIndex(x,y,1);\r
-                       else\r
-                               tmp.BlindSetPixelIndex(x,y,0);\r
-               }\r
-       }\r
-       tmp.SetPaletteColor(0,0,0,0);\r
-       tmp.SetPaletteColor(1,255,255,255);\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Filters only the pixels with a lightness less (or more) than the threshold level,\r
- * and preserves the colors for the unfiltered pixels.\r
- * \param level = the lightness threshold.\r
- * \param bDirection = false: filter dark pixels, true: filter light pixels\r
- * \param nBkgndColor =  filtered pixels are set to nBkgndColor color\r
- * \param bSetAlpha = if true, sets also the alpha component for the filtered pixels, with nBkgndColor.rgbReserved\r
- * \return true if everything is ok\r
- * \author [DP], [wangsongtao]\r
- */\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::Threshold2(BYTE level, bool bDirection, RGBQUAD nBkgndColor, bool bSetAlpha)\r
-{\r
-       if (!pDib) return false;\r
-       if (head.biBitCount == 1) return true;\r
-\r
-       CxImage tmp(*this, true, false, false);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       tmp.GrayScale();\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*y/head.biHeight);\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               BYTE i = tmp.BlindGetPixelIndex(x,y);\r
-                               if (!bDirection && i<level) BlindSetPixelColor(x,y,nBkgndColor,bSetAlpha);\r
-                               if (bDirection && i>=level) BlindSetPixelColor(x,y,nBkgndColor,bSetAlpha);\r
-                       }\r
-               }\r
-       }\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Extract RGB channels from the image. Each channel is an 8 bit grayscale image. \r
- * \param r,g,b: pointers to CxImage objects, to store the splited channels\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::SplitRGB(CxImage* r,CxImage* g,CxImage* b)\r
-{\r
-       if (!pDib) return false;\r
-       if (r==NULL && g==NULL && b==NULL) return false;\r
-\r
-       CxImage tmpr(head.biWidth,head.biHeight,8);\r
-       CxImage tmpg(head.biWidth,head.biHeight,8);\r
-       CxImage tmpb(head.biWidth,head.biHeight,8);\r
-\r
-       RGBQUAD color;\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       color = BlindGetPixelColor(x,y);\r
-                       if (r) tmpr.BlindSetPixelIndex(x,y,color.rgbRed);\r
-                       if (g) tmpg.BlindSetPixelIndex(x,y,color.rgbGreen);\r
-                       if (b) tmpb.BlindSetPixelIndex(x,y,color.rgbBlue);\r
-               }\r
-       }\r
-\r
-       if (r) tmpr.SetGrayPalette();\r
-       if (g) tmpg.SetGrayPalette();\r
-       if (b) tmpb.SetGrayPalette();\r
-\r
-       /*for(long j=0; j<256; j++){\r
-               BYTE i=(BYTE)j;\r
-               if (r) tmpr.SetPaletteColor(i,i,0,0);\r
-               if (g) tmpg.SetPaletteColor(i,0,i,0);\r
-               if (b) tmpb.SetPaletteColor(i,0,0,i);\r
-       }*/\r
-\r
-       if (r) r->Transfer(tmpr);\r
-       if (g) g->Transfer(tmpg);\r
-       if (b) b->Transfer(tmpb);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Extract CMYK channels from the image. Each channel is an 8 bit grayscale image. \r
- * \param c,m,y,k: pointers to CxImage objects, to store the splited channels\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::SplitCMYK(CxImage* c,CxImage* m,CxImage* y,CxImage* k)\r
-{\r
-       if (!pDib) return false;\r
-       if (c==NULL && m==NULL && y==NULL && k==NULL) return false;\r
-\r
-       CxImage tmpc(head.biWidth,head.biHeight,8);\r
-       CxImage tmpm(head.biWidth,head.biHeight,8);\r
-       CxImage tmpy(head.biWidth,head.biHeight,8);\r
-       CxImage tmpk(head.biWidth,head.biHeight,8);\r
-\r
-       RGBQUAD color;\r
-       for(long yy=0; yy<head.biHeight; yy++){\r
-               for(long xx=0; xx<head.biWidth; xx++){\r
-                       color = BlindGetPixelColor(xx,yy);\r
-                       if (c) tmpc.BlindSetPixelIndex(xx,yy,(BYTE)(255-color.rgbRed));\r
-                       if (m) tmpm.BlindSetPixelIndex(xx,yy,(BYTE)(255-color.rgbGreen));\r
-                       if (y) tmpy.BlindSetPixelIndex(xx,yy,(BYTE)(255-color.rgbBlue));\r
-                       if (k) tmpk.BlindSetPixelIndex(xx,yy,(BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue));\r
-               }\r
-       }\r
-\r
-       if (c) tmpc.SetGrayPalette();\r
-       if (m) tmpm.SetGrayPalette();\r
-       if (y) tmpy.SetGrayPalette();\r
-       if (k) tmpk.SetGrayPalette();\r
-\r
-       if (c) c->Transfer(tmpc);\r
-       if (m) m->Transfer(tmpm);\r
-       if (y) y->Transfer(tmpy);\r
-       if (k) k->Transfer(tmpk);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Extract YUV channels from the image. Each channel is an 8 bit grayscale image. \r
- * \param y,u,v: pointers to CxImage objects, to store the splited channels\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::SplitYUV(CxImage* y,CxImage* u,CxImage* v)\r
-{\r
-       if (!pDib) return false;\r
-       if (y==NULL && u==NULL && v==NULL) return false;\r
-\r
-       CxImage tmpy(head.biWidth,head.biHeight,8);\r
-       CxImage tmpu(head.biWidth,head.biHeight,8);\r
-       CxImage tmpv(head.biWidth,head.biHeight,8);\r
-\r
-       RGBQUAD color;\r
-       for(long yy=0; yy<head.biHeight; yy++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       color = RGBtoYUV(BlindGetPixelColor(x,yy));\r
-                       if (y) tmpy.BlindSetPixelIndex(x,yy,color.rgbRed);\r
-                       if (u) tmpu.BlindSetPixelIndex(x,yy,color.rgbGreen);\r
-                       if (v) tmpv.BlindSetPixelIndex(x,yy,color.rgbBlue);\r
-               }\r
-       }\r
-\r
-       if (y) tmpy.SetGrayPalette();\r
-       if (u) tmpu.SetGrayPalette();\r
-       if (v) tmpv.SetGrayPalette();\r
-\r
-       if (y) y->Transfer(tmpy);\r
-       if (u) u->Transfer(tmpu);\r
-       if (v) v->Transfer(tmpv);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Extract YIQ channels from the image. Each channel is an 8 bit grayscale image. \r
- * \param y,i,q: pointers to CxImage objects, to store the splited channels\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::SplitYIQ(CxImage* y,CxImage* i,CxImage* q)\r
-{\r
-       if (!pDib) return false;\r
-       if (y==NULL && i==NULL && q==NULL) return false;\r
-\r
-       CxImage tmpy(head.biWidth,head.biHeight,8);\r
-       CxImage tmpi(head.biWidth,head.biHeight,8);\r
-       CxImage tmpq(head.biWidth,head.biHeight,8);\r
-\r
-       RGBQUAD color;\r
-       for(long yy=0; yy<head.biHeight; yy++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       color = RGBtoYIQ(BlindGetPixelColor(x,yy));\r
-                       if (y) tmpy.BlindSetPixelIndex(x,yy,color.rgbRed);\r
-                       if (i) tmpi.BlindSetPixelIndex(x,yy,color.rgbGreen);\r
-                       if (q) tmpq.BlindSetPixelIndex(x,yy,color.rgbBlue);\r
-               }\r
-       }\r
-\r
-       if (y) tmpy.SetGrayPalette();\r
-       if (i) tmpi.SetGrayPalette();\r
-       if (q) tmpq.SetGrayPalette();\r
-\r
-       if (y) y->Transfer(tmpy);\r
-       if (i) i->Transfer(tmpi);\r
-       if (q) q->Transfer(tmpq);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Extract XYZ channels from the image. Each channel is an 8 bit grayscale image. \r
- * \param x,y,z: pointers to CxImage objects, to store the splited channels\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::SplitXYZ(CxImage* x,CxImage* y,CxImage* z)\r
-{\r
-       if (!pDib) return false;\r
-       if (x==NULL && y==NULL && z==NULL) return false;\r
-\r
-       CxImage tmpx(head.biWidth,head.biHeight,8);\r
-       CxImage tmpy(head.biWidth,head.biHeight,8);\r
-       CxImage tmpz(head.biWidth,head.biHeight,8);\r
-\r
-       RGBQUAD color;\r
-       for(long yy=0; yy<head.biHeight; yy++){\r
-               for(long xx=0; xx<head.biWidth; xx++){\r
-                       color = RGBtoXYZ(BlindGetPixelColor(xx,yy));\r
-                       if (x) tmpx.BlindSetPixelIndex(xx,yy,color.rgbRed);\r
-                       if (y) tmpy.BlindSetPixelIndex(xx,yy,color.rgbGreen);\r
-                       if (z) tmpz.BlindSetPixelIndex(xx,yy,color.rgbBlue);\r
-               }\r
-       }\r
-\r
-       if (x) tmpx.SetGrayPalette();\r
-       if (y) tmpy.SetGrayPalette();\r
-       if (z) tmpz.SetGrayPalette();\r
-\r
-       if (x) x->Transfer(tmpx);\r
-       if (y) y->Transfer(tmpy);\r
-       if (z) z->Transfer(tmpz);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Extract HSL channels from the image. Each channel is an 8 bit grayscale image. \r
- * \param h,s,l: pointers to CxImage objects, to store the splited channels\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::SplitHSL(CxImage* h,CxImage* s,CxImage* l)\r
-{\r
-       if (!pDib) return false;\r
-       if (h==NULL && s==NULL && l==NULL) return false;\r
-\r
-       CxImage tmph(head.biWidth,head.biHeight,8);\r
-       CxImage tmps(head.biWidth,head.biHeight,8);\r
-       CxImage tmpl(head.biWidth,head.biHeight,8);\r
-\r
-       RGBQUAD color;\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       color = RGBtoHSL(BlindGetPixelColor(x,y));\r
-                       if (h) tmph.BlindSetPixelIndex(x,y,color.rgbRed);\r
-                       if (s) tmps.BlindSetPixelIndex(x,y,color.rgbGreen);\r
-                       if (l) tmpl.BlindSetPixelIndex(x,y,color.rgbBlue);\r
-               }\r
-       }\r
-\r
-       if (h) tmph.SetGrayPalette();\r
-       if (s) tmps.SetGrayPalette();\r
-       if (l) tmpl.SetGrayPalette();\r
-\r
-       /* pseudo-color generator for hue channel (visual debug)\r
-       if (h) for(long j=0; j<256; j++){\r
-               BYTE i=(BYTE)j;\r
-               RGBQUAD hsl={120,240,i,0};\r
-               tmph.SetPaletteColor(i,HSLtoRGB(hsl));\r
-       }*/\r
-\r
-       if (h) h->Transfer(tmph);\r
-       if (s) s->Transfer(tmps);\r
-       if (l) l->Transfer(tmpl);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#define  HSLMAX   255  /* H,L, and S vary over 0-HSLMAX */\r
-#define  RGBMAX   255   /* R,G, and B vary over 0-RGBMAX */\r
-                        /* HSLMAX BEST IF DIVISIBLE BY 6 */\r
-                        /* RGBMAX, HSLMAX must each fit in a BYTE. */\r
-/* Hue is undefined if Saturation is 0 (grey-scale) */\r
-/* This value determines where the Hue scrollbar is */\r
-/* initially set for achromatic colors */\r
-#define HSLUNDEFINED (HSLMAX*2/3)\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::RGBtoHSL(RGBQUAD lRGBColor)\r
-{\r
-       BYTE R,G,B;                                     /* input RGB values */\r
-       BYTE H,L,S;                                     /* output HSL values */\r
-       BYTE cMax,cMin;                         /* max and min RGB values */\r
-       WORD Rdelta,Gdelta,Bdelta;      /* intermediate value: % of spread from max*/\r
-\r
-       R = lRGBColor.rgbRed;   /* get R, G, and B out of DWORD */\r
-       G = lRGBColor.rgbGreen;\r
-       B = lRGBColor.rgbBlue;\r
-\r
-       cMax = max( max(R,G), B);       /* calculate lightness */\r
-       cMin = min( min(R,G), B);\r
-       L = (BYTE)((((cMax+cMin)*HSLMAX)+RGBMAX)/(2*RGBMAX));\r
-\r
-       if (cMax==cMin){                        /* r=g=b --> achromatic case */\r
-               S = 0;                                  /* saturation */\r
-               H = HSLUNDEFINED;               /* hue */\r
-       } else {                                        /* chromatic case */\r
-               if (L <= (HSLMAX/2))    /* saturation */\r
-                       S = (BYTE)((((cMax-cMin)*HSLMAX)+((cMax+cMin)/2))/(cMax+cMin));\r
-               else\r
-                       S = (BYTE)((((cMax-cMin)*HSLMAX)+((2*RGBMAX-cMax-cMin)/2))/(2*RGBMAX-cMax-cMin));\r
-               /* hue */\r
-               Rdelta = (WORD)((((cMax-R)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));\r
-               Gdelta = (WORD)((((cMax-G)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));\r
-               Bdelta = (WORD)((((cMax-B)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));\r
-\r
-               if (R == cMax)\r
-                       H = (BYTE)(Bdelta - Gdelta);\r
-               else if (G == cMax)\r
-                       H = (BYTE)((HSLMAX/3) + Rdelta - Bdelta);\r
-               else /* B == cMax */\r
-                       H = (BYTE)(((2*HSLMAX)/3) + Gdelta - Rdelta);\r
-\r
-//             if (H < 0) H += HSLMAX;     //always false\r
-               if (H > HSLMAX) H -= HSLMAX;\r
-       }\r
-       RGBQUAD hsl={L,S,H,0};\r
-       return hsl;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::HueToRGB(float n1,float n2, float hue)\r
-{\r
-       //<F. Livraghi> fixed implementation for HSL2RGB routine\r
-       float rValue;\r
-\r
-       if (hue > 360)\r
-               hue = hue - 360;\r
-       else if (hue < 0)\r
-               hue = hue + 360;\r
-\r
-       if (hue < 60)\r
-               rValue = n1 + (n2-n1)*hue/60.0f;\r
-       else if (hue < 180)\r
-               rValue = n2;\r
-       else if (hue < 240)\r
-               rValue = n1+(n2-n1)*(240-hue)/60;\r
-       else\r
-               rValue = n1;\r
-\r
-       return rValue;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::HSLtoRGB(COLORREF cHSLColor)\r
-{\r
-       return HSLtoRGB(RGBtoRGBQUAD(cHSLColor));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::HSLtoRGB(RGBQUAD lHSLColor)\r
-{ \r
-       //<F. Livraghi> fixed implementation for HSL2RGB routine\r
-       float h,s,l;\r
-       float m1,m2;\r
-       BYTE r,g,b;\r
-\r
-       h = (float)lHSLColor.rgbRed * 360.0f/255.0f;\r
-       s = (float)lHSLColor.rgbGreen/255.0f;\r
-       l = (float)lHSLColor.rgbBlue/255.0f;\r
-\r
-       if (l <= 0.5)   m2 = l * (1+s);\r
-       else                    m2 = l + s - l*s;\r
-\r
-       m1 = 2 * l - m2;\r
-\r
-       if (s == 0) {\r
-               r=g=b=(BYTE)(l*255.0f);\r
-       } else {\r
-               r = (BYTE)(HueToRGB(m1,m2,h+120) * 255.0f);\r
-               g = (BYTE)(HueToRGB(m1,m2,h) * 255.0f);\r
-               b = (BYTE)(HueToRGB(m1,m2,h-120) * 255.0f);\r
-       }\r
-\r
-       RGBQUAD rgb = {b,g,r,0};\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::YUVtoRGB(RGBQUAD lYUVColor)\r
-{\r
-       int U,V,R,G,B;\r
-       float Y = lYUVColor.rgbRed;\r
-       U = lYUVColor.rgbGreen - 128;\r
-       V = lYUVColor.rgbBlue - 128;\r
-\r
-//     R = (int)(1.164 * Y + 2.018 * U);\r
-//     G = (int)(1.164 * Y - 0.813 * V - 0.391 * U);\r
-//     B = (int)(1.164 * Y + 1.596 * V);\r
-       R = (int)( Y + 1.403f * V);\r
-       G = (int)( Y - 0.344f * U - 0.714f * V);\r
-       B = (int)( Y + 1.770f * U);\r
-\r
-       R= min(255,max(0,R));\r
-       G= min(255,max(0,G));\r
-       B= min(255,max(0,B));\r
-       RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0};\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::RGBtoYUV(RGBQUAD lRGBColor)\r
-{\r
-       int Y,U,V,R,G,B;\r
-       R = lRGBColor.rgbRed;\r
-       G = lRGBColor.rgbGreen;\r
-       B = lRGBColor.rgbBlue;\r
-\r
-//     Y = (int)( 0.257 * R + 0.504 * G + 0.098 * B);\r
-//     U = (int)( 0.439 * R - 0.368 * G - 0.071 * B + 128);\r
-//     V = (int)(-0.148 * R - 0.291 * G + 0.439 * B + 128);\r
-       Y = (int)(0.299f * R + 0.587f * G + 0.114f * B);\r
-       U = (int)((B-Y) * 0.565f + 128);\r
-       V = (int)((R-Y) * 0.713f + 128);\r
-\r
-       Y= min(255,max(0,Y));\r
-       U= min(255,max(0,U));\r
-       V= min(255,max(0,V));\r
-       RGBQUAD yuv={(BYTE)V,(BYTE)U,(BYTE)Y,0};\r
-       return yuv;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::YIQtoRGB(RGBQUAD lYIQColor)\r
-{\r
-       int I,Q,R,G,B;\r
-       float Y = lYIQColor.rgbRed;\r
-       I = lYIQColor.rgbGreen - 128;\r
-       Q = lYIQColor.rgbBlue - 128;\r
-\r
-       R = (int)( Y + 0.956f * I + 0.621f * Q);\r
-       G = (int)( Y - 0.273f * I - 0.647f * Q);\r
-       B = (int)( Y - 1.104f * I + 1.701f * Q);\r
-\r
-       R= min(255,max(0,R));\r
-       G= min(255,max(0,G));\r
-       B= min(255,max(0,B));\r
-       RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0};\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::RGBtoYIQ(RGBQUAD lRGBColor)\r
-{\r
-       int Y,I,Q,R,G,B;\r
-       R = lRGBColor.rgbRed;\r
-       G = lRGBColor.rgbGreen;\r
-       B = lRGBColor.rgbBlue;\r
-\r
-       Y = (int)( 0.2992f * R + 0.5868f * G + 0.1140f * B);\r
-       I = (int)( 0.5960f * R - 0.2742f * G - 0.3219f * B + 128);\r
-       Q = (int)( 0.2109f * R - 0.5229f * G + 0.3120f * B + 128);\r
-\r
-       Y= min(255,max(0,Y));\r
-       I= min(255,max(0,I));\r
-       Q= min(255,max(0,Q));\r
-       RGBQUAD yiq={(BYTE)Q,(BYTE)I,(BYTE)Y,0};\r
-       return yiq;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::XYZtoRGB(RGBQUAD lXYZColor)\r
-{\r
-       int X,Y,Z,R,G,B;\r
-       X = lXYZColor.rgbRed;\r
-       Y = lXYZColor.rgbGreen;\r
-       Z = lXYZColor.rgbBlue;\r
-       double k=1.088751;\r
-\r
-       R = (int)(  3.240479f * X - 1.537150f * Y - 0.498535f * Z * k);\r
-       G = (int)( -0.969256f * X + 1.875992f * Y + 0.041556f * Z * k);\r
-       B = (int)(  0.055648f * X - 0.204043f * Y + 1.057311f * Z * k);\r
-\r
-       R= min(255,max(0,R));\r
-       G= min(255,max(0,G));\r
-       B= min(255,max(0,B));\r
-       RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0};\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::RGBtoXYZ(RGBQUAD lRGBColor)\r
-{\r
-       int X,Y,Z,R,G,B;\r
-       R = lRGBColor.rgbRed;\r
-       G = lRGBColor.rgbGreen;\r
-       B = lRGBColor.rgbBlue;\r
-\r
-       X = (int)( 0.412453f * R + 0.357580f * G + 0.180423f * B);\r
-       Y = (int)( 0.212671f * R + 0.715160f * G + 0.072169f * B);\r
-       Z = (int)((0.019334f * R + 0.119193f * G + 0.950227f * B)*0.918483657f);\r
-\r
-       //X= min(255,max(0,X));\r
-       //Y= min(255,max(0,Y));\r
-       //Z= min(255,max(0,Z));\r
-       RGBQUAD xyz={(BYTE)Z,(BYTE)Y,(BYTE)X,0};\r
-       return xyz;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Generates a "rainbow" palette with saturated colors\r
- * \param correction: 1 generates a single hue spectrum. 0.75 is nice for scientific applications.\r
- */\r
-void CxImage::HuePalette(float correction)\r
-{\r
-       if (head.biClrUsed==0) return;\r
-\r
-       for(DWORD j=0; j<head.biClrUsed; j++){\r
-               BYTE i=(BYTE)(j*correction*(255/(head.biClrUsed-1)));\r
-               RGBQUAD hsl={120,240,i,0};\r
-               SetPaletteColor((BYTE)j,HSLtoRGB(hsl));\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Replaces the original hue and saturation values.\r
- * \param hue: hue\r
- * \param sat: saturation\r
- * \param blend: can be from 0 (no effect) to 1 (full effect)\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Colorize(BYTE hue, BYTE sat, float blend)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       if (blend < 0.0f) blend = 0.0f;\r
-       if (blend > 1.0f) blend = 1.0f;\r
-       int a0 = (int)(256*blend);\r
-       int a1 = 256 - a0;\r
-\r
-       bool bFullBlend = false;\r
-       if (blend > 0.999f)     bFullBlend = true;\r
-\r
-       RGBQUAD color,hsl;\r
-       if (head.biClrUsed==0){\r
-\r
-               long xmin,xmax,ymin,ymax;\r
-               if (pSelection){\r
-                       xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-                       ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-               } else {\r
-                       xmin = ymin = 0;\r
-                       xmax = head.biWidth; ymax=head.biHeight;\r
-               }\r
-\r
-               for(long y=ymin; y<ymax; y++){\r
-                       info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-                       if (info.nEscape) break;\r
-                       for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                               if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                               {\r
-                                       if (bFullBlend){\r
-                                               color = RGBtoHSL(BlindGetPixelColor(x,y));\r
-                                               color.rgbRed=hue;\r
-                                               color.rgbGreen=sat;\r
-                                               BlindSetPixelColor(x,y,HSLtoRGB(color));\r
-                                       } else {\r
-                                               color = BlindGetPixelColor(x,y);\r
-                                               hsl.rgbRed=hue;\r
-                                               hsl.rgbGreen=sat;\r
-                                               hsl.rgbBlue = (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);\r
-                                               hsl = HSLtoRGB(hsl);\r
-                                               //BlendPixelColor(x,y,hsl,blend);\r
-                                               //color.rgbRed = (BYTE)(hsl.rgbRed * blend + color.rgbRed * (1.0f - blend));\r
-                                               //color.rgbBlue = (BYTE)(hsl.rgbBlue * blend + color.rgbBlue * (1.0f - blend));\r
-                                               //color.rgbGreen = (BYTE)(hsl.rgbGreen * blend + color.rgbGreen * (1.0f - blend));\r
-                                               color.rgbRed = (BYTE)((hsl.rgbRed * a0 + color.rgbRed * a1)>>8);\r
-                                               color.rgbBlue = (BYTE)((hsl.rgbBlue * a0 + color.rgbBlue * a1)>>8);\r
-                                               color.rgbGreen = (BYTE)((hsl.rgbGreen * a0 + color.rgbGreen * a1)>>8);\r
-                                               BlindSetPixelColor(x,y,color);\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       } else {\r
-               for(DWORD j=0; j<head.biClrUsed; j++){\r
-                       if (bFullBlend){\r
-                               color = RGBtoHSL(GetPaletteColor((BYTE)j));\r
-                               color.rgbRed=hue;\r
-                               color.rgbGreen=sat;\r
-                               SetPaletteColor((BYTE)j,HSLtoRGB(color));\r
-                       } else {\r
-                               color = GetPaletteColor((BYTE)j);\r
-                               hsl.rgbRed=hue;\r
-                               hsl.rgbGreen=sat;\r
-                               hsl.rgbBlue = (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);\r
-                               hsl = HSLtoRGB(hsl);\r
-                               color.rgbRed = (BYTE)(hsl.rgbRed * blend + color.rgbRed * (1.0f - blend));\r
-                               color.rgbBlue = (BYTE)(hsl.rgbBlue * blend + color.rgbBlue * (1.0f - blend));\r
-                               color.rgbGreen = (BYTE)(hsl.rgbGreen * blend + color.rgbGreen * (1.0f - blend));\r
-                               SetPaletteColor((BYTE)j,color);\r
-                       }\r
-               }\r
-       }\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Changes the brightness and the contrast of the image. \r
- * \param brightness: can be from -255 to 255, if brightness is negative, the image becomes dark.\r
- * \param contrast: can be from -100 to 100, the neutral value is 0.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Light(long brightness, long contrast)\r
-{\r
-       if (!pDib) return false;\r
-       float c=(100 + contrast)/100.0f;\r
-       brightness+=128;\r
-\r
-       BYTE cTable[256]; //<nipper>\r
-       for (int i=0;i<256;i++) {\r
-               cTable[i] = (BYTE)max(0,min(255,(int)((i-128)*c + brightness + 0.5f)));\r
-       }\r
-\r
-       return Lut(cTable);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return mean lightness of the image. Useful with Threshold() and Light()\r
- */\r
-float CxImage::Mean()\r
-{\r
-       if (!pDib) return 0;\r
-\r
-       CxImage tmp(*this,true);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       tmp.GrayScale();\r
-       float sum=0;\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-       if (xmin==xmax || ymin==ymax) return (float)0.0;\r
-\r
-       BYTE *iSrc=tmp.info.pImage;\r
-       iSrc += tmp.info.dwEffWidth*ymin; // necessary for selections <Admir Hodzic>\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin)); //<zhanghk><Anatoly Ivasyuk>\r
-               for(long x=xmin; x<xmax; x++){\r
-                       sum+=iSrc[x];\r
-               }\r
-               iSrc+=tmp.info.dwEffWidth;\r
-       }\r
-       return sum/(xmax-xmin)/(ymax-ymin);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * 2D linear filter\r
- * \param kernel: convolving matrix, in row format.\r
- * \param Ksize: size of the kernel.\r
- * \param Kfactor: normalization constant.\r
- * \param Koffset: bias.\r
- * \verbatim Example: the "soften" filter uses this kernel:\r
-       1 1 1\r
-       1 8 1\r
-       1 1 1\r
- the function needs: kernel={1,1,1,1,8,1,1,1,1}; Ksize=3; Kfactor=16; Koffset=0; \endverbatim\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Filter(long* kernel, long Ksize, long Kfactor, long Koffset)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long k2 = Ksize/2;\r
-       long kmax= Ksize-k2;\r
-       long r,g,b,i;\r
-       long ksumcur,ksumtot;\r
-       RGBQUAD c;\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       ksumtot = 0;\r
-       for(long j=-k2;j<kmax;j++){\r
-               for(long k=-k2;k<kmax;k++){\r
-                       ksumtot += kernel[(j+k2)+Ksize*(k+k2)];\r
-               }\r
-       }\r
-\r
-       if ((head.biBitCount==8) && IsGrayScale())\r
-       {\r
-               unsigned char* cPtr;\r
-               unsigned char* cPtr2;      \r
-               int iCount;\r
-               int iY, iY2, iY1;\r
-               cPtr = info.pImage;\r
-               cPtr2 = (unsigned char *)tmp.info.pImage;\r
-               for(long y=ymin; y<ymax; y++){\r
-                       info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-                       if (info.nEscape) break;\r
-                       iY1 = y*info.dwEffWidth+xmin;\r
-                       for(long x=xmin; x<xmax; x++, iY1++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                               if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                               {\r
-                                       b=ksumcur=0;\r
-                                       iCount = 0;\r
-                                       iY2 = ((y-k2)*info.dwEffWidth);\r
-                                       for(long j=-k2;j<kmax;j++, iY2+=info.dwEffWidth)\r
-                                       {\r
-                                               if (0>(y+j) || (y+j)>=head.biHeight) continue;\r
-                                               iY = iY2+x;\r
-                                               for(long k=-k2;k<kmax;k++, iCount++)\r
-                                               {\r
-                                                       if (0>(x+k) || (x+k)>=head.biWidth) continue;\r
-                                                       i=kernel[iCount];\r
-                                                       b += cPtr[iY+k] * i;\r
-                                                       ksumcur += i;\r
-                                               }\r
-                                       }\r
-                                       if (Kfactor==0 || ksumcur==0){\r
-                                               cPtr2[iY1] = (BYTE)min(255, max(0,(int)(b + Koffset)));\r
-                                       } else if (ksumtot == ksumcur) {\r
-                                               cPtr2[iY1] = (BYTE)min(255, max(0,(int)(b/Kfactor + Koffset)));\r
-                                       } else {\r
-                                               cPtr2[iY1] = (BYTE)min(255, max(0,(int)((b*ksumtot)/(ksumcur*Kfactor) + Koffset)));\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       else\r
-       {\r
-               for(long y=ymin; y<ymax; y++){\r
-                       info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-                       if (info.nEscape) break;\r
-                       for(long x=xmin; x<xmax; x++){\r
-       #if CXIMAGE_SUPPORT_SELECTION\r
-                               if (BlindSelectionIsInside(x,y))\r
-       #endif //CXIMAGE_SUPPORT_SELECTION\r
-                                       {\r
-                                       r=b=g=ksumcur=0;\r
-                                       for(long j=-k2;j<kmax;j++){\r
-                                               for(long k=-k2;k<kmax;k++){\r
-                                                       if (!IsInside(x+j,y+k)) continue;\r
-                                                       c = BlindGetPixelColor(x+j,y+k);\r
-                                                       i = kernel[(j+k2)+Ksize*(k+k2)];\r
-                                                       r += c.rgbRed * i;\r
-                                                       g += c.rgbGreen * i;\r
-                                                       b += c.rgbBlue * i;\r
-                                                       ksumcur += i;\r
-                                               }\r
-                                       }\r
-                                       if (Kfactor==0 || ksumcur==0){\r
-                                               c.rgbRed   = (BYTE)min(255, max(0,(int)(r + Koffset)));\r
-                                               c.rgbGreen = (BYTE)min(255, max(0,(int)(g + Koffset)));\r
-                                               c.rgbBlue  = (BYTE)min(255, max(0,(int)(b + Koffset)));\r
-                                       } else if (ksumtot == ksumcur) {\r
-                                               c.rgbRed   = (BYTE)min(255, max(0,(int)(r/Kfactor + Koffset)));\r
-                                               c.rgbGreen = (BYTE)min(255, max(0,(int)(g/Kfactor + Koffset)));\r
-                                               c.rgbBlue  = (BYTE)min(255, max(0,(int)(b/Kfactor + Koffset)));\r
-                                       } else {\r
-                                               c.rgbRed   = (BYTE)min(255, max(0,(int)((r*ksumtot)/(ksumcur*Kfactor) + Koffset)));\r
-                                               c.rgbGreen = (BYTE)min(255, max(0,(int)((g*ksumtot)/(ksumcur*Kfactor) + Koffset)));\r
-                                               c.rgbBlue  = (BYTE)min(255, max(0,(int)((b*ksumtot)/(ksumcur*Kfactor) + Koffset)));\r
-                                       }\r
-                                       tmp.BlindSetPixelColor(x,y,c);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Enhance the dark areas of the image\r
- * \param Ksize: size of the kernel.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Erode(long Ksize)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long k2 = Ksize/2;\r
-       long kmax= Ksize-k2;\r
-       BYTE r,g,b;\r
-       RGBQUAD c;\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               r=b=g=255;\r
-                               for(long j=-k2;j<kmax;j++){\r
-                                       for(long k=-k2;k<kmax;k++){\r
-                                               if (!IsInside(x+j,y+k)) continue;\r
-                                               c = BlindGetPixelColor(x+j,y+k);\r
-                                               if (c.rgbRed < r) r=c.rgbRed;\r
-                                               if (c.rgbGreen < g) g=c.rgbGreen;\r
-                                               if (c.rgbBlue < b) b=c.rgbBlue;\r
-                                       }\r
-                               }\r
-                               c.rgbRed   = r;\r
-                               c.rgbGreen = g;\r
-                               c.rgbBlue  = b;\r
-                               tmp.BlindSetPixelColor(x,y,c);\r
-                       }\r
-               }\r
-       }\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Enhance the light areas of the image\r
- * \param Ksize: size of the kernel.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Dilate(long Ksize)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long k2 = Ksize/2;\r
-       long kmax= Ksize-k2;\r
-       BYTE r,g,b;\r
-       RGBQUAD c;\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               r=b=g=0;\r
-                               for(long j=-k2;j<kmax;j++){\r
-                                       for(long k=-k2;k<kmax;k++){\r
-                                               if (!IsInside(x+j,y+k)) continue;\r
-                                               c = BlindGetPixelColor(x+j,y+k);\r
-                                               if (c.rgbRed > r) r=c.rgbRed;\r
-                                               if (c.rgbGreen > g) g=c.rgbGreen;\r
-                                               if (c.rgbBlue > b) b=c.rgbBlue;\r
-                                       }\r
-                               }\r
-                               c.rgbRed   = r;\r
-                               c.rgbGreen = g;\r
-                               c.rgbBlue  = b;\r
-                               tmp.BlindSetPixelColor(x,y,c);\r
-                       }\r
-               }\r
-       }\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Enhance the variations between adjacent pixels.\r
- * Similar results can be achieved using Filter(),\r
- * but the algorithms are different both in Edge() and in Contour().\r
- * \param Ksize: size of the kernel.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Edge(long Ksize)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long k2 = Ksize/2;\r
-       long kmax= Ksize-k2;\r
-       BYTE r,g,b,rr,gg,bb;\r
-       RGBQUAD c;\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               r=b=g=0;\r
-                               rr=bb=gg=255;\r
-                               for(long j=-k2;j<kmax;j++){\r
-                                       for(long k=-k2;k<kmax;k++){\r
-                                               if (!IsInside(x+j,y+k)) continue;\r
-                                               c = BlindGetPixelColor(x+j,y+k);\r
-                                               if (c.rgbRed > r) r=c.rgbRed;\r
-                                               if (c.rgbGreen > g) g=c.rgbGreen;\r
-                                               if (c.rgbBlue > b) b=c.rgbBlue;\r
-\r
-                                               if (c.rgbRed < rr) rr=c.rgbRed;\r
-                                               if (c.rgbGreen < gg) gg=c.rgbGreen;\r
-                                               if (c.rgbBlue < bb) bb=c.rgbBlue;\r
-                                       }\r
-                               }\r
-                               c.rgbRed   = (BYTE)(255-abs(r-rr));\r
-                               c.rgbGreen = (BYTE)(255-abs(g-gg));\r
-                               c.rgbBlue  = (BYTE)(255-abs(b-bb));\r
-                               tmp.BlindSetPixelColor(x,y,c);\r
-                       }\r
-               }\r
-       }\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Blends two images\r
- * \param imgsrc2: image to be mixed with this\r
- * \param op: blending method; see ImageOpType\r
- * \param lXOffset, lYOffset: image displacement\r
- * \param bMixAlpha: if true and imgsrc2 has a valid alpha layer, it will be mixed in the destination image.\r
- * \return true if everything is ok\r
- *\r
- * thanks to Mwolski\r
- */\r
-// \r
-void CxImage::Mix(CxImage & imgsrc2, ImageOpType op, long lXOffset, long lYOffset, bool bMixAlpha)\r
-{\r
-    long lWide = min(GetWidth(),imgsrc2.GetWidth()-lXOffset);\r
-    long lHeight = min(GetHeight(),imgsrc2.GetHeight()-lYOffset);\r
-\r
-       bool bEditAlpha = imgsrc2.AlphaIsValid() & bMixAlpha;\r
-\r
-       if (bEditAlpha && AlphaIsValid()==false){\r
-               AlphaCreate();\r
-       }\r
-\r
-    RGBQUAD rgbBackgrnd1 = GetTransColor();\r
-    RGBQUAD rgb1, rgb2, rgbDest;\r
-\r
-    for(long lY=0;lY<lHeight;lY++)\r
-    {\r
-               info.nProgress = (long)(100*lY/head.biHeight);\r
-               if (info.nEscape) break;\r
-\r
-        for(long lX=0;lX<lWide;lX++)\r
-        {\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (SelectionIsInside(lX,lY) && imgsrc2.SelectionIsInside(lX+lXOffset,lY+lYOffset))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               rgb1 = GetPixelColor(lX,lY);\r
-                               rgb2 = imgsrc2.GetPixelColor(lX+lXOffset,lY+lYOffset);\r
-                               switch(op)\r
-                               {\r
-                                       case OpAvg:\r
-                                               rgbDest.rgbBlue =  (BYTE)((rgb1.rgbBlue+rgb2.rgbBlue)/2);\r
-                                               rgbDest.rgbGreen = (BYTE)((rgb1.rgbGreen+rgb2.rgbGreen)/2);\r
-                                               rgbDest.rgbRed =   (BYTE)((rgb1.rgbRed+rgb2.rgbRed)/2);\r
-                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)((rgb1.rgbReserved+rgb2.rgbReserved)/2);\r
-                                       break;\r
-                                       case OpAdd:\r
-                                               rgbDest.rgbBlue = (BYTE)max(0,min(255,rgb1.rgbBlue+rgb2.rgbBlue));\r
-                                               rgbDest.rgbGreen = (BYTE)max(0,min(255,rgb1.rgbGreen+rgb2.rgbGreen));\r
-                                               rgbDest.rgbRed = (BYTE)max(0,min(255,rgb1.rgbRed+rgb2.rgbRed));\r
-                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)max(0,min(255,rgb1.rgbReserved+rgb2.rgbReserved));\r
-                                       break;\r
-                                       case OpSub:\r
-                                               rgbDest.rgbBlue = (BYTE)max(0,min(255,rgb1.rgbBlue-rgb2.rgbBlue));\r
-                                               rgbDest.rgbGreen = (BYTE)max(0,min(255,rgb1.rgbGreen-rgb2.rgbGreen));\r
-                                               rgbDest.rgbRed = (BYTE)max(0,min(255,rgb1.rgbRed-rgb2.rgbRed));\r
-                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)max(0,min(255,rgb1.rgbReserved-rgb2.rgbReserved));\r
-                                       break;\r
-                                       case OpAnd:\r
-                                               rgbDest.rgbBlue = (BYTE)(rgb1.rgbBlue&rgb2.rgbBlue);\r
-                                               rgbDest.rgbGreen = (BYTE)(rgb1.rgbGreen&rgb2.rgbGreen);\r
-                                               rgbDest.rgbRed = (BYTE)(rgb1.rgbRed&rgb2.rgbRed);\r
-                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(rgb1.rgbReserved&rgb2.rgbReserved);\r
-                                       break;\r
-                                       case OpXor:\r
-                                               rgbDest.rgbBlue = (BYTE)(rgb1.rgbBlue^rgb2.rgbBlue);\r
-                                               rgbDest.rgbGreen = (BYTE)(rgb1.rgbGreen^rgb2.rgbGreen);\r
-                                               rgbDest.rgbRed = (BYTE)(rgb1.rgbRed^rgb2.rgbRed);\r
-                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(rgb1.rgbReserved^rgb2.rgbReserved);\r
-                                       break;\r
-                                       case OpOr:\r
-                                               rgbDest.rgbBlue = (BYTE)(rgb1.rgbBlue|rgb2.rgbBlue);\r
-                                               rgbDest.rgbGreen = (BYTE)(rgb1.rgbGreen|rgb2.rgbGreen);\r
-                                               rgbDest.rgbRed = (BYTE)(rgb1.rgbRed|rgb2.rgbRed);\r
-                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(rgb1.rgbReserved|rgb2.rgbReserved);\r
-                                       break;\r
-                                       case OpMask:\r
-                                               if(rgb2.rgbBlue==0 && rgb2.rgbGreen==0 && rgb2.rgbRed==0)\r
-                                                       rgbDest = rgbBackgrnd1;\r
-                                               else\r
-                                                       rgbDest = rgb1;\r
-                                               break;\r
-                                       case OpSrcCopy:\r
-                                               if(IsTransparent(lX,lY))\r
-                                                       rgbDest = rgb2;\r
-                                               else // copy straight over\r
-                                                       rgbDest = rgb1;\r
-                                               break;\r
-                                       case OpDstCopy:\r
-                                               if(imgsrc2.IsTransparent(lX+lXOffset,lY+lYOffset))\r
-                                                       rgbDest = rgb1;\r
-                                               else // copy straight over\r
-                                                       rgbDest = rgb2;\r
-                                               break;\r
-                                       case OpScreen:\r
-                                               { \r
-                                                       BYTE a,a1; \r
-                                                       \r
-                                                       if (imgsrc2.IsTransparent(lX+lXOffset,lY+lYOffset)){\r
-                                                               a=0;\r
-                                                       } else if (imgsrc2.AlphaIsValid()){\r
-                                                               a=imgsrc2.AlphaGet(lX+lXOffset,lY+lYOffset);\r
-                                                               a =(BYTE)((a*imgsrc2.info.nAlphaMax)/255);\r
-                                                       } else {\r
-                                                               a=255;\r
-                                                       }\r
-\r
-                                                       if (a==0){ //transparent \r
-                                                               rgbDest = rgb1; \r
-                                                       } else if (a==255){ //opaque \r
-                                                               rgbDest = rgb2; \r
-                                                       } else { //blend \r
-                                                               a1 = (BYTE)~a; \r
-                                                               rgbDest.rgbBlue = (BYTE)((rgb1.rgbBlue*a1+rgb2.rgbBlue*a)/255); \r
-                                                               rgbDest.rgbGreen = (BYTE)((rgb1.rgbGreen*a1+rgb2.rgbGreen*a)/255); \r
-                                                               rgbDest.rgbRed = (BYTE)((rgb1.rgbRed*a1+rgb2.rgbRed*a)/255);  \r
-                                                       }\r
-\r
-                                                       if (bEditAlpha) rgbDest.rgbReserved = (BYTE)((rgb1.rgbReserved*a)/255);\r
-                                               } \r
-                                               break; \r
-                                       case OpSrcBlend:\r
-                                               if(IsTransparent(lX,lY))\r
-                                                       rgbDest = rgb2;\r
-                                               else\r
-                                               {\r
-                                                       long lBDiff = abs(rgb1.rgbBlue - rgbBackgrnd1.rgbBlue);\r
-                                                       long lGDiff = abs(rgb1.rgbGreen - rgbBackgrnd1.rgbGreen);\r
-                                                       long lRDiff = abs(rgb1.rgbRed - rgbBackgrnd1.rgbRed);\r
-\r
-                                                       double lAverage = (lBDiff+lGDiff+lRDiff)/3;\r
-                                                       double lThresh = 16;\r
-                                                       double dLarge = lAverage/lThresh;\r
-                                                       double dSmall = (lThresh-lAverage)/lThresh;\r
-                                                       double dSmallAmt = dSmall*((double)rgb2.rgbBlue);\r
-\r
-                                                       if( lAverage < lThresh+1){\r
-                                                               rgbDest.rgbBlue = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbBlue) +\r
-                                                                                               dSmallAmt)));\r
-                                                               rgbDest.rgbGreen = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbGreen) +\r
-                                                                                               dSmallAmt)));\r
-                                                               rgbDest.rgbRed = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbRed) +\r
-                                                                                               dSmallAmt)));\r
-                                                       }\r
-                                                       else\r
-                                                               rgbDest = rgb1;\r
-                                               }\r
-                                               break;\r
-                                               default:\r
-                                               return;\r
-                               }\r
-                               SetPixelColor(lX,lY,rgbDest,bEditAlpha);\r
-                       }\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// thanks to Kenneth Ballard\r
-void CxImage::MixFrom(CxImage & imagesrc2, long lXOffset, long lYOffset)\r
-{\r
-    long width = imagesrc2.GetWidth();\r
-    long height = imagesrc2.GetHeight();\r
-\r
-    int x, y;\r
-\r
-       if (imagesrc2.IsTransparent()) {\r
-               for(x = 0; x < width; x++) {\r
-                       for(y = 0; y < height; y++) {\r
-                               if(!imagesrc2.IsTransparent(x,y)){\r
-                                       SetPixelColor(x + lXOffset, y + lYOffset, imagesrc2.BlindGetPixelColor(x, y));\r
-                               }\r
-                       }\r
-               }\r
-       } else { //no transparency so just set it <Matt>\r
-               for(x = 0; x < width; x++) {\r
-                       for(y = 0; y < height; y++) {\r
-                               SetPixelColor(x + lXOffset, y + lYOffset, imagesrc2.BlindGetPixelColor(x, y)); \r
-                       }\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adjusts separately the red, green, and blue values in the image.\r
- * \param r, g, b: can be from -255 to +255.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::ShiftRGB(long r, long g, long b)\r
-{\r
-       if (!pDib) return false;\r
-       RGBQUAD color;\r
-       if (head.biClrUsed==0){\r
-\r
-               long xmin,xmax,ymin,ymax;\r
-               if (pSelection){\r
-                       xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-                       ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-               } else {\r
-                       xmin = ymin = 0;\r
-                       xmax = head.biWidth; ymax=head.biHeight;\r
-               }\r
-\r
-               for(long y=ymin; y<ymax; y++){\r
-                       for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                               if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                               {\r
-                                       color = BlindGetPixelColor(x,y);\r
-                                       color.rgbRed = (BYTE)max(0,min(255,(int)(color.rgbRed + r)));\r
-                                       color.rgbGreen = (BYTE)max(0,min(255,(int)(color.rgbGreen + g)));\r
-                                       color.rgbBlue = (BYTE)max(0,min(255,(int)(color.rgbBlue + b)));\r
-                                       BlindSetPixelColor(x,y,color);\r
-                               }\r
-                       }\r
-               }\r
-       } else {\r
-               for(DWORD j=0; j<head.biClrUsed; j++){\r
-                       color = GetPaletteColor((BYTE)j);\r
-                       color.rgbRed = (BYTE)max(0,min(255,(int)(color.rgbRed + r)));\r
-                       color.rgbGreen = (BYTE)max(0,min(255,(int)(color.rgbGreen + g)));\r
-                       color.rgbBlue = (BYTE)max(0,min(255,(int)(color.rgbBlue + b)));\r
-                       SetPaletteColor((BYTE)j,color);\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adjusts the color balance of the image\r
- * \param gamma can be from 0.1 to 5.\r
- * \return true if everything is ok\r
- * \sa GammaRGB\r
- */\r
-bool CxImage::Gamma(float gamma)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       if (gamma <= 0.0f) return false;\r
-\r
-       double dinvgamma = 1/gamma;\r
-       double dMax = pow(255.0, dinvgamma) / 255.0;\r
-\r
-       BYTE cTable[256]; //<nipper>\r
-       for (int i=0;i<256;i++) {\r
-               cTable[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax)));\r
-       }\r
-\r
-       return Lut(cTable);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adjusts the color balance indipendent for each color channel\r
- * \param gammaR, gammaG, gammaB  can be from 0.1 to 5.\r
- * \return true if everything is ok\r
- * \sa Gamma\r
- */\r
-bool CxImage::GammaRGB(float gammaR, float gammaG, float gammaB)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       if (gammaR <= 0.0f) return false;\r
-       if (gammaG <= 0.0f) return false;\r
-       if (gammaB <= 0.0f) return false;\r
-\r
-       double dinvgamma, dMax;\r
-       int i;\r
-\r
-       dinvgamma = 1/gammaR;\r
-       dMax = pow(255.0, dinvgamma) / 255.0;\r
-       BYTE cTableR[256];\r
-       for (i=0;i<256;i++)     {\r
-               cTableR[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax)));\r
-       }\r
-\r
-       dinvgamma = 1/gammaG;\r
-       dMax = pow(255.0, dinvgamma) / 255.0;\r
-       BYTE cTableG[256];\r
-       for (i=0;i<256;i++)     {\r
-               cTableG[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax)));\r
-       }\r
-\r
-       dinvgamma = 1/gammaB;\r
-       dMax = pow(255.0, dinvgamma) / 255.0;\r
-       BYTE cTableB[256];\r
-       for (i=0;i<256;i++)     {\r
-               cTableB[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax)));\r
-       }\r
-\r
-       return Lut(cTableR, cTableG, cTableB);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-//#if !defined (_WIN32_WCE)\r
-/**\r
- * Adjusts the intensity of each pixel to the median intensity of its surrounding pixels.\r
- * \param Ksize: size of the kernel.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Median(long Ksize)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long k2 = Ksize/2;\r
-       long kmax= Ksize-k2;\r
-       long i,j,k;\r
-\r
-       RGBQUAD* kernel = (RGBQUAD*)malloc(Ksize*Ksize*sizeof(RGBQUAD));\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                               {\r
-                               for(j=-k2, i=0;j<kmax;j++)\r
-                                       for(k=-k2;k<kmax;k++)\r
-                                               if (IsInside(x+j,y+k))\r
-                                                       kernel[i++]=BlindGetPixelColor(x+j,y+k);\r
-\r
-                               qsort(kernel, i, sizeof(RGBQUAD), CompareColors);\r
-                               tmp.SetPixelColor(x,y,kernel[i/2]);\r
-                       }\r
-               }\r
-       }\r
-       free(kernel);\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-//#endif //_WIN32_WCE\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adds an uniform noise to the image\r
- * \param level: can be from 0 (no noise) to 255 (lot of noise).\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Noise(long level)\r
-{\r
-       if (!pDib) return false;\r
-       RGBQUAD color;\r
-\r
-       long xmin,xmax,ymin,ymax,n;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin)); //<zhanghk><Anatoly Ivasyuk>\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               color = BlindGetPixelColor(x,y);\r
-                               n=(long)((rand()/(float)RAND_MAX - 0.5)*level);\r
-                               color.rgbRed = (BYTE)max(0,min(255,(int)(color.rgbRed + n)));\r
-                               n=(long)((rand()/(float)RAND_MAX - 0.5)*level);\r
-                               color.rgbGreen = (BYTE)max(0,min(255,(int)(color.rgbGreen + n)));\r
-                               n=(long)((rand()/(float)RAND_MAX - 0.5)*level);\r
-                               color.rgbBlue = (BYTE)max(0,min(255,(int)(color.rgbBlue + n)));\r
-                               BlindSetPixelColor(x,y,color);\r
-                       }\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Computes the bidimensional FFT or DFT of the image.\r
- * - The images are processed as grayscale\r
- * - If the dimensions of the image are a power of, 2 the FFT is performed automatically.\r
- * - If dstReal and/or dstImag are NULL, the resulting images replaces the original(s).\r
- * - Note: with 8 bits there is a HUGE loss in the dynamics. The function tries\r
- *   to keep an acceptable SNR, but 8bit = 48dB...\r
- *\r
- * \param srcReal, srcImag: source images: One can be NULL, but not both\r
- * \param dstReal, dstImag: destination images. Can be NULL.\r
- * \param direction: 1 = forward, -1 = inverse.\r
- * \param bForceFFT: if true, the images are resampled to make the dimensions a power of 2.\r
- * \param bMagnitude: if true, the real part returns the magnitude, the imaginary part returns the phase\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::FFT2(CxImage* srcReal, CxImage* srcImag, CxImage* dstReal, CxImage* dstImag,\r
-                                  long direction, bool bForceFFT, bool bMagnitude)\r
-{\r
-       //check if there is something to convert\r
-       if (srcReal==NULL && srcImag==NULL) return false;\r
-\r
-       long w,h;\r
-       //get width and height\r
-       if (srcReal) {\r
-               w=srcReal->GetWidth();\r
-               h=srcReal->GetHeight();\r
-       } else {\r
-               w=srcImag->GetWidth();\r
-               h=srcImag->GetHeight();\r
-       }\r
-\r
-       bool bXpow2 = IsPowerof2(w);\r
-       bool bYpow2 = IsPowerof2(h);\r
-       //if bForceFFT, width AND height must be powers of 2\r
-       if (bForceFFT && !(bXpow2 && bYpow2)) {\r
-               long i;\r
-               \r
-               i=0;\r
-               while((1<<i)<w) i++;\r
-               w=1<<i;\r
-               bXpow2=true;\r
-\r
-               i=0;\r
-               while((1<<i)<h) i++;\r
-               h=1<<i;\r
-               bYpow2=true;\r
-       }\r
-\r
-       // I/O images for FFT\r
-       CxImage *tmpReal,*tmpImag;\r
-\r
-       // select output\r
-       tmpReal = (dstReal) ? dstReal : srcReal;\r
-       tmpImag = (dstImag) ? dstImag : srcImag;\r
-\r
-       // src!=dst -> copy the image\r
-       if (srcReal && dstReal) tmpReal->Copy(*srcReal,true,false,false);\r
-       if (srcImag && dstImag) tmpImag->Copy(*srcImag,true,false,false);\r
-\r
-       // dst&&src are empty -> create new one, else turn to GrayScale\r
-       if (srcReal==0 && dstReal==0){\r
-               tmpReal = new CxImage(w,h,8);\r
-               tmpReal->Clear(0);\r
-               tmpReal->SetGrayPalette();\r
-       } else {\r
-               if (!tmpReal->IsGrayScale()) tmpReal->GrayScale();\r
-       }\r
-       if (srcImag==0 && dstImag==0){\r
-               tmpImag = new CxImage(w,h,8);\r
-               tmpImag->Clear(0);\r
-               tmpImag->SetGrayPalette();\r
-       } else {\r
-               if (!tmpImag->IsGrayScale()) tmpImag->GrayScale();\r
-       }\r
-\r
-       if (!(tmpReal->IsValid() && tmpImag->IsValid())){\r
-               if (srcReal==0 && dstReal==0) delete tmpReal;\r
-               if (srcImag==0 && dstImag==0) delete tmpImag;\r
-               return false;\r
-       }\r
-\r
-       //resample for FFT, if necessary \r
-       tmpReal->Resample(w,h,0);\r
-       tmpImag->Resample(w,h,0);\r
-\r
-       //ok, here we have 2 (w x h), grayscale images ready for a FFT\r
-\r
-       double* real;\r
-       double* imag;\r
-       long j,k,m;\r
-\r
-       _complex **grid;\r
-       //double mean = tmpReal->Mean();\r
-       /* Allocate memory for the grid */\r
-       grid = (_complex **)malloc(w * sizeof(_complex));\r
-       for (k=0;k<w;k++) {\r
-               grid[k] = (_complex *)malloc(h * sizeof(_complex));\r
-       }\r
-       for (j=0;j<h;j++) {\r
-               for (k=0;k<w;k++) {\r
-                       grid[k][j].x = tmpReal->GetPixelIndex(k,j)-128;\r
-                       grid[k][j].y = tmpImag->GetPixelIndex(k,j)-128;\r
-               }\r
-       }\r
-\r
-       //DFT buffers\r
-       double *real2,*imag2;\r
-       real2 = (double*)malloc(max(w,h) * sizeof(double));\r
-       imag2 = (double*)malloc(max(w,h) * sizeof(double));\r
-\r
-       /* Transform the rows */\r
-       real = (double *)malloc(w * sizeof(double));\r
-       imag = (double *)malloc(w * sizeof(double));\r
-\r
-       m=0;\r
-       while((1<<m)<w) m++;\r
-\r
-       for (j=0;j<h;j++) {\r
-               for (k=0;k<w;k++) {\r
-                       real[k] = grid[k][j].x;\r
-                       imag[k] = grid[k][j].y;\r
-               }\r
-\r
-               if (bXpow2) FFT(direction,m,real,imag);\r
-               else            DFT(direction,w,real,imag,real2,imag2);\r
-\r
-               for (k=0;k<w;k++) {\r
-                       grid[k][j].x = real[k];\r
-                       grid[k][j].y = imag[k];\r
-               }\r
-       }\r
-       free(real);\r
-       free(imag);\r
-\r
-       /* Transform the columns */\r
-       real = (double *)malloc(h * sizeof(double));\r
-       imag = (double *)malloc(h * sizeof(double));\r
-\r
-       m=0;\r
-       while((1<<m)<h) m++;\r
-\r
-       for (k=0;k<w;k++) {\r
-               for (j=0;j<h;j++) {\r
-                       real[j] = grid[k][j].x;\r
-                       imag[j] = grid[k][j].y;\r
-               }\r
-\r
-               if (bYpow2) FFT(direction,m,real,imag);\r
-               else            DFT(direction,h,real,imag,real2,imag2);\r
-\r
-               for (j=0;j<h;j++) {\r
-                       grid[k][j].x = real[j];\r
-                       grid[k][j].y = imag[j];\r
-               }\r
-       }\r
-       free(real);\r
-       free(imag);\r
-\r
-       free(real2);\r
-       free(imag2);\r
-\r
-       /* converting from double to byte, there is a HUGE loss in the dynamics\r
-         "nn" tries to keep an acceptable SNR, but 8bit=48dB: don't ask more */\r
-       double nn=pow((double)2,(double)log((double)max(w,h))/(double)log((double)2)-4);\r
-       //reversed gain for reversed transform\r
-       if (direction==-1) nn=1/nn;\r
-       //bMagnitude : just to see it on the screen\r
-       if (bMagnitude) nn*=4;\r
-\r
-       for (j=0;j<h;j++) {\r
-               for (k=0;k<w;k++) {\r
-                       if (bMagnitude){\r
-                               tmpReal->SetPixelIndex(k,j,(BYTE)max(0,min(255,(nn*(3+log(_cabs(grid[k][j])))))));\r
-                               if (grid[k][j].x==0){\r
-                                       tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/0.0000000001)*nn)))));\r
-                               } else {\r
-                                       tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/grid[k][j].x)*nn)))));\r
-                               }\r
-                       } else {\r
-                               tmpReal->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].x*nn))));\r
-                               tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].y*nn))));\r
-                       }\r
-               }\r
-       }\r
-\r
-       for (k=0;k<w;k++) free (grid[k]);\r
-       free (grid);\r
-\r
-       if (srcReal==0 && dstReal==0) delete tmpReal;\r
-       if (srcImag==0 && dstImag==0) delete tmpImag;\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::IsPowerof2(long x)\r
-{\r
-       long i=0;\r
-       while ((1<<i)<x) i++;\r
-       if (x==(1<<i)) return true;\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
-   This computes an in-place complex-to-complex FFT \r
-   x and y are the real and imaginary arrays of n=2^m points.\r
-   o(n)=n*log2(n)\r
-   dir =  1 gives forward transform\r
-   dir = -1 gives reverse transform \r
-   Written by Paul Bourke, July 1998\r
-   FFT algorithm by Cooley and Tukey, 1965 \r
-*/\r
-bool CxImage::FFT(int dir,int m,double *x,double *y)\r
-{\r
-       long nn,i,i1,j,k,i2,l,l1,l2;\r
-       double c1,c2,tx,ty,t1,t2,u1,u2,z;\r
-\r
-       /* Calculate the number of points */\r
-       nn = 1<<m;\r
-\r
-       /* Do the bit reversal */\r
-       i2 = nn >> 1;\r
-       j = 0;\r
-       for (i=0;i<nn-1;i++) {\r
-               if (i < j) {\r
-                       tx = x[i];\r
-                       ty = y[i];\r
-                       x[i] = x[j];\r
-                       y[i] = y[j];\r
-                       x[j] = tx;\r
-                       y[j] = ty;\r
-               }\r
-               k = i2;\r
-               while (k <= j) {\r
-                       j -= k;\r
-                       k >>= 1;\r
-               }\r
-               j += k;\r
-       }\r
-\r
-       /* Compute the FFT */\r
-       c1 = -1.0;\r
-       c2 = 0.0;\r
-       l2 = 1;\r
-       for (l=0;l<m;l++) {\r
-               l1 = l2;\r
-               l2 <<= 1;\r
-               u1 = 1.0;\r
-               u2 = 0.0;\r
-               for (j=0;j<l1;j++) {\r
-                       for (i=j;i<nn;i+=l2) {\r
-                               i1 = i + l1;\r
-                               t1 = u1 * x[i1] - u2 * y[i1];\r
-                               t2 = u1 * y[i1] + u2 * x[i1];\r
-                               x[i1] = x[i] - t1;\r
-                               y[i1] = y[i] - t2;\r
-                               x[i] += t1;\r
-                               y[i] += t2;\r
-                       }\r
-                       z =  u1 * c1 - u2 * c2;\r
-                       u2 = u1 * c2 + u2 * c1;\r
-                       u1 = z;\r
-               }\r
-               c2 = sqrt((1.0 - c1) / 2.0);\r
-               if (dir == 1)\r
-                       c2 = -c2;\r
-               c1 = sqrt((1.0 + c1) / 2.0);\r
-       }\r
-\r
-       /* Scaling for forward transform */\r
-       if (dir == 1) {\r
-               for (i=0;i<nn;i++) {\r
-                       x[i] /= (double)nn;\r
-                       y[i] /= (double)nn;\r
-               }\r
-       }\r
-\r
-   return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
-   Direct fourier transform o(n)=n^2\r
-   Written by Paul Bourke, July 1998 \r
-*/\r
-bool CxImage::DFT(int dir,long m,double *x1,double *y1,double *x2,double *y2)\r
-{\r
-   long i,k;\r
-   double arg;\r
-   double cosarg,sinarg;\r
-   \r
-   for (i=0;i<m;i++) {\r
-      x2[i] = 0;\r
-      y2[i] = 0;\r
-      arg = - dir * 2.0 * PI * i / (double)m;\r
-      for (k=0;k<m;k++) {\r
-         cosarg = cos(k * arg);\r
-         sinarg = sin(k * arg);\r
-         x2[i] += (x1[k] * cosarg - y1[k] * sinarg);\r
-         y2[i] += (x1[k] * sinarg + y1[k] * cosarg);\r
-      }\r
-   }\r
-   \r
-   /* Copy the data back */\r
-   if (dir == 1) {\r
-      for (i=0;i<m;i++) {\r
-         x1[i] = x2[i] / m;\r
-         y1[i] = y2[i] / m;\r
-      }\r
-   } else {\r
-      for (i=0;i<m;i++) {\r
-         x1[i] = x2[i];\r
-         y1[i] = y2[i];\r
-      }\r
-   }\r
-   \r
-   return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Combines different color components into a single image\r
- * \param r,g,b: color channels\r
- * \param a: alpha layer, can be NULL\r
- * \param colorspace: 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ \r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Combine(CxImage* r,CxImage* g,CxImage* b,CxImage* a, long colorspace)\r
-{\r
-       if (r==0 || g==0 || b==0) return false;\r
-\r
-       long w = r->GetWidth();\r
-       long h = r->GetHeight();\r
-\r
-       Create(w,h,24);\r
-\r
-       g->Resample(w,h);\r
-       b->Resample(w,h);\r
-\r
-       if (a) {\r
-               a->Resample(w,h);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               AlphaCreate();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       }\r
-\r
-       RGBQUAD c;\r
-       for (long y=0;y<h;y++){\r
-               info.nProgress = (long)(100*y/h); //<Anatoly Ivasyuk>\r
-               for (long x=0;x<w;x++){\r
-                       c.rgbRed=r->GetPixelIndex(x,y);\r
-                       c.rgbGreen=g->GetPixelIndex(x,y);\r
-                       c.rgbBlue=b->GetPixelIndex(x,y);\r
-                       switch (colorspace){\r
-                       case 1:\r
-                               BlindSetPixelColor(x,y,HSLtoRGB(c));\r
-                               break;\r
-                       case 2:\r
-                               BlindSetPixelColor(x,y,YUVtoRGB(c));\r
-                               break;\r
-                       case 3:\r
-                               BlindSetPixelColor(x,y,YIQtoRGB(c));\r
-                               break;\r
-                       case 4:\r
-                               BlindSetPixelColor(x,y,XYZtoRGB(c));\r
-                               break;\r
-                       default:\r
-                               BlindSetPixelColor(x,y,c);\r
-                       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       if (a) AlphaSet(x,y,a->GetPixelIndex(x,y));\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-               }\r
-       }\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Smart blurring to remove small defects, dithering or artifacts.\r
- * \param radius: normally between 0.01 and 0.5\r
- * \param niterations: should be trimmed with radius, to avoid blurring should be (radius*niterations)<1\r
- * \param colorspace: 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ \r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Repair(float radius, long niterations, long colorspace)\r
-{\r
-       if (!IsValid()) return false;\r
-\r
-       long w = GetWidth();\r
-       long h = GetHeight();\r
-\r
-       CxImage r,g,b;\r
-\r
-       r.Create(w,h,8);\r
-       g.Create(w,h,8);\r
-       b.Create(w,h,8);\r
-\r
-       switch (colorspace){\r
-       case 1:\r
-               SplitHSL(&r,&g,&b);\r
-               break;\r
-       case 2:\r
-               SplitYUV(&r,&g,&b);\r
-               break;\r
-       case 3:\r
-               SplitYIQ(&r,&g,&b);\r
-               break;\r
-       case 4:\r
-               SplitXYZ(&r,&g,&b);\r
-               break;\r
-       default:\r
-               SplitRGB(&r,&g,&b);\r
-       }\r
-       \r
-       for (int i=0; i<niterations; i++){\r
-               RepairChannel(&r,radius);\r
-               RepairChannel(&g,radius);\r
-               RepairChannel(&b,radius);\r
-       }\r
-\r
-       CxImage* a=NULL;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()){\r
-               a = new CxImage();\r
-               AlphaSplit(a);\r
-       }\r
-#endif\r
-\r
-       Combine(&r,&g,&b,a,colorspace);\r
-\r
-       delete a;\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::RepairChannel(CxImage *ch, float radius)\r
-{\r
-       if (ch==NULL) return false;\r
-\r
-       CxImage tmp(*ch);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long w = ch->GetWidth()-1;\r
-       long h = ch->GetHeight()-1;\r
-\r
-       double correction,ix,iy,ixx,ixy,iyy;\r
-       int x,y,xy0,xp1,xm1,yp1,ym1;\r
-\r
-       for(x=1; x<w; x++){\r
-               for(y=1; y<h; y++){\r
-\r
-                       xy0 = ch->BlindGetPixelIndex(x,y);\r
-                       xm1 = ch->BlindGetPixelIndex(x-1,y);\r
-                       xp1 = ch->BlindGetPixelIndex(x+1,y);\r
-                       ym1 = ch->BlindGetPixelIndex(x,y-1);\r
-                       yp1 = ch->BlindGetPixelIndex(x,y+1);\r
-\r
-                       ix= (xp1-xm1)/2.0;\r
-                       iy= (yp1-ym1)/2.0;\r
-                       ixx= xp1 - 2.0 * xy0 + xm1;\r
-                       iyy= yp1 - 2.0 * xy0 + ym1;\r
-                       ixy=(ch->BlindGetPixelIndex(x+1,y+1) + ch->BlindGetPixelIndex(x-1,y-1) -\r
-                                ch->BlindGetPixelIndex(x-1,y+1) - ch->BlindGetPixelIndex(x+1,y-1))/4.0;\r
-\r
-                       correction = ((1.0+iy*iy)*ixx - ix*iy*ixy + (1.0+ix*ix)*iyy)/(1.0+ix*ix+iy*iy);\r
-\r
-                       tmp.BlindSetPixelIndex(x,y,(BYTE)min(255,max(0,(xy0 + radius * correction + 0.5))));\r
-               }\r
-       }\r
-\r
-       for (x=0;x<=w;x++){\r
-               for(y=0; y<=h; y+=h){\r
-                       xy0 = ch->BlindGetPixelIndex(x,y);\r
-                       xm1 = ch->GetPixelIndex(x-1,y);\r
-                       xp1 = ch->GetPixelIndex(x+1,y);\r
-                       ym1 = ch->GetPixelIndex(x,y-1);\r
-                       yp1 = ch->GetPixelIndex(x,y+1);\r
-\r
-                       ix= (xp1-xm1)/2.0;\r
-                       iy= (yp1-ym1)/2.0;\r
-                       ixx= xp1 - 2.0 * xy0 + xm1;\r
-                       iyy= yp1 - 2.0 * xy0 + ym1;\r
-                       ixy=(ch->GetPixelIndex(x+1,y+1) + ch->GetPixelIndex(x-1,y-1) -\r
-                                ch->GetPixelIndex(x-1,y+1) - ch->GetPixelIndex(x+1,y-1))/4.0;\r
-\r
-                       correction = ((1.0+iy*iy)*ixx - ix*iy*ixy + (1.0+ix*ix)*iyy)/(1.0+ix*ix+iy*iy);\r
-\r
-                       tmp.BlindSetPixelIndex(x,y,(BYTE)min(255,max(0,(xy0 + radius * correction + 0.5))));\r
-               }\r
-       }\r
-       for (x=0;x<=w;x+=w){\r
-               for (y=0;y<=h;y++){\r
-                       xy0 = ch->BlindGetPixelIndex(x,y);\r
-                       xm1 = ch->GetPixelIndex(x-1,y);\r
-                       xp1 = ch->GetPixelIndex(x+1,y);\r
-                       ym1 = ch->GetPixelIndex(x,y-1);\r
-                       yp1 = ch->GetPixelIndex(x,y+1);\r
-\r
-                       ix= (xp1-xm1)/2.0;\r
-                       iy= (yp1-ym1)/2.0;\r
-                       ixx= xp1 - 2.0 * xy0 + xm1;\r
-                       iyy= yp1 - 2.0 * xy0 + ym1;\r
-                       ixy=(ch->GetPixelIndex(x+1,y+1) + ch->GetPixelIndex(x-1,y-1) -\r
-                                ch->GetPixelIndex(x-1,y+1) - ch->GetPixelIndex(x+1,y-1))/4.0;\r
-\r
-                       correction = ((1.0+iy*iy)*ixx - ix*iy*ixy + (1.0+ix*ix)*iyy)/(1.0+ix*ix+iy*iy);\r
-\r
-                       tmp.BlindSetPixelIndex(x,y,(BYTE)min(255,max(0,(xy0 + radius * correction + 0.5))));\r
-               }\r
-       }\r
-\r
-       ch->Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Enhance the variations between adjacent pixels.\r
- * Similar results can be achieved using Filter(),\r
- * but the algorithms are different both in Edge() and in Contour().\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Contour()\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long Ksize = 3;\r
-       long k2 = Ksize/2;\r
-       long kmax= Ksize-k2;\r
-       long i,j,k;\r
-       BYTE maxr,maxg,maxb;\r
-       RGBQUAD pix1,pix2;\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                               {\r
-                               pix1 = BlindGetPixelColor(x,y);\r
-                               maxr=maxg=maxb=0;\r
-                               for(j=-k2, i=0;j<kmax;j++){\r
-                                       for(k=-k2;k<kmax;k++, i++){\r
-                                               if (!IsInside(x+j,y+k)) continue;\r
-                                               pix2 = BlindGetPixelColor(x+j,y+k);\r
-                                               if ((pix2.rgbBlue-pix1.rgbBlue)>maxb) maxb = pix2.rgbBlue;\r
-                                               if ((pix2.rgbGreen-pix1.rgbGreen)>maxg) maxg = pix2.rgbGreen;\r
-                                               if ((pix2.rgbRed-pix1.rgbRed)>maxr) maxr = pix2.rgbRed;\r
-                                       }\r
-                               }\r
-                               pix1.rgbBlue=(BYTE)(255-maxb);\r
-                               pix1.rgbGreen=(BYTE)(255-maxg);\r
-                               pix1.rgbRed=(BYTE)(255-maxr);\r
-                               tmp.BlindSetPixelColor(x,y,pix1);\r
-                       }\r
-               }\r
-       }\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adds a random offset to each pixel in the image\r
- * \param radius: maximum pixel displacement\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Jitter(long radius)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long nx,ny;\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               nx=x+(long)((rand()/(float)RAND_MAX - 0.5)*(radius*2));\r
-                               ny=y+(long)((rand()/(float)RAND_MAX - 0.5)*(radius*2));\r
-                               if (!IsInside(nx,ny)) {\r
-                                       nx=x;\r
-                                       ny=y;\r
-                               }\r
-                               if (head.biClrUsed==0){\r
-                                       tmp.BlindSetPixelColor(x,y,BlindGetPixelColor(nx,ny));\r
-                               } else {\r
-                                       tmp.BlindSetPixelIndex(x,y,BlindGetPixelIndex(nx,ny));\r
-                               }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               tmp.AlphaSet(x,y,AlphaGet(nx,ny));\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       }\r
-               }\r
-       }\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/** \r
- * generates a 1-D convolution matrix to be used for each pass of \r
- * a two-pass gaussian blur.  Returns the length of the matrix.\r
- * \author [nipper]\r
- */\r
-int CxImage::gen_convolve_matrix (float radius, float **cmatrix_p)\r
-{\r
-       int matrix_length;\r
-       int matrix_midpoint;\r
-       float* cmatrix;\r
-       int i,j;\r
-       float std_dev;\r
-       float sum;\r
-       \r
-       /* we want to generate a matrix that goes out a certain radius\r
-       * from the center, so we have to go out ceil(rad-0.5) pixels,\r
-       * inlcuding the center pixel.  Of course, that's only in one direction,\r
-       * so we have to go the same amount in the other direction, but not count\r
-       * the center pixel again.  So we double the previous result and subtract\r
-       * one.\r
-       * The radius parameter that is passed to this function is used as\r
-       * the standard deviation, and the radius of effect is the\r
-       * standard deviation * 2.  It's a little confusing.\r
-       * <DP> modified scaling, so that matrix_lenght = 1+2*radius parameter\r
-       */\r
-       radius = (float)fabs(0.5*radius) + 0.25f;\r
-       \r
-       std_dev = radius;\r
-       radius = std_dev * 2;\r
-       \r
-       /* go out 'radius' in each direction */\r
-       matrix_length = int (2 * ceil(radius-0.5) + 1);\r
-       if (matrix_length <= 0) matrix_length = 1;\r
-       matrix_midpoint = matrix_length/2 + 1;\r
-       *cmatrix_p = new float[matrix_length];\r
-       cmatrix = *cmatrix_p;\r
-       \r
-       /*  Now we fill the matrix by doing a numeric integration approximation\r
-       * from -2*std_dev to 2*std_dev, sampling 50 points per pixel.\r
-       * We do the bottom half, mirror it to the top half, then compute the\r
-       * center point.  Otherwise asymmetric quantization errors will occur.\r
-       *  The formula to integrate is e^-(x^2/2s^2).\r
-       */\r
-       \r
-       /* first we do the top (right) half of matrix */\r
-       for (i = matrix_length/2 + 1; i < matrix_length; i++)\r
-    {\r
-               float base_x = i - (float)floor((float)(matrix_length/2)) - 0.5f;\r
-               sum = 0;\r
-               for (j = 1; j <= 50; j++)\r
-               {\r
-                       if ( base_x+0.02*j <= radius ) \r
-                               sum += (float)exp (-(base_x+0.02*j)*(base_x+0.02*j) / \r
-                               (2*std_dev*std_dev));\r
-               }\r
-               cmatrix[i] = sum/50;\r
-    }\r
-       \r
-       /* mirror the thing to the bottom half */\r
-       for (i=0; i<=matrix_length/2; i++) {\r
-               cmatrix[i] = cmatrix[matrix_length-1-i];\r
-       }\r
-       \r
-       /* find center val -- calculate an odd number of quanta to make it symmetric,\r
-       * even if the center point is weighted slightly higher than others. */\r
-       sum = 0;\r
-       for (j=0; j<=50; j++)\r
-    {\r
-               sum += (float)exp (-(0.5+0.02*j)*(0.5+0.02*j) /\r
-                       (2*std_dev*std_dev));\r
-    }\r
-       cmatrix[matrix_length/2] = sum/51;\r
-       \r
-       /* normalize the distribution by scaling the total sum to one */\r
-       sum=0;\r
-       for (i=0; i<matrix_length; i++) sum += cmatrix[i];\r
-       for (i=0; i<matrix_length; i++) cmatrix[i] = cmatrix[i] / sum;\r
-       \r
-       return matrix_length;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * generates a lookup table for every possible product of 0-255 and\r
- * each value in the convolution matrix.  The returned array is\r
- * indexed first by matrix position, then by input multiplicand (?)\r
- * value.\r
- * \author [nipper]\r
- */\r
-float* CxImage::gen_lookup_table (float *cmatrix, int cmatrix_length)\r
-{\r
-       float* lookup_table = new float[cmatrix_length * 256];\r
-       float* lookup_table_p = lookup_table;\r
-       float* cmatrix_p      = cmatrix;\r
-       \r
-       for (int i=0; i<cmatrix_length; i++)\r
-    {\r
-               for (int j=0; j<256; j++)\r
-               {\r
-                       *(lookup_table_p++) = *cmatrix_p * (float)j;\r
-               }\r
-               cmatrix_p++;\r
-    }\r
-       \r
-       return lookup_table;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * this function is written as if it is blurring a column at a time,\r
- * even though it can operate on rows, too.  There is no difference\r
- * in the processing of the lines, at least to the blur_line function.\r
- * \author [nipper]\r
- */\r
-void CxImage::blur_line (float *ctable, float *cmatrix, int cmatrix_length, BYTE* cur_col, BYTE* dest_col, int y, long bytes)\r
-{\r
-       float scale;\r
-       float sum;\r
-       int i=0, j=0;\r
-       int row;\r
-       int cmatrix_middle = cmatrix_length/2;\r
-       \r
-       float *cmatrix_p;\r
-       BYTE  *cur_col_p;\r
-       BYTE  *cur_col_p1;\r
-       BYTE  *dest_col_p;\r
-       float *ctable_p;\r
-       \r
-       /* this first block is the same as the non-optimized version --\r
-       * it is only used for very small pictures, so speed isn't a\r
-       * big concern.\r
-       */\r
-       if (cmatrix_length > y)\r
-    {\r
-               for (row = 0; row < y ; row++)\r
-               {\r
-                       scale=0;\r
-                       /* find the scale factor */\r
-                       for (j = 0; j < y ; j++)\r
-                       {\r
-                               /* if the index is in bounds, add it to the scale counter */\r
-                               if ((j + cmatrix_middle - row >= 0) &&\r
-                                       (j + cmatrix_middle - row < cmatrix_length))\r
-                                       scale += cmatrix[j + cmatrix_middle - row];\r
-                       }\r
-                       for (i = 0; i<bytes; i++)\r
-                       {\r
-                               sum = 0;\r
-                               for (j = 0; j < y; j++)\r
-                               {\r
-                                       if ((j >= row - cmatrix_middle) &&\r
-                                               (j <= row + cmatrix_middle))\r
-                                               sum += cur_col[j*bytes + i] * cmatrix[j];\r
-                               }\r
-                               dest_col[row*bytes + i] = (BYTE)(0.5f + sum / scale);\r
-                       }\r
-               }\r
-    }\r
-       else\r
-    {\r
-               /* for the edge condition, we only use available info and scale to one */\r
-               for (row = 0; row < cmatrix_middle; row++)\r
-               {\r
-                       /* find scale factor */\r
-                       scale=0;\r
-                       for (j = cmatrix_middle - row; j<cmatrix_length; j++)\r
-                               scale += cmatrix[j];\r
-                       for (i = 0; i<bytes; i++)\r
-                       {\r
-                               sum = 0;\r
-                               for (j = cmatrix_middle - row; j<cmatrix_length; j++)\r
-                               {\r
-                                       sum += cur_col[(row + j-cmatrix_middle)*bytes + i] * cmatrix[j];\r
-                               }\r
-                               dest_col[row*bytes + i] = (BYTE)(0.5f + sum / scale);\r
-                       }\r
-               }\r
-               /* go through each pixel in each col */\r
-               dest_col_p = dest_col + row*bytes;\r
-               for (; row < y-cmatrix_middle; row++)\r
-               {\r
-                       cur_col_p = (row - cmatrix_middle) * bytes + cur_col;\r
-                       for (i = 0; i<bytes; i++)\r
-                       {\r
-                               sum = 0;\r
-                               cmatrix_p = cmatrix;\r
-                               cur_col_p1 = cur_col_p;\r
-                               ctable_p = ctable;\r
-                               for (j = cmatrix_length; j>0; j--)\r
-                               {\r
-                                       sum += *(ctable_p + *cur_col_p1);\r
-                                       cur_col_p1 += bytes;\r
-                                       ctable_p += 256;\r
-                               }\r
-                               cur_col_p++;\r
-                               *(dest_col_p++) = (BYTE)(0.5f + sum);\r
-                       }\r
-               }\r
-               \r
-               /* for the edge condition , we only use available info, and scale to one */\r
-               for (; row < y; row++)\r
-               {\r
-                       /* find scale factor */\r
-                       scale=0;\r
-                       for (j = 0; j< y-row + cmatrix_middle; j++)\r
-                               scale += cmatrix[j];\r
-                       for (i = 0; i<bytes; i++)\r
-                       {\r
-                               sum = 0;\r
-                               for (j = 0; j<y-row + cmatrix_middle; j++)\r
-                               {\r
-                                       sum += cur_col[(row + j-cmatrix_middle)*bytes + i] * cmatrix[j];\r
-                               }\r
-                               dest_col[row*bytes + i] = (BYTE) (0.5f + sum / scale);\r
-                       }\r
-               }\r
-    }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \author [DP]\r
- */\r
-void CxImage::blur_text (BYTE threshold, BYTE decay, BYTE max_depth, CxImage* iSrc, CxImage* iDst, BYTE bytes)\r
-{\r
-       long x,y,z,m;\r
-       BYTE *pSrc, *pSrc2, *pSrc3, *pDst;\r
-       BYTE step,n;\r
-       int pivot;\r
-\r
-       if (max_depth<1) max_depth = 1;\r
-\r
-       long nmin,nmax,xmin,xmax,ymin,ymax;\r
-       xmin = ymin = 0;\r
-       xmax = iSrc->head.biWidth;\r
-       ymax = iSrc->head.biHeight;\r
-\r
-       if (xmin==xmax || ymin==ymax) return;\r
-\r
-       nmin = xmin * bytes;\r
-       nmax = xmax * bytes;\r
-\r
-       CImageIterator itSrc(iSrc);\r
-       CImageIterator itTmp(iDst);\r
-\r
-       double dbScaler = 100.0f/(ymax-ymin)/bytes;\r
-\r
-       for (n=0; n<bytes; n++){\r
-               for (y=ymin+1;y<(ymax-1);y++)\r
-               {\r
-                       if (info.nEscape) break;\r
-                       info.nProgress = (long)((y-ymin)*dbScaler*(1+n));\r
-\r
-                       pSrc  = itSrc.GetRow(y);\r
-                       pSrc2 = itSrc.GetRow(y+1);\r
-                       pSrc3 = itSrc.GetRow(y-1);\r
-                       pDst  = itTmp.GetRow(y);\r
-\r
-                       //scan left to right\r
-                       for (x=n+nmin /*,i=xmin*/; x<(nmax-1); x+=bytes /*,i++*/)\r
-                       {\r
-                               z=x+bytes;\r
-                               pivot = pSrc[z]-threshold;\r
-                               //find upper corner\r
-                               if (pSrc[x]<pivot && pSrc2[z]<pivot && pSrc3[x]>=pivot){\r
-                                       while (z<nmax && pSrc2[z]<pSrc[x+bytes] && pSrc[x+bytes]<=pSrc[z]){\r
-                                               z+=bytes;\r
-                                       }\r
-                                       m = z-x;\r
-                                       m = (decay>1) ? ((m/bytes)/decay+1) : m/bytes;\r
-                                       if (m>max_depth) m = max_depth;\r
-                                       step = (BYTE)((pSrc[x+bytes]-pSrc[x])/(m+1));\r
-                                       while (m-->1){\r
-                                               pDst[x+m*bytes] = (BYTE)(pDst[x]+(step*(m+1)));\r
-                                       }\r
-                               }\r
-                               //find lower corner\r
-                               z=x+bytes;\r
-                               if (pSrc[x]<pivot && pSrc3[z]<pivot && pSrc2[x]>=pivot){\r
-                                       while (z<nmax && pSrc3[z]<pSrc[x+bytes] && pSrc[x+bytes]<=pSrc[z]){\r
-                                               z+=bytes;\r
-                                       }\r
-                                       m = z-x;\r
-                                       m = (decay>1) ? ((m/bytes)/decay+1) : m/bytes;\r
-                                       if (m>max_depth) m = max_depth;\r
-                                       step = (BYTE)((pSrc[x+bytes]-pSrc[x])/(m+1));\r
-                                       while (m-->1){\r
-                                               pDst[x+m*bytes] = (BYTE)(pDst[x]+(step*(m+1)));\r
-                                       }\r
-                               }\r
-                       }\r
-                       //scan right to left\r
-                       for (x=nmax-1-n /*,i=(xmax-1)*/; x>0; x-=bytes /*,i--*/)\r
-                       {\r
-                               z=x-bytes;\r
-                               pivot = pSrc[z]-threshold;\r
-                               //find upper corner\r
-                               if (pSrc[x]<pivot && pSrc2[z]<pivot && pSrc3[x]>=pivot){\r
-                                       while (z>n && pSrc2[z]<pSrc[x-bytes] && pSrc[x-bytes]<=pSrc[z]){\r
-                                               z-=bytes;\r
-                                       }\r
-                                       m = x-z;\r
-                                       m = (decay>1) ? ((m/bytes)/decay+1) : m/bytes;\r
-                                       if (m>max_depth) m = max_depth;\r
-                                       step = (BYTE)((pSrc[x-bytes]-pSrc[x])/(m+1));\r
-                                       while (m-->1){\r
-                                               pDst[x-m*bytes] = (BYTE)(pDst[x]+(step*(m+1)));\r
-                                       }\r
-                               }\r
-                               //find lower corner\r
-                               z=x-bytes;\r
-                               if (pSrc[x]<pivot && pSrc3[z]<pivot && pSrc2[x]>=pivot){\r
-                                       while (z>n && pSrc3[z]<pSrc[x-bytes] && pSrc[x-bytes]<=pSrc[z]){\r
-                                               z-=bytes;\r
-                                       }\r
-                                       m = x-z;\r
-                                       m = (decay>1) ? ((m/bytes)/decay+1) : m/bytes;\r
-                                       if (m>max_depth) m = max_depth;\r
-                                       step = (BYTE)((pSrc[x-bytes]-pSrc[x])/(m+1));\r
-                                       while (m-->1){\r
-                                               pDst[x-m*bytes] = (BYTE)(pDst[x]+(step*(m+1)));\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \author [DP]\r
- */\r
-bool CxImage::TextBlur(BYTE threshold, BYTE decay, BYTE max_depth, bool bBlurHorizontal, bool bBlurVertical, CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       RGBQUAD* pPalette=NULL;\r
-       WORD bpp = GetBpp();\r
-\r
-       //the routine is optimized for RGB or GrayScale images\r
-       if (!(head.biBitCount == 24 || IsGrayScale())){\r
-               pPalette = new RGBQUAD[head.biClrUsed];\r
-               memcpy(pPalette, GetPalette(),GetPaletteSize());\r
-               if (!IncreaseBpp(24))\r
-                       return false;\r
-       }\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       if (bBlurHorizontal)\r
-               blur_text(threshold, decay, max_depth, this, &tmp, head.biBitCount>>3);\r
-\r
-       if (bBlurVertical){\r
-               CxImage src2(*this);\r
-               src2.RotateLeft();\r
-               tmp.RotateLeft();\r
-               blur_text(threshold, decay, max_depth, &src2, &tmp, head.biBitCount>>3);\r
-               tmp.RotateRight();\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       //restore the non selected region\r
-       if (pSelection){\r
-               for(long y=0; y<head.biHeight; y++){\r
-                       for(long x=0; x<head.biWidth; x++){\r
-                               if (!BlindSelectionIsInside(x,y)){\r
-                                       tmp.BlindSetPixelColor(x,y,BlindGetPixelColor(x,y));\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-       //if necessary, restore the original BPP and palette\r
-       if (pPalette){\r
-               tmp.DecreaseBpp(bpp, true, pPalette);\r
-               delete [] pPalette;\r
-       }\r
-\r
-       if (iDst) iDst->Transfer(tmp);\r
-       else Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \author [nipper]; changes [DP]\r
- */\r
-bool CxImage::GaussianBlur(float radius /*= 1.0f*/, CxImage* iDst /*= 0*/)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       RGBQUAD* pPalette=NULL;\r
-       WORD bpp = GetBpp();\r
-\r
-       //the routine is optimized for RGB or GrayScale images\r
-       if (!(head.biBitCount == 24 || IsGrayScale())){\r
-               pPalette = new RGBQUAD[head.biClrUsed];\r
-               memcpy(pPalette, GetPalette(),GetPaletteSize());\r
-               if (!IncreaseBpp(24))\r
-                       return false;\r
-       }\r
-\r
-       CxImage tmp_x(*this, false, true, true);\r
-       if (!tmp_x.IsValid()){\r
-               strcpy(info.szLastError,tmp_x.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       // generate convolution matrix and make sure it's smaller than each dimension\r
-       float *cmatrix = NULL;\r
-       int cmatrix_length = gen_convolve_matrix(radius, &cmatrix);\r
-       // generate lookup table\r
-       float *ctable = gen_lookup_table(cmatrix, cmatrix_length);\r
-\r
-       long x,y;\r
-       int bypp = head.biBitCount>>3;\r
-\r
-       CImageIterator itSrc(this);\r
-       CImageIterator itTmp(&tmp_x);\r
-\r
-       double dbScaler = 50.0f/head.biHeight;\r
-\r
-       // blur the rows\r
-    for (y=0;y<head.biHeight;y++)\r
-       {\r
-               if (info.nEscape) break;\r
-               info.nProgress = (long)(y*dbScaler);\r
-\r
-               blur_line(ctable, cmatrix, cmatrix_length, itSrc.GetRow(y), itTmp.GetRow(y), head.biWidth, bypp);\r
-       }\r
-\r
-       CxImage tmp_y(tmp_x, false, true, true);\r
-       if (!tmp_y.IsValid()){\r
-               strcpy(info.szLastError,tmp_y.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       CImageIterator itDst(&tmp_y);\r
-\r
-       // blur the cols\r
-    BYTE* cur_col = (BYTE*)malloc(bypp*head.biHeight);\r
-    BYTE* dest_col = (BYTE*)malloc(bypp*head.biHeight);\r
-\r
-       dbScaler = 50.0f/head.biWidth;\r
-\r
-       for (x=0;x<head.biWidth;x++)\r
-       {\r
-               if (info.nEscape) break;\r
-               info.nProgress = (long)(50.0f+x*dbScaler);\r
-\r
-               itTmp.GetCol(cur_col, x);\r
-               itDst.GetCol(dest_col, x);\r
-               blur_line(ctable, cmatrix, cmatrix_length, cur_col, dest_col, head.biHeight, bypp);\r
-               itDst.SetCol(dest_col, x);\r
-       }\r
-\r
-       free(cur_col);\r
-       free(dest_col);\r
-\r
-       delete [] cmatrix;\r
-       delete [] ctable;\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       //restore the non selected region\r
-       if (pSelection){\r
-               for(y=0; y<head.biHeight; y++){\r
-                       for(x=0; x<head.biWidth; x++){\r
-                               if (!BlindSelectionIsInside(x,y)){\r
-                                       tmp_y.BlindSetPixelColor(x,y,BlindGetPixelColor(x,y));\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-       //if necessary, restore the original BPP and palette\r
-       if (pPalette){\r
-               tmp_y.DecreaseBpp(bpp, false, pPalette);\r
-               if (iDst) DecreaseBpp(bpp, false, pPalette);\r
-               delete [] pPalette;\r
-       }\r
-\r
-       if (iDst) iDst->Transfer(tmp_y);\r
-       else Transfer(tmp_y);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \author [DP],[nipper]\r
- */\r
-bool CxImage::SelectiveBlur(float radius, BYTE threshold, CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       RGBQUAD* pPalette=NULL;\r
-       WORD bpp = GetBpp();\r
-\r
-       CxImage Tmp(*this, true, true, true);\r
-       if (!Tmp.IsValid()){\r
-               strcpy(info.szLastError,Tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       //the routine is optimized for RGB or GrayScale images\r
-       if (!(head.biBitCount == 24 || IsGrayScale())){\r
-               pPalette = new RGBQUAD[head.biClrUsed];\r
-               memcpy(pPalette, GetPalette(),GetPaletteSize());\r
-               if (!Tmp.IncreaseBpp(24))\r
-                       return false;\r
-       }\r
-\r
-       CxImage Dst(Tmp, true, true, true);\r
-       if (!Dst.IsValid()){\r
-               strcpy(info.szLastError,Dst.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       //build the difference mask\r
-       BYTE thresh_dw = (BYTE)max( 0 ,(int)(128 - threshold));\r
-       BYTE thresh_up = (BYTE)min(255,(int)(128 + threshold));\r
-       long kernel[]={-100,-100,-100,-100,801,-100,-100,-100,-100};\r
-       if (!Tmp.Filter(kernel,3,800,128)){\r
-               strcpy(info.szLastError,Tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       //if the image has no selection, build a selection for the whole image\r
-       if (!Tmp.SelectionIsValid()){\r
-               Tmp.SelectionCreate();\r
-               Tmp.SelectionClear(255);\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       xmin = Tmp.info.rSelectionBox.left;\r
-       xmax = Tmp.info.rSelectionBox.right;\r
-       ymin = Tmp.info.rSelectionBox.bottom;\r
-       ymax = Tmp.info.rSelectionBox.top;\r
-\r
-       //modify the selection where the difference mask is over the threshold\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-                       if(Tmp.BlindSelectionIsInside(x,y)){\r
-                               RGBQUAD c = Tmp.BlindGetPixelColor(x,y);\r
-                               if ((c.rgbRed   < thresh_dw || c.rgbRed   > thresh_up) ||\r
-                                       (c.rgbGreen < thresh_dw || c.rgbGreen > thresh_up) ||\r
-                                       (c.rgbBlue  < thresh_dw || c.rgbBlue  > thresh_up))\r
-                               {\r
-                                       Tmp.SelectionSet(x,y,0);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       //blur the image (only in the selected pixels)\r
-       Dst.SelectionCopy(Tmp);\r
-       if (!Dst.GaussianBlur(radius)){\r
-               strcpy(info.szLastError,Dst.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       //restore the original selection\r
-       Dst.SelectionCopy(*this);\r
-\r
-       //if necessary, restore the original BPP and palette\r
-       if (pPalette){\r
-               Dst.DecreaseBpp(bpp, false, pPalette);\r
-               delete [] pPalette;\r
-       }\r
-\r
-       if (iDst) iDst->Transfer(Dst);\r
-       else Transfer(Dst);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * sharpen the image by subtracting a blurred copy from the original image.\r
- * \param radius: width in pixels of the blurring effect. Range: >0; default = 5.\r
- * \param amount: strength of the filter. Range: 0.0 (none) to 1.0 (max); default = 0.5\r
- * \param threshold: difference, between blurred and original pixel, to trigger the filter\r
- *                   Range: 0 (always triggered) to 255 (never triggered); default = 0.\r
- * \return true if everything is ok\r
- * \author [nipper]; changes [DP]\r
- */\r
-bool CxImage::UnsharpMask(float radius /*= 5.0*/, float amount /*= 0.5*/, int threshold /*= 0*/)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       RGBQUAD* pPalette=NULL;\r
-       WORD bpp = GetBpp();\r
-\r
-       //the routine is optimized for RGB or GrayScale images\r
-       if (!(head.biBitCount == 24 || IsGrayScale())){\r
-               pPalette = new RGBQUAD[head.biClrUsed];\r
-               memcpy(pPalette, GetPalette(),GetPaletteSize());\r
-               if (!IncreaseBpp(24))\r
-                       return false;\r
-       }\r
-\r
-       CxImage iDst;\r
-       if (!GaussianBlur(radius,&iDst))\r
-               return false;\r
-\r
-       CImageIterator itSrc(this);\r
-       CImageIterator itDst(&iDst);\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       if (xmin==xmax || ymin==ymax)\r
-               return false;\r
-\r
-       double dbScaler = 100.0/(ymax-ymin);\r
-       int bypp = head.biBitCount>>3;\r
-       \r
-       // merge the source and destination (which currently contains\r
-       // the blurred version) images\r
-    for (long y=ymin; y<ymax; y++)\r
-       {\r
-               if (info.nEscape) break;\r
-               info.nProgress = (long)((y-ymin)*dbScaler);\r
-\r
-               // get source row\r
-               BYTE* cur_row = itSrc.GetRow(y);\r
-               // get dest row\r
-               BYTE* dest_row = itDst.GetRow(y);\r
-               // combine the two\r
-               for (long x=xmin; x<xmax; x++) {\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               for (long b=0, z=x*bypp; b<bypp; b++, z++){\r
-                                       int diff = cur_row[z] - dest_row[z];\r
-\r
-                                       // do tresholding\r
-                                       if (abs(diff) < threshold){\r
-                                               dest_row[z] = cur_row[z];\r
-                                       } else {\r
-                                               dest_row[z] = (BYTE)min(255, max(0,(int)(cur_row[z] + amount * diff)));\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       //if necessary, restore the original BPP and palette\r
-       if (pPalette){\r
-               iDst.DecreaseBpp(bpp, false, pPalette);\r
-               delete [] pPalette;\r
-       }\r
-\r
-       Transfer(iDst);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Apply a look up table to the image. \r
- * \param pLut: BYTE[256] look up table\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Lut(BYTE* pLut)\r
-{\r
-       if (!pDib || !pLut) return false;\r
-       RGBQUAD color;\r
-\r
-       double dbScaler;\r
-       if (head.biClrUsed==0){\r
-\r
-               long xmin,xmax,ymin,ymax;\r
-               if (pSelection){\r
-                       xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-                       ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-               } else {\r
-                       // faster loop for full image\r
-                       BYTE *iSrc=info.pImage;\r
-                       for(unsigned long i=0; i < head.biSizeImage ; i++){\r
-                               *iSrc++ = pLut[*iSrc];\r
-                       }\r
-                       return true;\r
-               }\r
-\r
-               if (xmin==xmax || ymin==ymax)\r
-                       return false;\r
-\r
-               dbScaler = 100.0/(ymax-ymin);\r
-\r
-               for(long y=ymin; y<ymax; y++){\r
-                       info.nProgress = (long)((y-ymin)*dbScaler); //<Anatoly Ivasyuk>\r
-                       for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                               if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                               {\r
-                                       color = BlindGetPixelColor(x,y);\r
-                                       color.rgbRed = pLut[color.rgbRed];\r
-                                       color.rgbGreen = pLut[color.rgbGreen];\r
-                                       color.rgbBlue = pLut[color.rgbBlue];\r
-                                       BlindSetPixelColor(x,y,color);\r
-                               }\r
-                       }\r
-               }\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       } else if (pSelection && (head.biBitCount==8) && IsGrayScale()){\r
-               long xmin,xmax,ymin,ymax;\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-\r
-               if (xmin==xmax || ymin==ymax)\r
-                       return false;\r
-\r
-               dbScaler = 100.0/(ymax-ymin);\r
-               for(long y=ymin; y<ymax; y++){\r
-                       info.nProgress = (long)((y-ymin)*dbScaler);\r
-                       for(long x=xmin; x<xmax; x++){\r
-                               if (BlindSelectionIsInside(x,y))\r
-                               {\r
-                                       BlindSetPixelIndex(x,y,pLut[BlindGetPixelIndex(x,y)]);\r
-                               }\r
-                       }\r
-               }\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-       } else {\r
-               bool bIsGrayScale = IsGrayScale();\r
-               for(DWORD j=0; j<head.biClrUsed; j++){\r
-                       color = GetPaletteColor((BYTE)j);\r
-                       color.rgbRed = pLut[color.rgbRed];\r
-                       color.rgbGreen = pLut[color.rgbGreen];\r
-                       color.rgbBlue = pLut[color.rgbBlue];\r
-                       SetPaletteColor((BYTE)j,color);\r
-               }\r
-               if (bIsGrayScale) GrayScale();\r
-       }\r
-       return true;\r
-\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Apply an indipendent look up table for each channel\r
- * \param pLutR, pLutG, pLutB, pLutA: BYTE[256] look up tables\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Lut(BYTE* pLutR, BYTE* pLutG, BYTE* pLutB, BYTE* pLutA)\r
-{\r
-       if (!pDib || !pLutR || !pLutG || !pLutB) return false;\r
-       RGBQUAD color;\r
-\r
-       double dbScaler;\r
-       if (head.biClrUsed==0){\r
-\r
-               long xmin,xmax,ymin,ymax;\r
-               if (pSelection){\r
-                       xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-                       ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-               } else {\r
-                       xmin = ymin = 0;\r
-                       xmax = head.biWidth; ymax=head.biHeight;\r
-               }\r
-\r
-               if (xmin==xmax || ymin==ymax)\r
-                       return false;\r
-\r
-               dbScaler = 100.0/(ymax-ymin);\r
-\r
-               for(long y=ymin; y<ymax; y++){\r
-                       info.nProgress = (long)((y-ymin)*dbScaler);\r
-                       for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                               if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                               {\r
-                                       color = BlindGetPixelColor(x,y);\r
-                                       color.rgbRed =   pLutR[color.rgbRed];\r
-                                       color.rgbGreen = pLutG[color.rgbGreen];\r
-                                       color.rgbBlue =  pLutB[color.rgbBlue];\r
-                                       if (pLutA) color.rgbReserved=pLutA[color.rgbReserved];\r
-                                       BlindSetPixelColor(x,y,color,true);\r
-                               }\r
-                       }\r
-               }\r
-       } else {\r
-               bool bIsGrayScale = IsGrayScale();\r
-               for(DWORD j=0; j<head.biClrUsed; j++){\r
-                       color = GetPaletteColor((BYTE)j);\r
-                       color.rgbRed =   pLutR[color.rgbRed];\r
-                       color.rgbGreen = pLutG[color.rgbGreen];\r
-                       color.rgbBlue =  pLutB[color.rgbBlue];\r
-                       SetPaletteColor((BYTE)j,color);\r
-               }\r
-               if (bIsGrayScale) GrayScale();\r
-       }\r
-\r
-       return true;\r
-\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Use the RedEyeRemove function to remove the red-eye effect that frequently\r
- * occurs in photographs of humans and animals. You must select the region \r
- * where the function will filter the red channel.\r
- * \param strength: range from 0.0f (no effect) to 1.0f (full effect). Default = 0.8\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::RedEyeRemove(float strength)\r
-{\r
-       if (!pDib) return false;\r
-       RGBQUAD color;\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       if (xmin==xmax || ymin==ymax)\r
-               return false;\r
-\r
-       if (strength<0.0f) strength = 0.0f;\r
-       if (strength>1.0f) strength = 1.0f;\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               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)));\r
-                               if (a<0) a=0;\r
-                               color = BlindGetPixelColor(x,y);\r
-                               color.rgbRed = (BYTE)(a*min(color.rgbGreen,color.rgbBlue)+(1.0f-a)*color.rgbRed);\r
-                               BlindSetPixelColor(x,y,color);\r
-                       }\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Changes the saturation of the image. \r
- * \param saturation: can be from -100 to 100, positive values increase the saturation.\r
- * \param colorspace: can be 1 (HSL) or 2 (YUV).\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Saturate(const long saturation, const long colorspace)\r
-{\r
-       if (!pDib)\r
-               return false;\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       if (xmin==xmax || ymin==ymax)\r
-               return false;\r
-\r
-       BYTE cTable[256];\r
-\r
-       switch(colorspace)\r
-       {\r
-       case 1:\r
-               {\r
-                       for (int i=0;i<256;i++) {\r
-                               cTable[i] = (BYTE)max(0,min(255,(int)(i + saturation)));\r
-                       }\r
-                       for(long y=ymin; y<ymax; y++){\r
-                               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-                               if (info.nEscape) break;\r
-                               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                                       {\r
-                                               RGBQUAD c = RGBtoHSL(BlindGetPixelColor(x,y));\r
-                                               c.rgbGreen  = cTable[c.rgbGreen];\r
-                                               c = HSLtoRGB(c);\r
-                                               BlindSetPixelColor(x,y,c);\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               break;\r
-       case 2:\r
-               {\r
-                       for (int i=0;i<256;i++) {\r
-                               cTable[i] = (BYTE)max(0,min(255,(int)((i-128)*(100 + saturation)/100.0f + 128.5f)));\r
-                       }\r
-                       for(long y=ymin; y<ymax; y++){\r
-                               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-                               if (info.nEscape) break;\r
-                               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                                       {\r
-                                               RGBQUAD c = RGBtoYUV(BlindGetPixelColor(x,y));\r
-                                               c.rgbGreen  = cTable[c.rgbGreen];\r
-                                               c.rgbBlue = cTable[c.rgbBlue];\r
-                                               c = YUVtoRGB(c);\r
-                                               BlindSetPixelColor(x,y,c);\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               break;\r
-       default:\r
-               strcpy(info.szLastError,"Saturate: wrong colorspace");\r
-               return false;\r
-       }\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Solarize: convert all colors above a given lightness level into their negative\r
- * \param  level : lightness threshold. Range = 0 to 255; default = 128.\r
- * \param  bLinkedChannels: true = compare with luminance, preserve colors (default)\r
- *                         false = compare with independent R,G,B levels\r
- * \return true if everything is ok\r
- * \author [Priyank Bolia] (priyank_bolia(at)yahoo(dot)com); changes [DP]\r
- */\r
-bool CxImage::Solarize(BYTE level, bool bLinkedChannels)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       if (head.biBitCount<=8){\r
-               if (IsGrayScale()){ //GRAYSCALE, selection\r
-                       for(long y=ymin; y<ymax; y++){\r
-                               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                                       {\r
-                                               BYTE index = BlindGetPixelIndex(x,y);\r
-                                               RGBQUAD color = GetPaletteColor(index);\r
-                                               if ((BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)>level){\r
-                                                       BlindSetPixelIndex(x,y,255-index);\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               } else { //PALETTE, full image\r
-                       RGBQUAD* ppal=GetPalette();\r
-                       for(DWORD i=0;i<head.biClrUsed;i++){\r
-                               RGBQUAD color = GetPaletteColor((BYTE)i);\r
-                               if (bLinkedChannels){\r
-                                       if ((BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)>level){\r
-                                               ppal[i].rgbBlue =(BYTE)(255-ppal[i].rgbBlue);\r
-                                               ppal[i].rgbGreen =(BYTE)(255-ppal[i].rgbGreen);\r
-                                               ppal[i].rgbRed =(BYTE)(255-ppal[i].rgbRed);\r
-                                       }\r
-                               } else {\r
-                                       if (color.rgbBlue>level)        ppal[i].rgbBlue =(BYTE)(255-ppal[i].rgbBlue);\r
-                                       if (color.rgbGreen>level)       ppal[i].rgbGreen =(BYTE)(255-ppal[i].rgbGreen);\r
-                                       if (color.rgbRed>level)         ppal[i].rgbRed =(BYTE)(255-ppal[i].rgbRed);\r
-                               }\r
-                       }\r
-               }\r
-       } else { //RGB, selection\r
-               for(long y=ymin; y<ymax; y++){\r
-                       for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                               if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                               {\r
-                                       RGBQUAD color = BlindGetPixelColor(x,y);\r
-                                       if (bLinkedChannels){\r
-                                               if ((BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)>level){\r
-                                                       color.rgbRed = (BYTE)(255-color.rgbRed);\r
-                                                       color.rgbGreen = (BYTE)(255-color.rgbGreen);\r
-                                                       color.rgbBlue = (BYTE)(255-color.rgbBlue);\r
-                                               }\r
-                                       } else {\r
-                                               if (color.rgbBlue>level)        color.rgbBlue =(BYTE)(255-color.rgbBlue);\r
-                                               if (color.rgbGreen>level)       color.rgbGreen =(BYTE)(255-color.rgbGreen);\r
-                                               if (color.rgbRed>level)         color.rgbRed =(BYTE)(255-color.rgbRed);\r
-                                       }\r
-                                       BlindSetPixelColor(x,y,color);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       //invert transparent color only in case of full image processing\r
-       if (pSelection==0 || (!IsGrayScale() && IsIndexed())){\r
-               if (bLinkedChannels){\r
-                       if ((BYTE)RGB2GRAY(info.nBkgndColor.rgbRed,info.nBkgndColor.rgbGreen,info.nBkgndColor.rgbBlue)>level){\r
-                               info.nBkgndColor.rgbBlue = (BYTE)(255-info.nBkgndColor.rgbBlue);\r
-                               info.nBkgndColor.rgbGreen = (BYTE)(255-info.nBkgndColor.rgbGreen);\r
-                               info.nBkgndColor.rgbRed = (BYTE)(255-info.nBkgndColor.rgbRed);\r
-                       } \r
-               } else {\r
-                       if (info.nBkgndColor.rgbBlue>level)      info.nBkgndColor.rgbBlue = (BYTE)(255-info.nBkgndColor.rgbBlue);\r
-                       if (info.nBkgndColor.rgbGreen>level) info.nBkgndColor.rgbGreen = (BYTE)(255-info.nBkgndColor.rgbGreen);\r
-                       if (info.nBkgndColor.rgbRed>level)       info.nBkgndColor.rgbRed = (BYTE)(255-info.nBkgndColor.rgbRed);\r
-               }\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Converts the RGB triplets to and from different colorspace\r
- * \param dstColorSpace: destination colorspace; 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ \r
- * \param srcColorSpace: source colorspace; 0 = RGB, 1 = HSL, 2 = YUV, 3 = YIQ, 4 = XYZ \r
- * \return true if everything is ok\r
- */\r
-bool CxImage::ConvertColorSpace(const long dstColorSpace, const long srcColorSpace)\r
-{\r
-       if (!pDib)\r
-               return false;\r
-\r
-       if (dstColorSpace == srcColorSpace)\r
-               return true;\r
-\r
-       long w = GetWidth();\r
-       long h = GetHeight();\r
-\r
-       for (long y=0;y<h;y++){\r
-               info.nProgress = (long)(100*y/h);\r
-               if (info.nEscape) break;\r
-               for (long x=0;x<w;x++){\r
-                       RGBQUAD c = BlindGetPixelColor(x,y);\r
-                       switch (srcColorSpace){\r
-                       case 0:\r
-                               break;\r
-                       case 1:\r
-                               c = HSLtoRGB(c);\r
-                               break;\r
-                       case 2:\r
-                               c = YUVtoRGB(c);\r
-                               break;\r
-                       case 3:\r
-                               c = YIQtoRGB(c);\r
-                               break;\r
-                       case 4:\r
-                               c = XYZtoRGB(c);\r
-                               break;\r
-                       default:\r
-                               strcpy(info.szLastError,"ConvertColorSpace: unknown source colorspace");\r
-                               return false;\r
-                       }\r
-                       switch (dstColorSpace){\r
-                       case 0:\r
-                               break;\r
-                       case 1:\r
-                               c = RGBtoHSL(c);\r
-                               break;\r
-                       case 2:\r
-                               c = RGBtoYUV(c);\r
-                               break;\r
-                       case 3:\r
-                               c = RGBtoYIQ(c);\r
-                               break;\r
-                       case 4:\r
-                               c = RGBtoXYZ(c);\r
-                               break;\r
-                       default:\r
-                               strcpy(info.szLastError,"ConvertColorSpace: unknown destination colorspace");\r
-                               return false;\r
-                       }\r
-                       BlindSetPixelColor(x,y,c);\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Finds the optimal (global or local) treshold for image binarization\r
- * \param method: 0 = average all methods (default); 1 = Otsu; 2 = Kittler & Illingworth; 3 = max entropy; 4 = potential difference;\r
- * \param pBox: region from where the threshold is computed; 0 = full image (default).\r
- * \param pContrastMask: limit the computation only in regions with contrasted (!=0) pixels; default = 0.\r
- * the pContrastMask image must be grayscale with same with and height of the current image,\r
- * can be obtained from the current image with a filter:\r
- *   CxImage iContrastMask(*image,true,false,false);\r
- *   iContrastMask.GrayScale();\r
- *   long edge[]={-1,-1,-1,-1,8,-1,-1,-1,-1};\r
- *   iContrastMask.Filter(edge,3,1,0);\r
- *   long blur[]={1,1,1,1,1,1,1,1,1};\r
- *   iContrastMask.Filter(blur,3,9,0);\r
- * \return optimal threshold; -1 = error.\r
- * \sa AdaptiveThreshold\r
- */\r
-int  CxImage::OptimalThreshold(long method, RECT * pBox, CxImage* pContrastMask)\r
-{\r
-       if (!pDib)\r
-               return false;\r
-\r
-       if (head.biBitCount!=8){\r
-               strcpy(info.szLastError,"OptimalThreshold works only on 8 bit images");\r
-               return -1;\r
-       }\r
-\r
-       if (pContrastMask){\r
-               if (!pContrastMask->IsValid() ||\r
-                       !pContrastMask->IsGrayScale() ||\r
-                       pContrastMask->GetWidth() != GetWidth() ||\r
-                       pContrastMask->GetHeight() != GetHeight()){\r
-                       strcpy(info.szLastError,"OptimalThreshold invalid ContrastMask");\r
-                       return -1;\r
-               }\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pBox){\r
-               xmin = max(pBox->left,0);\r
-               xmax = min(pBox->right,head.biWidth);\r
-               ymin = max(pBox->bottom,0);\r
-               ymax = min(pBox->top,head.biHeight);\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-       \r
-       if (xmin>=xmax || ymin>=ymax)\r
-               return -1;\r
-\r
-       double p[256];\r
-       memset(p,  0, 256*sizeof(double));\r
-       //build histogram\r
-       for (long y = ymin; y<ymax; y++){\r
-               BYTE* pGray = GetBits(y) + xmin;\r
-               BYTE* pContr = 0;\r
-               if (pContrastMask) pContr = pContrastMask->GetBits(y) + xmin;\r
-               for (long x = xmin; x<xmax; x++){\r
-                       BYTE n = *pGray++;\r
-                       if (pContr){\r
-                               if (*pContr) p[n]++;\r
-                               pContr++;\r
-                       } else {\r
-                               p[n]++;\r
-                       }\r
-               }\r
-       }\r
-\r
-       //find histogram limits\r
-       int gray_min = 0;\r
-       while (gray_min<255 && p[gray_min]==0) gray_min++;\r
-       int gray_max = 255;\r
-       while (gray_max>0 && p[gray_max]==0) gray_max--;\r
-       if (gray_min > gray_max)\r
-               return -1;\r
-       if (gray_min == gray_max){\r
-               if (gray_min == 0)\r
-                       return 0;\r
-               else\r
-                       return gray_max-1;\r
-       }\r
-\r
-       //compute total moments 0th,1st,2nd order\r
-       int i,k;\r
-       double w_tot = 0;\r
-       double m_tot = 0;\r
-       double q_tot = 0;\r
-       for (i = gray_min; i <= gray_max; i++){\r
-               w_tot += p[i];\r
-               m_tot += i*p[i];\r
-               q_tot += i*i*p[i];\r
-       }\r
-\r
-       double L, L1max, L2max, L3max, L4max; //objective functions\r
-       int th1,th2,th3,th4; //optimal thresholds\r
-       L1max = L2max = L3max = L4max = 0;\r
-       th1 = th2 = th3 = th4 = -1;\r
-\r
-       double w1, w2, m1, m2, q1, q2, s1, s2;\r
-       w1 = m1 = q1 = 0;\r
-       for (i = gray_min; i < gray_max; i++){\r
-               w1 += p[i];\r
-               w2 = w_tot - w1;\r
-               m1 += i*p[i];\r
-               m2 = m_tot - m1;\r
-               q1 += i*i*p[i];\r
-               q2 = q_tot - q1;\r
-               s1 = q1/w1-m1*m1/w1/w1; //s1 = q1/w1-pow(m1/w1,2);\r
-               s2 = q2/w2-m2*m2/w2/w2; //s2 = q2/w2-pow(m2/w2,2);\r
-\r
-               //Otsu\r
-               L = -(s1*w1 + s2*w2); //implemented as definition\r
-               //L = w1 * w2 * (m2/w2 - m1/w1)*(m2/w2 - m1/w1); //implementation that doesn't need s1 & s2\r
-               if (L1max < L || th1<0){\r
-                       L1max = L;\r
-                       th1 = i;\r
-               }\r
-\r
-               //Kittler and Illingworth\r
-               if (s1>0 && s2>0){\r
-                       L = w1*log(w1/sqrt(s1))+w2*log(w2/sqrt(s2));\r
-                       //L = w1*log(w1*w1/s1)+w2*log(w2*w2/s2);\r
-                       if (L2max < L || th2<0){\r
-                               L2max = L;\r
-                               th2 = i;\r
-                       }\r
-               }\r
-\r
-               //max entropy\r
-               L = 0;\r
-               for (k=gray_min;k<=i;k++) if (p[k] > 0) L -= p[k]*log(p[k]/w1)/w1;\r
-               for (k;k<=gray_max;k++) if (p[k] > 0)   L -= p[k]*log(p[k]/w2)/w2;\r
-               if (L3max < L || th3<0){\r
-                       L3max = L;\r
-                       th3 = i;\r
-               }\r
-\r
-               //potential difference (based on Electrostatic Binarization method by J. Acharya & G. Sreechakra)\r
-               // L=-fabs(vdiff/vsum); Ã¨ molto selettivo, sembra che L=-fabs(vdiff) o L=-(vsum)\r
-               // abbiano lo stesso valore di soglia... il che semplificherebbe molto la routine\r
-               double vdiff = 0;\r
-               for (k=gray_min;k<=i;k++)\r
-                       vdiff += p[k]*(i-k)*(i-k);\r
-               double vsum = vdiff;\r
-               for (k;k<=gray_max;k++){\r
-                       double dv = p[k]*(k-i)*(k-i);\r
-                       vdiff -= dv;\r
-                       vsum += dv;\r
-               }\r
-               if (vsum>0) L = -fabs(vdiff/vsum); else L = 0;\r
-               if (L4max < L || th4<0){\r
-                       L4max = L;\r
-                       th4 = i;\r
-               }\r
-       }\r
-\r
-       int threshold;\r
-       switch (method){\r
-       case 1: //Otsu\r
-               threshold = th1;\r
-               break;\r
-       case 2: //Kittler and Illingworth\r
-               threshold = th2;\r
-               break;\r
-       case 3: //max entropy\r
-               threshold = th3;\r
-               break;\r
-       case 4: //potential difference\r
-               threshold = th4;\r
-               break;\r
-       default: //auto\r
-               {\r
-                       int nt = 0;\r
-                       threshold = 0;\r
-                       if (th1>=0) { threshold += th1; nt++;}\r
-                       if (th2>=0) { threshold += th2; nt++;}\r
-                       if (th3>=0) { threshold += th3; nt++;}\r
-                       if (th4>=0) { threshold += th4; nt++;}\r
-                       if (nt)\r
-                               threshold /= nt;\r
-                       else\r
-                               threshold = (gray_min+gray_max)/2;\r
-\r
-                       /*better(?) but really expensive alternative:\r
-                       n = 0:255;\r
-                       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));\r
-                       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));\r
-                       ...\r
-                       mse_th1 = sum((p-pth1).^2);\r
-                       mse_th2 = sum((p-pth2).^2);\r
-                       ...\r
-                       select th# that gives minimum mse_th#\r
-                       */\r
-\r
-               }\r
-       }\r
-\r
-       if (threshold <= gray_min || threshold >= gray_max)\r
-               threshold = (gray_min+gray_max)/2;\r
-       \r
-       return threshold;\r
-}\r
-///////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Converts the image to B&W, using an optimal threshold mask\r
- * \param method: 0 = average all methods (default); 1 = Otsu; 2 = Kittler & Illingworth; 3 = max entropy; 4 = potential difference;\r
- * \param nBoxSize: the image is divided into "nBoxSize x nBoxSize" blocks, from where the threshold is computed; min = 8; default = 64.\r
- * \param pContrastMask: limit the computation only in regions with contrasted (!=0) pixels; default = 0.\r
- * \param nBias: global offset added to the threshold mask; default = 0.\r
- * \param fGlobalLocalBalance: balance between local and global threshold. default = 0.5\r
- * fGlobalLocalBalance can be from 0.0 (use only local threshold) to 1.0 (use only global threshold)\r
- * the pContrastMask image must be grayscale with same with and height of the current image,\r
- * \return true if everything is ok.\r
- * \sa OptimalThreshold\r
- */\r
-bool CxImage::AdaptiveThreshold(long method, long nBoxSize, CxImage* pContrastMask, long nBias, float fGlobalLocalBalance)\r
-{\r
-       if (!pDib)\r
-               return false;\r
-\r
-       if (pContrastMask){\r
-               if (!pContrastMask->IsValid() ||\r
-                       !pContrastMask->IsGrayScale() ||\r
-                       pContrastMask->GetWidth() != GetWidth() ||\r
-                       pContrastMask->GetHeight() != GetHeight()){\r
-                       strcpy(info.szLastError,"AdaptiveThreshold invalid ContrastMask");\r
-                       return false;\r
-               }\r
-       }\r
-\r
-       if (nBoxSize<8) nBoxSize = 8;\r
-       if (fGlobalLocalBalance<0.0f) fGlobalLocalBalance = 0.0f;\r
-       if (fGlobalLocalBalance>1.0f) fGlobalLocalBalance = 1.0f;\r
-\r
-       long mw = (head.biWidth + nBoxSize - 1)/nBoxSize;\r
-       long mh = (head.biHeight + nBoxSize - 1)/nBoxSize;\r
-\r
-       CxImage mask(mw,mh,8);\r
-       if(!mask.GrayScale())\r
-               return false;\r
-\r
-       if(!GrayScale())\r
-               return false;\r
-\r
-       int globalthreshold = OptimalThreshold(method, 0, pContrastMask);\r
-       if (globalthreshold <0)\r
-               return false;\r
-\r
-       for (long y=0; y<mh; y++){\r
-               for (long x=0; x<mw; x++){\r
-                       info.nProgress = (long)(100*(x+y*mw)/(mw*mh));\r
-                       if (info.nEscape) break;\r
-                       RECT r;\r
-                       r.left = x*nBoxSize;\r
-                       r.right = r.left + nBoxSize;\r
-                       r.bottom = y*nBoxSize;\r
-                       r.top = r.bottom + nBoxSize;\r
-                       int threshold = OptimalThreshold(method, &r, pContrastMask);\r
-                       if (threshold <0) return false;\r
-                       mask.SetPixelIndex(x,y,(BYTE)max(0,min(255,nBias+((1.0f-fGlobalLocalBalance)*threshold + fGlobalLocalBalance*globalthreshold))));\r
-               }\r
-       }\r
-\r
-       mask.Resample(mw*nBoxSize,mh*nBoxSize,0);\r
-       mask.Crop(0,head.biHeight,head.biWidth,0);\r
-\r
-       if(!Threshold(&mask))\r
-               return false;\r
-\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#include <queue>\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Flood Fill\r
- * \param xStart, yStart: starting point\r
- * \param cFillColor: filling color\r
- * \param nTolerance: deviation from the starting point color\r
- * \param nOpacity: can be from 0 (transparent) to 255 (opaque, default)\r
- * \param bSelectFilledArea: if true, the pixels in the region are also set in the selection layer; default = false\r
- * \param nSelectionLevel: if bSelectFilledArea is true, the selected pixels are set to nSelectionLevel; default = 255\r
- * Note: nOpacity=0 && bSelectFilledArea=true act as a "magic wand"\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::FloodFill(const long xStart, const long yStart, const RGBQUAD cFillColor, const BYTE nTolerance,\r
-                                               BYTE nOpacity, const bool bSelectFilledArea, const BYTE nSelectionLevel)\r
-{\r
-       if (!pDib)\r
-               return false;\r
-\r
-       if (!IsInside(xStart,yStart))\r
-               return true;\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       if (!SelectionIsInside(xStart,yStart))\r
-               return true;\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-       RGBQUAD* pPalette=NULL;\r
-       WORD bpp = GetBpp();\r
-       //nTolerance or nOpacity implemented only for grayscale or 24bpp images\r
-       if ((nTolerance || nOpacity != 255) &&  !(head.biBitCount == 24 || IsGrayScale())){\r
-               pPalette = new RGBQUAD[head.biClrUsed];\r
-               memcpy(pPalette, GetPalette(),GetPaletteSize());\r
-               if (!IncreaseBpp(24))\r
-                       return false;\r
-       }\r
-\r
-       BYTE* pFillMask = (BYTE*)calloc(head.biWidth * head.biHeight,1);\r
-       if (!pFillMask)\r
-               return false;\r
-\r
-//------------------------------------- Begin of Flood Fill\r
-       POINT offset[4] = {{-1,0},{0,-1},{1,0},{0,1}};\r
-       std::queue<POINT> q;\r
-       POINT point = {xStart,yStart};\r
-       q.push(point);\r
-\r
-       if (IsIndexed()){ //--- Generic indexed image, no tolerance OR Grayscale image with tolerance\r
-               BYTE idxRef = GetPixelIndex(xStart,yStart);\r
-               BYTE idxFill = GetNearestIndex(cFillColor);\r
-               BYTE idxMin = (BYTE)min(255, max(0,(int)(idxRef - nTolerance)));\r
-               BYTE idxMax = (BYTE)min(255, max(0,(int)(idxRef + nTolerance)));\r
-\r
-               while(!q.empty())\r
-               {\r
-                       point = q.front();\r
-                       q.pop();\r
-\r
-                       for (int z=0; z<4; z++){\r
-                               int x = point.x + offset[z].x;\r
-                               int y = point.y + offset[z].y;\r
-                               if(IsInside(x,y)){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                                 if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                                 {\r
-                                       BYTE idx = BlindGetPixelIndex(x, y);\r
-                                       BYTE* pFill = pFillMask + x + y * head.biWidth;\r
-                                       if (*pFill==0 && idxMin <= idx && idx <= idxMax )\r
-                                       {\r
-                                               if (nOpacity>0){\r
-                                                       if (nOpacity == 255)\r
-                                                               BlindSetPixelIndex(x, y, idxFill);\r
-                                                       else\r
-                                                               BlindSetPixelIndex(x, y, (BYTE)((idxFill * nOpacity + idx * (255-nOpacity))>>8));\r
-                                               }\r
-                                               POINT pt = {x,y};\r
-                                               q.push(pt);\r
-                                               *pFill = 1;\r
-                                       }\r
-                                 }\r
-                               }\r
-                       }\r
-               }\r
-       } else { //--- RGB image\r
-               RGBQUAD cRef = GetPixelColor(xStart,yStart);\r
-               RGBQUAD cRefMin, cRefMax;\r
-               cRefMin.rgbRed   = (BYTE)min(255, max(0,(int)(cRef.rgbRed   - nTolerance)));\r
-               cRefMin.rgbGreen = (BYTE)min(255, max(0,(int)(cRef.rgbGreen - nTolerance)));\r
-               cRefMin.rgbBlue  = (BYTE)min(255, max(0,(int)(cRef.rgbBlue  - nTolerance)));\r
-               cRefMax.rgbRed   = (BYTE)min(255, max(0,(int)(cRef.rgbRed   + nTolerance)));\r
-               cRefMax.rgbGreen = (BYTE)min(255, max(0,(int)(cRef.rgbGreen + nTolerance)));\r
-               cRefMax.rgbBlue  = (BYTE)min(255, max(0,(int)(cRef.rgbBlue  + nTolerance)));\r
-\r
-               while(!q.empty())\r
-               {\r
-                       point = q.front();\r
-                       q.pop();\r
-\r
-                       for (int z=0; z<4; z++){\r
-                               int x = point.x + offset[z].x;\r
-                               int y = point.y + offset[z].y;\r
-                               if(IsInside(x,y)){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                                 if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                                 {\r
-                                       RGBQUAD cc = BlindGetPixelColor(x, y);\r
-                                       BYTE* pFill = pFillMask + x + y * head.biWidth;\r
-                                       if (*pFill==0 &&\r
-                                               cRefMin.rgbRed   <= cc.rgbRed   && cc.rgbRed   <= cRefMax.rgbRed   &&\r
-                                               cRefMin.rgbGreen <= cc.rgbGreen && cc.rgbGreen <= cRefMax.rgbGreen &&\r
-                                               cRefMin.rgbBlue  <= cc.rgbBlue  && cc.rgbBlue  <= cRefMax.rgbBlue )\r
-                                       {\r
-                                               if (nOpacity>0){\r
-                                                       if (nOpacity == 255)\r
-                                                               BlindSetPixelColor(x, y, cFillColor);\r
-                                                       else\r
-                                                       {\r
-                                                               cc.rgbRed   = (BYTE)((cFillColor.rgbRed   * nOpacity + cc.rgbRed   * (255-nOpacity))>>8);\r
-                                                               cc.rgbGreen = (BYTE)((cFillColor.rgbGreen * nOpacity + cc.rgbGreen * (255-nOpacity))>>8);\r
-                                                               cc.rgbBlue  = (BYTE)((cFillColor.rgbBlue  * nOpacity + cc.rgbBlue  * (255-nOpacity))>>8);\r
-                                                               BlindSetPixelColor(x, y, cc);\r
-                                                       }\r
-                                               }\r
-                                               POINT pt = {x,y};\r
-                                               q.push(pt);\r
-                                               *pFill = 1;\r
-                                       }\r
-                                 }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       if (pFillMask[xStart+yStart*head.biWidth] == 0 && nOpacity>0){\r
-               if (nOpacity == 255)\r
-                       BlindSetPixelColor(xStart, yStart, cFillColor);\r
-               else\r
-               {\r
-                       RGBQUAD cc = BlindGetPixelColor(xStart, yStart);\r
-                       cc.rgbRed   = (BYTE)((cFillColor.rgbRed   * nOpacity + cc.rgbRed   * (255-nOpacity))>>8);\r
-                       cc.rgbGreen = (BYTE)((cFillColor.rgbGreen * nOpacity + cc.rgbGreen * (255-nOpacity))>>8);\r
-                       cc.rgbBlue  = (BYTE)((cFillColor.rgbBlue  * nOpacity + cc.rgbBlue  * (255-nOpacity))>>8);\r
-                       BlindSetPixelColor(xStart, yStart, cc);\r
-               }\r
-       }\r
-       pFillMask[xStart+yStart*head.biWidth] = 1;\r
-//------------------------------------- End of Flood Fill\r
-\r
-       //if necessary, restore the original BPP and palette\r
-       if (pPalette){\r
-               DecreaseBpp(bpp, false, pPalette);\r
-               delete [] pPalette;\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       if (bSelectFilledArea){\r
-               if (!SelectionIsValid()){\r
-                       if (!SelectionCreate()){\r
-                               return false;\r
-                       }\r
-                       SelectionClear();\r
-                       info.rSelectionBox.right = head.biWidth;\r
-                       info.rSelectionBox.top = head.biHeight;\r
-                       info.rSelectionBox.left = info.rSelectionBox.bottom = 0;\r
-               }\r
-               RECT r;\r
-               SelectionGetBox(r);\r
-               for (long y = r.bottom; y < r.top; y++){\r
-                       BYTE* pFill = pFillMask + r.left + y * head.biWidth;\r
-                       for (long x = r.left; x<r.right; x++){\r
-                               if (*pFill)     SelectionSet(x,y,nSelectionLevel);\r
-                               pFill++;\r
-                       }\r
-               }\r
-               SelectionRebuildBox();\r
-       }\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-       free(pFillMask);\r
-\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DSP\r
+// xImaDsp.cpp : DSP functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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(BYTE 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 (long y=0;y<head.biHeight;y++){
+               info.nProgress = (long)(100*y/head.biHeight);
+               if (info.nEscape) break;
+               for (long 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 (long y=0;y<head.biHeight;y++){
+               info.nProgress = (long)(100*y/head.biHeight);
+               if (info.nEscape) break;
+               for (long 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(BYTE 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();
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*y/head.biHeight);
+               if (info.nEscape) break;
+               for(long x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+                       if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                       {
+                               BYTE 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(long y=0; y<head.biHeight; y++){
+               for(long 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(long j=0; j<256; j++){
+               BYTE i=(BYTE)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(long yy=0; yy<head.biHeight; yy++){
+               for(long xx=0; xx<head.biWidth; xx++){
+                       color = BlindGetPixelColor(xx,yy);
+                       if (c) tmpc.BlindSetPixelIndex(xx,yy,(BYTE)(255-color.rgbRed));
+                       if (m) tmpm.BlindSetPixelIndex(xx,yy,(BYTE)(255-color.rgbGreen));
+                       if (y) tmpy.BlindSetPixelIndex(xx,yy,(BYTE)(255-color.rgbBlue));
+                       if (k) tmpk.BlindSetPixelIndex(xx,yy,(BYTE)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(long yy=0; yy<head.biHeight; yy++){
+               for(long 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(long yy=0; yy<head.biHeight; yy++){
+               for(long 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(long yy=0; yy<head.biHeight; yy++){
+               for(long 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(long y=0; y<head.biHeight; y++){
+               for(long 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(long j=0; j<256; j++){
+               BYTE i=(BYTE)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 BYTE. */
+/* 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)
+{
+       BYTE R,G,B;                                     /* input RGB values */
+       BYTE H,L,S;                                     /* output HSL values */
+       BYTE cMax,cMin;                         /* max and min RGB values */
+       WORD Rdelta,Gdelta,Bdelta;      /* intermediate value: % of spread from max*/
+
+       R = lRGBColor.rgbRed;   /* get R, G, and B out of DWORD */
+       G = lRGBColor.rgbGreen;
+       B = lRGBColor.rgbBlue;
+
+       cMax = max( max(R,G), B);       /* calculate lightness */
+       cMin = min( min(R,G), B);
+       L = (BYTE)((((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 = (BYTE)((((cMax-cMin)*HSLMAX)+((cMax+cMin)/2))/(cMax+cMin));
+               else
+                       S = (BYTE)((((cMax-cMin)*HSLMAX)+((2*RGBMAX-cMax-cMin)/2))/(2*RGBMAX-cMax-cMin));
+               /* hue */
+               Rdelta = (WORD)((((cMax-R)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));
+               Gdelta = (WORD)((((cMax-G)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));
+               Bdelta = (WORD)((((cMax-B)*(HSLMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin));
+
+               if (R == cMax)
+                       H = (BYTE)(Bdelta - Gdelta);
+               else if (G == cMax)
+                       H = (BYTE)((HSLMAX/3) + Rdelta - Bdelta);
+               else /* B == cMax */
+                       H = (BYTE)(((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;
+       BYTE 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=(BYTE)(l*255.0f);
+       } else {
+               r = (BYTE)(HueToRGB(m1,m2,h+120) * 255.0f);
+               g = (BYTE)(HueToRGB(m1,m2,h) * 255.0f);
+               b = (BYTE)(HueToRGB(m1,m2,h-120) * 255.0f);
+       }
+
+       RGBQUAD rgb = {b,g,r,0};
+       return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::YUVtoRGB(RGBQUAD lYUVColor)
+{
+       int U,V,R,G,B;
+       float Y = lYUVColor.rgbRed;
+       U = lYUVColor.rgbGreen - 128;
+       V = lYUVColor.rgbBlue - 128;
+
+//     R = (int)(1.164 * Y + 2.018 * U);
+//     G = (int)(1.164 * Y - 0.813 * V - 0.391 * U);
+//     B = (int)(1.164 * Y + 1.596 * V);
+       R = (int)( Y + 1.403f * V);
+       G = (int)( Y - 0.344f * U - 0.714f * V);
+       B = (int)( Y + 1.770f * U);
+
+       R= min(255,max(0,R));
+       G= min(255,max(0,G));
+       B= min(255,max(0,B));
+       RGBQUAD rgb={(BYTE)B,(BYTE)G,(BYTE)R,0};
+       return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoYUV(RGBQUAD lRGBColor)
+{
+       int Y,U,V,R,G,B;
+       R = lRGBColor.rgbRed;
+       G = lRGBColor.rgbGreen;
+       B = lRGBColor.rgbBlue;
+
+//     Y = (int)( 0.257 * R + 0.504 * G + 0.098 * B);
+//     U = (int)( 0.439 * R - 0.368 * G - 0.071 * B + 128);
+//     V = (int)(-0.148 * R - 0.291 * G + 0.439 * B + 128);
+       Y = (int)(0.299f * R + 0.587f * G + 0.114f * B);
+       U = (int)((B-Y) * 0.565f + 128);
+       V = (int)((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={(BYTE)V,(BYTE)U,(BYTE)Y,0};
+       return yuv;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::YIQtoRGB(RGBQUAD lYIQColor)
+{
+       int I,Q,R,G,B;
+       float Y = lYIQColor.rgbRed;
+       I = lYIQColor.rgbGreen - 128;
+       Q = lYIQColor.rgbBlue - 128;
+
+       R = (int)( Y + 0.956f * I + 0.621f * Q);
+       G = (int)( Y - 0.273f * I - 0.647f * Q);
+       B = (int)( 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={(BYTE)B,(BYTE)G,(BYTE)R,0};
+       return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoYIQ(RGBQUAD lRGBColor)
+{
+       int Y,I,Q,R,G,B;
+       R = lRGBColor.rgbRed;
+       G = lRGBColor.rgbGreen;
+       B = lRGBColor.rgbBlue;
+
+       Y = (int)( 0.2992f * R + 0.5868f * G + 0.1140f * B);
+       I = (int)( 0.5960f * R - 0.2742f * G - 0.3219f * B + 128);
+       Q = (int)( 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={(BYTE)Q,(BYTE)I,(BYTE)Y,0};
+       return yiq;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::XYZtoRGB(RGBQUAD lXYZColor)
+{
+       int X,Y,Z,R,G,B;
+       X = lXYZColor.rgbRed;
+       Y = lXYZColor.rgbGreen;
+       Z = lXYZColor.rgbBlue;
+       double k=1.088751;
+
+       R = (int)(  3.240479f * X - 1.537150f * Y - 0.498535f * Z * k);
+       G = (int)( -0.969256f * X + 1.875992f * Y + 0.041556f * Z * k);
+       B = (int)(  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={(BYTE)B,(BYTE)G,(BYTE)R,0};
+       return rgb;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::RGBtoXYZ(RGBQUAD lRGBColor)
+{
+       int X,Y,Z,R,G,B;
+       R = lRGBColor.rgbRed;
+       G = lRGBColor.rgbGreen;
+       B = lRGBColor.rgbBlue;
+
+       X = (int)( 0.412453f * R + 0.357580f * G + 0.180423f * B);
+       Y = (int)( 0.212671f * R + 0.715160f * G + 0.072169f * B);
+       Z = (int)((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={(BYTE)Z,(BYTE)Y,(BYTE)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(DWORD j=0; j<head.biClrUsed; j++){
+               BYTE i=(BYTE)(j*correction*(255/(head.biClrUsed-1)));
+               RGBQUAD hsl={120,240,i,0};
+               SetPaletteColor((BYTE)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(BYTE hue, BYTE sat, float blend)
+{
+       if (!pDib) return false;
+
+       if (blend < 0.0f) blend = 0.0f;
+       if (blend > 1.0f) blend = 1.0f;
+       int a0 = (int)(256*blend);
+       int a1 = 256 - a0;
+
+       bool bFullBlend = false;
+       if (blend > 0.999f)     bFullBlend = true;
+
+       RGBQUAD color,hsl;
+       if (head.biClrUsed==0){
+
+               long 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(long y=ymin; y<ymax; y++){
+                       info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+                       if (info.nEscape) break;
+                       for(long 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 = (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);
+                                               hsl = HSLtoRGB(hsl);
+                                               //BlendPixelColor(x,y,hsl,blend);
+                                               //color.rgbRed = (BYTE)(hsl.rgbRed * blend + color.rgbRed * (1.0f - blend));
+                                               //color.rgbBlue = (BYTE)(hsl.rgbBlue * blend + color.rgbBlue * (1.0f - blend));
+                                               //color.rgbGreen = (BYTE)(hsl.rgbGreen * blend + color.rgbGreen * (1.0f - blend));
+                                               color.rgbRed = (BYTE)((hsl.rgbRed * a0 + color.rgbRed * a1)>>8);
+                                               color.rgbBlue = (BYTE)((hsl.rgbBlue * a0 + color.rgbBlue * a1)>>8);
+                                               color.rgbGreen = (BYTE)((hsl.rgbGreen * a0 + color.rgbGreen * a1)>>8);
+                                               BlindSetPixelColor(x,y,color);
+                                       }
+                               }
+                       }
+               }
+       } else {
+               for(DWORD j=0; j<head.biClrUsed; j++){
+                       if (bFullBlend){
+                               color = RGBtoHSL(GetPaletteColor((BYTE)j));
+                               color.rgbRed=hue;
+                               color.rgbGreen=sat;
+                               SetPaletteColor((BYTE)j,HSLtoRGB(color));
+                       } else {
+                               color = GetPaletteColor((BYTE)j);
+                               hsl.rgbRed=hue;
+                               hsl.rgbGreen=sat;
+                               hsl.rgbBlue = (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);
+                               hsl = HSLtoRGB(hsl);
+                               color.rgbRed = (BYTE)(hsl.rgbRed * blend + color.rgbRed * (1.0f - blend));
+                               color.rgbBlue = (BYTE)(hsl.rgbBlue * blend + color.rgbBlue * (1.0f - blend));
+                               color.rgbGreen = (BYTE)(hsl.rgbGreen * blend + color.rgbGreen * (1.0f - blend));
+                               SetPaletteColor((BYTE)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(long brightness, long contrast)
+{
+       if (!pDib) return false;
+       float c=(100 + contrast)/100.0f;
+       brightness+=128;
+
+       BYTE cTable[256]; //<nipper>
+       for (int i=0;i<256;i++) {
+               cTable[i] = (BYTE)max(0,min(255,(int)((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;
+
+       long 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;
+
+       BYTE *iSrc=tmp.info.pImage;
+       iSrc += tmp.info.dwEffWidth*ymin; // necessary for selections <Admir Hodzic>
+
+       for(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin)); //<zhanghk><Anatoly Ivasyuk>
+               for(long 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(long* kernel, long Ksize, long Kfactor, long Koffset)
+{
+       if (!pDib) return false;
+
+       long k2 = Ksize/2;
+       long kmax= Ksize-k2;
+       long r,g,b,i;
+       long ksumcur,ksumtot;
+       RGBQUAD c;
+
+       CxImage tmp(*this);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       long 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(long j=-k2;j<kmax;j++){
+               for(long k=-k2;k<kmax;k++){
+                       ksumtot += kernel[(j+k2)+Ksize*(k+k2)];
+               }
+       }
+
+       if ((head.biBitCount==8) && IsGrayScale())
+       {
+               unsigned char* cPtr;
+               unsigned char* cPtr2;      
+               int iCount;
+               int iY, iY2, iY1;
+               cPtr = info.pImage;
+               cPtr2 = (unsigned char *)tmp.info.pImage;
+               for(long y=ymin; y<ymax; y++){
+                       info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+                       if (info.nEscape) break;
+                       iY1 = y*info.dwEffWidth+xmin;
+                       for(long 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(long j=-k2;j<kmax;j++, iY2+=info.dwEffWidth)
+                                       {
+                                               if (0>(y+j) || (y+j)>=head.biHeight) continue;
+                                               iY = iY2+x;
+                                               for(long 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] = (BYTE)min(255, max(0,(int)(b + Koffset)));
+                                       } else if (ksumtot == ksumcur) {
+                                               cPtr2[iY1] = (BYTE)min(255, max(0,(int)(b/Kfactor + Koffset)));
+                                       } else {
+                                               cPtr2[iY1] = (BYTE)min(255, max(0,(int)((b*ksumtot)/(ksumcur*Kfactor) + Koffset)));
+                                       }
+                               }
+                       }
+               }
+       }
+       else
+       {
+               for(long y=ymin; y<ymax; y++){
+                       info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+                       if (info.nEscape) break;
+                       for(long x=xmin; x<xmax; x++){
+       #if CXIMAGE_SUPPORT_SELECTION
+                               if (BlindSelectionIsInside(x,y))
+       #endif //CXIMAGE_SUPPORT_SELECTION
+                                       {
+                                       r=b=g=ksumcur=0;
+                                       for(long j=-k2;j<kmax;j++){
+                                               for(long 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   = (BYTE)min(255, max(0,(int)(r + Koffset)));
+                                               c.rgbGreen = (BYTE)min(255, max(0,(int)(g + Koffset)));
+                                               c.rgbBlue  = (BYTE)min(255, max(0,(int)(b + Koffset)));
+                                       } else if (ksumtot == ksumcur) {
+                                               c.rgbRed   = (BYTE)min(255, max(0,(int)(r/Kfactor + Koffset)));
+                                               c.rgbGreen = (BYTE)min(255, max(0,(int)(g/Kfactor + Koffset)));
+                                               c.rgbBlue  = (BYTE)min(255, max(0,(int)(b/Kfactor + Koffset)));
+                                       } else {
+                                               c.rgbRed   = (BYTE)min(255, max(0,(int)((r*ksumtot)/(ksumcur*Kfactor) + Koffset)));
+                                               c.rgbGreen = (BYTE)min(255, max(0,(int)((g*ksumtot)/(ksumcur*Kfactor) + Koffset)));
+                                               c.rgbBlue  = (BYTE)min(255, max(0,(int)((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(long Ksize)
+{
+       if (!pDib) return false;
+
+       long k2 = Ksize/2;
+       long kmax= Ksize-k2;
+       BYTE r,g,b;
+       RGBQUAD c;
+
+       CxImage tmp(*this);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+                       if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                       {
+                               r=b=g=255;
+                               for(long j=-k2;j<kmax;j++){
+                                       for(long 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(long Ksize)
+{
+       if (!pDib) return false;
+
+       long k2 = Ksize/2;
+       long kmax= Ksize-k2;
+       BYTE r,g,b;
+       RGBQUAD c;
+
+       CxImage tmp(*this);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+                       if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                       {
+                               r=b=g=0;
+                               for(long j=-k2;j<kmax;j++){
+                                       for(long 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(long Ksize)
+{
+       if (!pDib) return false;
+
+       long k2 = Ksize/2;
+       long kmax= Ksize-k2;
+       BYTE r,g,b,rr,gg,bb;
+       RGBQUAD c;
+
+       CxImage tmp(*this);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long 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(long j=-k2;j<kmax;j++){
+                                       for(long 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   = (BYTE)(255-abs(r-rr));
+                               c.rgbGreen = (BYTE)(255-abs(g-gg));
+                               c.rgbBlue  = (BYTE)(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
+ *
+ * thanks to Mwolski
+ */
+// 
+void CxImage::Mix(CxImage & imgsrc2, ImageOpType op, long lXOffset, long lYOffset, bool bMixAlpha)
+{
+    long lWide = min(GetWidth(),imgsrc2.GetWidth()-lXOffset);
+    long lHeight = min(GetHeight(),imgsrc2.GetHeight()-lYOffset);
+
+       bool bEditAlpha = imgsrc2.AlphaIsValid() & bMixAlpha;
+
+       if (bEditAlpha && AlphaIsValid()==false){
+               AlphaCreate();
+       }
+
+    RGBQUAD rgbBackgrnd1 = GetTransColor();
+    RGBQUAD rgb1, rgb2, rgbDest;
+
+    for(long lY=0;lY<lHeight;lY++)
+    {
+               info.nProgress = (long)(100*lY/head.biHeight);
+               if (info.nEscape) break;
+
+        for(long 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 =  (BYTE)((rgb1.rgbBlue+rgb2.rgbBlue)/2);
+                                               rgbDest.rgbGreen = (BYTE)((rgb1.rgbGreen+rgb2.rgbGreen)/2);
+                                               rgbDest.rgbRed =   (BYTE)((rgb1.rgbRed+rgb2.rgbRed)/2);
+                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)((rgb1.rgbReserved+rgb2.rgbReserved)/2);
+                                       break;
+                                       case OpAdd:
+                                               rgbDest.rgbBlue = (BYTE)max(0,min(255,rgb1.rgbBlue+rgb2.rgbBlue));
+                                               rgbDest.rgbGreen = (BYTE)max(0,min(255,rgb1.rgbGreen+rgb2.rgbGreen));
+                                               rgbDest.rgbRed = (BYTE)max(0,min(255,rgb1.rgbRed+rgb2.rgbRed));
+                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)max(0,min(255,rgb1.rgbReserved+rgb2.rgbReserved));
+                                       break;
+                                       case OpSub:
+                                               rgbDest.rgbBlue = (BYTE)max(0,min(255,rgb1.rgbBlue-rgb2.rgbBlue));
+                                               rgbDest.rgbGreen = (BYTE)max(0,min(255,rgb1.rgbGreen-rgb2.rgbGreen));
+                                               rgbDest.rgbRed = (BYTE)max(0,min(255,rgb1.rgbRed-rgb2.rgbRed));
+                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)max(0,min(255,rgb1.rgbReserved-rgb2.rgbReserved));
+                                       break;
+                                       case OpAnd:
+                                               rgbDest.rgbBlue = (BYTE)(rgb1.rgbBlue&rgb2.rgbBlue);
+                                               rgbDest.rgbGreen = (BYTE)(rgb1.rgbGreen&rgb2.rgbGreen);
+                                               rgbDest.rgbRed = (BYTE)(rgb1.rgbRed&rgb2.rgbRed);
+                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(rgb1.rgbReserved&rgb2.rgbReserved);
+                                       break;
+                                       case OpXor:
+                                               rgbDest.rgbBlue = (BYTE)(rgb1.rgbBlue^rgb2.rgbBlue);
+                                               rgbDest.rgbGreen = (BYTE)(rgb1.rgbGreen^rgb2.rgbGreen);
+                                               rgbDest.rgbRed = (BYTE)(rgb1.rgbRed^rgb2.rgbRed);
+                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(rgb1.rgbReserved^rgb2.rgbReserved);
+                                       break;
+                                       case OpOr:
+                                               rgbDest.rgbBlue = (BYTE)(rgb1.rgbBlue|rgb2.rgbBlue);
+                                               rgbDest.rgbGreen = (BYTE)(rgb1.rgbGreen|rgb2.rgbGreen);
+                                               rgbDest.rgbRed = (BYTE)(rgb1.rgbRed|rgb2.rgbRed);
+                                               if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(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:
+                                               { 
+                                                       BYTE a,a1; 
+                                                       
+                                                       if (imgsrc2.IsTransparent(lX+lXOffset,lY+lYOffset)){
+                                                               a=0;
+                                                       } else if (imgsrc2.AlphaIsValid()){
+                                                               a=imgsrc2.AlphaGet(lX+lXOffset,lY+lYOffset);
+                                                               a =(BYTE)((a*imgsrc2.info.nAlphaMax)/255);
+                                                       } else {
+                                                               a=255;
+                                                       }
+
+                                                       if (a==0){ //transparent 
+                                                               rgbDest = rgb1; 
+                                                       } else if (a==255){ //opaque 
+                                                               rgbDest = rgb2; 
+                                                       } else { //blend 
+                                                               a1 = (BYTE)~a; 
+                                                               rgbDest.rgbBlue = (BYTE)((rgb1.rgbBlue*a1+rgb2.rgbBlue*a)/255); 
+                                                               rgbDest.rgbGreen = (BYTE)((rgb1.rgbGreen*a1+rgb2.rgbGreen*a)/255); 
+                                                               rgbDest.rgbRed = (BYTE)((rgb1.rgbRed*a1+rgb2.rgbRed*a)/255);  
+                                                       }
+
+                                                       if (bEditAlpha) rgbDest.rgbReserved = (BYTE)((rgb1.rgbReserved*a)/255);
+                                               } 
+                                               break; 
+                                       case OpSrcBlend:
+                                               if(IsTransparent(lX,lY))
+                                                       rgbDest = rgb2;
+                                               else
+                                               {
+                                                       long lBDiff = abs(rgb1.rgbBlue - rgbBackgrnd1.rgbBlue);
+                                                       long lGDiff = abs(rgb1.rgbGreen - rgbBackgrnd1.rgbGreen);
+                                                       long 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 = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbBlue) +
+                                                                                               dSmallAmt)));
+                                                               rgbDest.rgbGreen = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbGreen) +
+                                                                                               dSmallAmt)));
+                                                               rgbDest.rgbRed = (BYTE)max(0,min(255,(int)(dLarge*((double)rgb1.rgbRed) +
+                                                                                               dSmallAmt)));
+                                                       }
+                                                       else
+                                                               rgbDest = rgb1;
+                                               }
+                                               break;
+                                               default:
+                                               return;
+                               }
+                               SetPixelColor(lX,lY,rgbDest,bEditAlpha);
+                       }
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+// thanks to Kenneth Ballard
+void CxImage::MixFrom(CxImage & imagesrc2, long lXOffset, long lYOffset)
+{
+    long width = imagesrc2.GetWidth();
+    long height = imagesrc2.GetHeight();
+
+    int 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(long r, long g, long b)
+{
+       if (!pDib) return false;
+       RGBQUAD color;
+       if (head.biClrUsed==0){
+
+               long 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(long y=ymin; y<ymax; y++){
+                       for(long x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+                               if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                               {
+                                       color = BlindGetPixelColor(x,y);
+                                       color.rgbRed = (BYTE)max(0,min(255,(int)(color.rgbRed + r)));
+                                       color.rgbGreen = (BYTE)max(0,min(255,(int)(color.rgbGreen + g)));
+                                       color.rgbBlue = (BYTE)max(0,min(255,(int)(color.rgbBlue + b)));
+                                       BlindSetPixelColor(x,y,color);
+                               }
+                       }
+               }
+       } else {
+               for(DWORD j=0; j<head.biClrUsed; j++){
+                       color = GetPaletteColor((BYTE)j);
+                       color.rgbRed = (BYTE)max(0,min(255,(int)(color.rgbRed + r)));
+                       color.rgbGreen = (BYTE)max(0,min(255,(int)(color.rgbGreen + g)));
+                       color.rgbBlue = (BYTE)max(0,min(255,(int)(color.rgbBlue + b)));
+                       SetPaletteColor((BYTE)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;
+
+       BYTE cTable[256]; //<nipper>
+       for (int i=0;i<256;i++) {
+               cTable[i] = (BYTE)max(0,min(255,(int)( 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;
+       int i;
+
+       dinvgamma = 1/gammaR;
+       dMax = pow(255.0, dinvgamma) / 255.0;
+       BYTE cTableR[256];
+       for (i=0;i<256;i++)     {
+               cTableR[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax)));
+       }
+
+       dinvgamma = 1/gammaG;
+       dMax = pow(255.0, dinvgamma) / 255.0;
+       BYTE cTableG[256];
+       for (i=0;i<256;i++)     {
+               cTableG[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax)));
+       }
+
+       dinvgamma = 1/gammaB;
+       dMax = pow(255.0, dinvgamma) / 255.0;
+       BYTE cTableB[256];
+       for (i=0;i<256;i++)     {
+               cTableB[i] = (BYTE)max(0,min(255,(int)( 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(long Ksize)
+{
+       if (!pDib) return false;
+
+       long k2 = Ksize/2;
+       long kmax= Ksize-k2;
+       long i,j,k;
+
+       RGBQUAD* kernel = (RGBQUAD*)malloc(Ksize*Ksize*sizeof(RGBQUAD));
+
+       CxImage tmp(*this);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long 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(long level)
+{
+       if (!pDib) return false;
+       RGBQUAD color;
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin)); //<zhanghk><Anatoly Ivasyuk>
+               for(long x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+                       if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                       {
+                               color = BlindGetPixelColor(x,y);
+                               n=(long)((rand()/(float)RAND_MAX - 0.5)*level);
+                               color.rgbRed = (BYTE)max(0,min(255,(int)(color.rgbRed + n)));
+                               n=(long)((rand()/(float)RAND_MAX - 0.5)*level);
+                               color.rgbGreen = (BYTE)max(0,min(255,(int)(color.rgbGreen + n)));
+                               n=(long)((rand()/(float)RAND_MAX - 0.5)*level);
+                               color.rgbBlue = (BYTE)max(0,min(255,(int)(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,
+                                  long direction, bool bForceFFT, bool bMagnitude)
+{
+       //check if there is something to convert
+       if (srcReal==NULL && srcImag==NULL) return false;
+
+       long 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)) {
+               long 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;
+       long 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,(BYTE)max(0,min(255,(nn*(3+log(_cabs(grid[k][j])))))));
+                               if (grid[k][j].x==0){
+                                       tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/0.0000000001)*nn)))));
+                               } else {
+                                       tmpImag->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128+(atan(grid[k][j].y/grid[k][j].x)*nn)))));
+                               }
+                       } else {
+                               tmpReal->SetPixelIndex(k,j,(BYTE)max(0,min(255,(128 + grid[k][j].x*nn))));
+                               tmpImag->SetPixelIndex(k,j,(BYTE)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(long x)
+{
+       long 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(int dir,int m,double *x,double *y)
+{
+       long 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(int dir,long m,double *x1,double *y1,double *x2,double *y2)
+{
+   long 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, long colorspace)
+{
+       if (r==0 || g==0 || b==0) return false;
+
+       long w = r->GetWidth();
+       long 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 (long y=0;y<h;y++){
+               info.nProgress = (long)(100*y/h); //<Anatoly Ivasyuk>
+               for (long 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, long niterations, long colorspace)
+{
+       if (!IsValid()) return false;
+
+       long w = GetWidth();
+       long 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 (int 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;
+       }
+
+       long w = ch->GetWidth()-1;
+       long h = ch->GetHeight()-1;
+
+       double correction,ix,iy,ixx,ixy,iyy;
+       int 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,(BYTE)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,(BYTE)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,(BYTE)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;
+
+       long Ksize = 3;
+       long k2 = Ksize/2;
+       long kmax= Ksize-k2;
+       long i,j,k;
+       BYTE maxr,maxg,maxb;
+       RGBQUAD pix1,pix2;
+
+       CxImage tmp(*this);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long 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=(BYTE)(255-maxb);
+                               pix1.rgbGreen=(BYTE)(255-maxg);
+                               pix1.rgbRed=(BYTE)(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(long radius)
+{
+       if (!pDib) return false;
+
+       long nx,ny;
+
+       CxImage tmp(*this);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+                       if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                       {
+                               nx=x+(long)((rand()/(float)RAND_MAX - 0.5)*(radius*2));
+                               ny=y+(long)((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]
+ */
+int CxImage::gen_convolve_matrix (float radius, float **cmatrix_p)
+{
+       int matrix_length;
+       int matrix_midpoint;
+       float* cmatrix;
+       int 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 = int (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, int cmatrix_length)
+{
+       float* lookup_table = new float[cmatrix_length * 256];
+       float* lookup_table_p = lookup_table;
+       float* cmatrix_p      = cmatrix;
+       
+       for (int i=0; i<cmatrix_length; i++)
+    {
+               for (int 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, int cmatrix_length, BYTE* cur_col, BYTE* dest_col, int y, long bytes)
+{
+       float scale;
+       float sum;
+       int i=0, j=0;
+       int row;
+       int cmatrix_middle = cmatrix_length/2;
+       
+       float *cmatrix_p;
+       BYTE  *cur_col_p;
+       BYTE  *cur_col_p1;
+       BYTE  *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] = (BYTE)(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] = (BYTE)(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++) = (BYTE)(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] = (BYTE) (0.5f + sum / scale);
+                       }
+               }
+    }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \author [DP]
+ */
+void CxImage::blur_text (BYTE threshold, BYTE decay, BYTE max_depth, CxImage* iSrc, CxImage* iDst, BYTE bytes)
+{
+       long x,y,z,m;
+       BYTE *pSrc, *pSrc2, *pSrc3, *pDst;
+       BYTE step,n;
+       int pivot;
+
+       if (max_depth<1) max_depth = 1;
+
+       long 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 = (long)((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 = (BYTE)((pSrc[x+bytes]-pSrc[x])/(m+1));
+                                       while (m-->1){
+                                               pDst[x+m*bytes] = (BYTE)(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 = (BYTE)((pSrc[x+bytes]-pSrc[x])/(m+1));
+                                       while (m-->1){
+                                               pDst[x+m*bytes] = (BYTE)(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 = (BYTE)((pSrc[x-bytes]-pSrc[x])/(m+1));
+                                       while (m-->1){
+                                               pDst[x-m*bytes] = (BYTE)(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 = (BYTE)((pSrc[x-bytes]-pSrc[x])/(m+1));
+                                       while (m-->1){
+                                               pDst[x-m*bytes] = (BYTE)(pDst[x]+(step*(m+1)));
+                                       }
+                               }
+                       }
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \author [DP]
+ */
+bool CxImage::TextBlur(BYTE threshold, BYTE decay, BYTE max_depth, bool bBlurHorizontal, bool bBlurVertical, CxImage* iDst)
+{
+       if (!pDib) return false;
+
+       RGBQUAD* pPalette=NULL;
+       WORD 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(long y=0; y<head.biHeight; y++){
+                       for(long 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;
+       WORD 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;
+       int cmatrix_length = gen_convolve_matrix(radius, &cmatrix);
+       // generate lookup table
+       float *ctable = gen_lookup_table(cmatrix, cmatrix_length);
+
+       long x,y;
+       int 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 = (long)(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
+    BYTE* cur_col = (BYTE*)malloc(bypp*head.biHeight);
+    BYTE* dest_col = (BYTE*)malloc(bypp*head.biHeight);
+
+       dbScaler = 50.0f/head.biWidth;
+
+       for (x=0;x<head.biWidth;x++)
+       {
+               if (info.nEscape) break;
+               info.nProgress = (long)(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, BYTE threshold, CxImage* iDst)
+{
+       if (!pDib) return false;
+
+       RGBQUAD* pPalette=NULL;
+       WORD 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))
+                       return false;
+       }
+
+       CxImage Dst(Tmp, true, true, true);
+       if (!Dst.IsValid()){
+               strcpy(info.szLastError,Dst.GetLastError());
+               return false;
+       }
+
+       //build the difference mask
+       BYTE thresh_dw = (BYTE)max( 0 ,(int)(128 - threshold));
+       BYTE thresh_up = (BYTE)min(255,(int)(128 + threshold));
+       long kernel[]={-100,-100,-100,-100,801,-100,-100,-100,-100};
+       if (!Tmp.Filter(kernel,3,800,128)){
+               strcpy(info.szLastError,Tmp.GetLastError());
+               return false;
+       }
+
+       //if the image has no selection, build a selection for the whole image
+       if (!Tmp.SelectionIsValid()){
+               Tmp.SelectionCreate();
+               Tmp.SelectionClear(255);
+       }
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long 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());
+               return false;
+       }
+
+       //restore the original selection
+       Dst.SelectionCopy(*this);
+
+       //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*/, int threshold /*= 0*/)
+{
+       if (!pDib) return false;
+
+       RGBQUAD* pPalette=NULL;
+       WORD 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);
+
+       long 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);
+       int bypp = head.biBitCount>>3;
+       
+       // merge the source and destination (which currently contains
+       // the blurred version) images
+    for (long y=ymin; y<ymax; y++)
+       {
+               if (info.nEscape) break;
+               info.nProgress = (long)((y-ymin)*dbScaler);
+
+               // get source row
+               BYTE* cur_row = itSrc.GetRow(y);
+               // get dest row
+               BYTE* dest_row = itDst.GetRow(y);
+               // combine the two
+               for (long x=xmin; x<xmax; x++) {
+#if CXIMAGE_SUPPORT_SELECTION
+                       if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                       {
+                               for (long b=0, z=x*bypp; b<bypp; b++, z++){
+                                       int diff = cur_row[z] - dest_row[z];
+
+                                       // do tresholding
+                                       if (abs(diff) < threshold){
+                                               dest_row[z] = cur_row[z];
+                                       } else {
+                                               dest_row[z] = (BYTE)min(255, max(0,(int)(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: BYTE[256] look up table
+ * \return true if everything is ok
+ */
+bool CxImage::Lut(BYTE* pLut)
+{
+       if (!pDib || !pLut) return false;
+       RGBQUAD color;
+
+       double dbScaler;
+       if (head.biClrUsed==0){
+
+               long 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
+                       BYTE *iSrc=info.pImage;
+                       for(unsigned long i=0; i < head.biSizeImage ; i++){
+                               *iSrc++ = pLut[*iSrc];
+                       }
+                       return true;
+               }
+
+               if (xmin==xmax || ymin==ymax)
+                       return false;
+
+               dbScaler = 100.0/(ymax-ymin);
+
+               for(long y=ymin; y<ymax; y++){
+                       info.nProgress = (long)((y-ymin)*dbScaler); //<Anatoly Ivasyuk>
+                       for(long 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()){
+               long 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(long y=ymin; y<ymax; y++){
+                       info.nProgress = (long)((y-ymin)*dbScaler);
+                       for(long 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(DWORD j=0; j<head.biClrUsed; j++){
+                       color = GetPaletteColor((BYTE)j);
+                       color.rgbRed = pLut[color.rgbRed];
+                       color.rgbGreen = pLut[color.rgbGreen];
+                       color.rgbBlue = pLut[color.rgbBlue];
+                       SetPaletteColor((BYTE)j,color);
+               }
+               if (bIsGrayScale) GrayScale();
+       }
+       return true;
+
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Apply an indipendent look up table for each channel
+ * \param pLutR, pLutG, pLutB, pLutA: BYTE[256] look up tables
+ * \return true if everything is ok
+ */
+bool CxImage::Lut(BYTE* pLutR, BYTE* pLutG, BYTE* pLutB, BYTE* pLutA)
+{
+       if (!pDib || !pLutR || !pLutG || !pLutB) return false;
+       RGBQUAD color;
+
+       double dbScaler;
+       if (head.biClrUsed==0){
+
+               long 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(long y=ymin; y<ymax; y++){
+                       info.nProgress = (long)((y-ymin)*dbScaler);
+                       for(long 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(DWORD j=0; j<head.biClrUsed; j++){
+                       color = GetPaletteColor((BYTE)j);
+                       color.rgbRed =   pLutR[color.rgbRed];
+                       color.rgbGreen = pLutG[color.rgbGreen];
+                       color.rgbBlue =  pLutB[color.rgbBlue];
+                       SetPaletteColor((BYTE)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;
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long 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 = (BYTE)(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 long saturation, const long colorspace)
+{
+       if (!pDib)
+               return false;
+
+       long 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;
+
+       BYTE cTable[256];
+
+       switch(colorspace)
+       {
+       case 1:
+               {
+                       for (int i=0;i<256;i++) {
+                               cTable[i] = (BYTE)max(0,min(255,(int)(i + saturation)));
+                       }
+                       for(long y=ymin; y<ymax; y++){
+                               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+                               if (info.nEscape) break;
+                               for(long 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 (int i=0;i<256;i++) {
+                               cTable[i] = (BYTE)max(0,min(255,(int)((i-128)*(100 + saturation)/100.0f + 128.5f)));
+                       }
+                       for(long y=ymin; y<ymax; y++){
+                               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+                               if (info.nEscape) break;
+                               for(long 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(BYTE level, bool bLinkedChannels)
+{
+       if (!pDib) return false;
+
+       long 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(long y=ymin; y<ymax; y++){
+                               for(long x=xmin; x<xmax; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+                                       if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                                       {
+                                               BYTE index = BlindGetPixelIndex(x,y);
+                                               RGBQUAD color = GetPaletteColor(index);
+                                               if ((BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)>level){
+                                                       BlindSetPixelIndex(x,y,255-index);
+                                               }
+                                       }
+                               }
+                       }
+               } else { //PALETTE, full image
+                       RGBQUAD* ppal=GetPalette();
+                       for(DWORD i=0;i<head.biClrUsed;i++){
+                               RGBQUAD color = GetPaletteColor((BYTE)i);
+                               if (bLinkedChannels){
+                                       if ((BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)>level){
+                                               ppal[i].rgbBlue =(BYTE)(255-ppal[i].rgbBlue);
+                                               ppal[i].rgbGreen =(BYTE)(255-ppal[i].rgbGreen);
+                                               ppal[i].rgbRed =(BYTE)(255-ppal[i].rgbRed);
+                                       }
+                               } else {
+                                       if (color.rgbBlue>level)        ppal[i].rgbBlue =(BYTE)(255-ppal[i].rgbBlue);
+                                       if (color.rgbGreen>level)       ppal[i].rgbGreen =(BYTE)(255-ppal[i].rgbGreen);
+                                       if (color.rgbRed>level)         ppal[i].rgbRed =(BYTE)(255-ppal[i].rgbRed);
+                               }
+                       }
+               }
+       } else { //RGB, selection
+               for(long y=ymin; y<ymax; y++){
+                       for(long 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 ((BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)>level){
+                                                       color.rgbRed = (BYTE)(255-color.rgbRed);
+                                                       color.rgbGreen = (BYTE)(255-color.rgbGreen);
+                                                       color.rgbBlue = (BYTE)(255-color.rgbBlue);
+                                               }
+                                       } else {
+                                               if (color.rgbBlue>level)        color.rgbBlue =(BYTE)(255-color.rgbBlue);
+                                               if (color.rgbGreen>level)       color.rgbGreen =(BYTE)(255-color.rgbGreen);
+                                               if (color.rgbRed>level)         color.rgbRed =(BYTE)(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 ((BYTE)RGB2GRAY(info.nBkgndColor.rgbRed,info.nBkgndColor.rgbGreen,info.nBkgndColor.rgbBlue)>level){
+                               info.nBkgndColor.rgbBlue = (BYTE)(255-info.nBkgndColor.rgbBlue);
+                               info.nBkgndColor.rgbGreen = (BYTE)(255-info.nBkgndColor.rgbGreen);
+                               info.nBkgndColor.rgbRed = (BYTE)(255-info.nBkgndColor.rgbRed);
+                       } 
+               } else {
+                       if (info.nBkgndColor.rgbBlue>level)      info.nBkgndColor.rgbBlue = (BYTE)(255-info.nBkgndColor.rgbBlue);
+                       if (info.nBkgndColor.rgbGreen>level) info.nBkgndColor.rgbGreen = (BYTE)(255-info.nBkgndColor.rgbGreen);
+                       if (info.nBkgndColor.rgbRed>level)       info.nBkgndColor.rgbRed = (BYTE)(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 long dstColorSpace, const long srcColorSpace)
+{
+       if (!pDib)
+               return false;
+
+       if (dstColorSpace == srcColorSpace)
+               return true;
+
+       long w = GetWidth();
+       long h = GetHeight();
+
+       for (long y=0;y<h;y++){
+               info.nProgress = (long)(100*y/h);
+               if (info.nEscape) break;
+               for (long 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();
+ *   long edge[]={-1,-1,-1,-1,8,-1,-1,-1,-1};
+ *   iContrastMask.Filter(edge,3,1,0);
+ *   long blur[]={1,1,1,1,1,1,1,1,1};
+ *   iContrastMask.Filter(blur,3,9,0);
+ * \return optimal threshold; -1 = error.
+ * \sa AdaptiveThreshold
+ */
+int  CxImage::OptimalThreshold(long 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;
+               }
+       }
+
+       long 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 (long y = ymin; y<ymax; y++){
+               BYTE* pGray = GetBits(y) + xmin;
+               BYTE* pContr = 0;
+               if (pContrastMask) pContr = pContrastMask->GetBits(y) + xmin;
+               for (long x = xmin; x<xmax; x++){
+                       BYTE n = *pGray++;
+                       if (pContr){
+                               if (*pContr) p[n]++;
+                               pContr++;
+                       } else {
+                               p[n]++;
+                       }
+               }
+       }
+
+       //find histogram limits
+       int gray_min = 0;
+       while (gray_min<255 && p[gray_min]==0) gray_min++;
+       int 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
+       int 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
+       int 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;
+               }
+       }
+
+       int 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
+               {
+                       int 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(long method, long nBoxSize, CxImage* pContrastMask, long 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;
+
+       long mw = (head.biWidth + nBoxSize - 1)/nBoxSize;
+       long mh = (head.biHeight + nBoxSize - 1)/nBoxSize;
+
+       CxImage mask(mw,mh,8);
+       if(!mask.GrayScale())
+               return false;
+
+       if(!GrayScale())
+               return false;
+
+       int globalthreshold = OptimalThreshold(method, 0, pContrastMask);
+       if (globalthreshold <0)
+               return false;
+
+       for (long y=0; y<mh; y++){
+               for (long x=0; x<mw; x++){
+                       info.nProgress = (long)(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;
+                       int threshold = OptimalThreshold(method, &r, pContrastMask);
+                       if (threshold <0) return false;
+                       mask.SetPixelIndex(x,y,(BYTE)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;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#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 long xStart, const long yStart, const RGBQUAD cFillColor, const BYTE nTolerance,
+                                               BYTE nOpacity, const bool bSelectFilledArea, const BYTE 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;
+       WORD 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;
+       }
+
+       BYTE* pFillMask = (BYTE*)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
+               BYTE idxRef = GetPixelIndex(xStart,yStart);
+               BYTE idxFill = GetNearestIndex(cFillColor);
+               BYTE idxMin = (BYTE)min(255, max(0,(int)(idxRef - nTolerance)));
+               BYTE idxMax = (BYTE)min(255, max(0,(int)(idxRef + nTolerance)));
+
+               while(!q.empty())
+               {
+                       point = q.front();
+                       q.pop();
+
+                       for (int z=0; z<4; z++){
+                               int x = point.x + offset[z].x;
+                               int y = point.y + offset[z].y;
+                               if(IsInside(x,y)){
+#if CXIMAGE_SUPPORT_SELECTION
+                                 if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                                 {
+                                       BYTE idx = BlindGetPixelIndex(x, y);
+                                       BYTE* 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, (BYTE)((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   = (BYTE)min(255, max(0,(int)(cRef.rgbRed   - nTolerance)));
+               cRefMin.rgbGreen = (BYTE)min(255, max(0,(int)(cRef.rgbGreen - nTolerance)));
+               cRefMin.rgbBlue  = (BYTE)min(255, max(0,(int)(cRef.rgbBlue  - nTolerance)));
+               cRefMax.rgbRed   = (BYTE)min(255, max(0,(int)(cRef.rgbRed   + nTolerance)));
+               cRefMax.rgbGreen = (BYTE)min(255, max(0,(int)(cRef.rgbGreen + nTolerance)));
+               cRefMax.rgbBlue  = (BYTE)min(255, max(0,(int)(cRef.rgbBlue  + nTolerance)));
+
+               while(!q.empty())
+               {
+                       point = q.front();
+                       q.pop();
+
+                       for (int z=0; z<4; z++){
+                               int x = point.x + offset[z].x;
+                               int 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);
+                                       BYTE* 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   = (BYTE)((cFillColor.rgbRed   * nOpacity + cc.rgbRed   * (255-nOpacity))>>8);
+                                                               cc.rgbGreen = (BYTE)((cFillColor.rgbGreen * nOpacity + cc.rgbGreen * (255-nOpacity))>>8);
+                                                               cc.rgbBlue  = (BYTE)((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   = (BYTE)((cFillColor.rgbRed   * nOpacity + cc.rgbRed   * (255-nOpacity))>>8);
+                       cc.rgbGreen = (BYTE)((cFillColor.rgbGreen * nOpacity + cc.rgbGreen * (255-nOpacity))>>8);
+                       cc.rgbBlue  = (BYTE)((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 (long y = r.bottom; y < r.top; y++){
+                       BYTE* pFill = pFillMask + r.left + y * head.biWidth;
+                       for (long x = r.left; x<r.right; x++){
+                               if (*pFill)     SelectionSet(x,y,nSelectionLevel);
+                               pFill++;
+                       }
+               }
+               SelectionRebuildBox();
+       }
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+       free(pFillMask);
+
+       return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DSP
index d7ef4fea081583f17babfe1d5aa4e4408d1b335b..8edfbfcd6d5521a681372eb67203a91b26f9d4a5 100644 (file)
-// xImaCodec.cpp : Encode Decode functions\r
-/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_JPG\r
-#include "ximajpg.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_GIF\r
-#include "ximagif.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_PNG\r
-#include "ximapng.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_MNG\r
-#include "ximamng.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_BMP\r
-#include "ximabmp.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_ICO\r
-#include "ximaico.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_TIF\r
-#include "ximatif.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_TGA\r
-#include "ximatga.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_PCX\r
-#include "ximapcx.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_WBMP\r
-#include "ximawbmp.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_WMF\r
-#include "ximawmf.h" // <vho> - WMF/EMF support\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_JBG\r
-#include "ximajbg.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_JASPER\r
-#include "ximajas.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_SKA\r
-#include "ximaska.h"\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_RAW\r
-#include "ximaraw.h"\r
-#endif\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::EncodeSafeCheck(CxFile *hFile)\r
-{\r
-       if (hFile==NULL) {\r
-               strcpy(info.szLastError,CXIMAGE_ERR_NOFILE);\r
-               return true;\r
-       }\r
-\r
-       if (pDib==NULL){\r
-               strcpy(info.szLastError,CXIMAGE_ERR_NOIMAGE);\r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-//#ifdef WIN32\r
-//bool CxImage::Save(LPCWSTR filename, DWORD imagetype)\r
-//{\r
-//     FILE* hFile;    //file handle to write the image\r
-//     if ((hFile=_wfopen(filename,L"wb"))==NULL)  return false;\r
-//     bool bOK = Encode(hFile,imagetype);\r
-//     fclose(hFile);\r
-//     return bOK;\r
-//}\r
-//#endif //WIN32\r
-////////////////////////////////////////////////////////////////////////////////\r
-// For UNICODE support: char -> TCHAR\r
-/**\r
- * Saves to disk the image in a specific format.\r
- * \param filename: file name\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Save(const TCHAR * filename, DWORD imagetype)\r
-{\r
-       FILE* hFile;    //file handle to write the image\r
-\r
-#ifdef WIN32\r
-       if ((hFile=_tfopen(filename,_T("wb")))==NULL)  return false;    // For UNICODE support\r
-#else\r
-       if ((hFile=fopen(filename,"wb"))==NULL)  return false;\r
-#endif\r
-\r
-       bool bOK = Encode(hFile,imagetype);\r
-       fclose(hFile);\r
-       return bOK;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Saves to disk the image in a specific format.\r
- * \param hFile: file handle, open and enabled for writing.\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Encode(FILE *hFile, DWORD imagetype)\r
-{\r
-       CxIOFile file(hFile);\r
-       return Encode(&file,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Saves to memory buffer the image in a specific format.\r
- * \param buffer: output memory buffer pointer. Must be NULL,\r
- * the function allocates and fill the memory,\r
- * the application must free the buffer, see also FreeMemory().\r
- * \param size: output memory buffer size.\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Encode(BYTE * &buffer, long &size, DWORD imagetype)\r
-{\r
-       if (buffer!=NULL){\r
-               strcpy(info.szLastError,"the buffer must be empty");\r
-               return false;\r
-       }\r
-       CxMemFile file;\r
-       file.Open();\r
-       if(Encode(&file,imagetype)){\r
-               buffer=file.GetBuffer();\r
-               size=file.Size();\r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Saves to disk the image in a specific format.\r
- * \param hFile: file handle (CxMemFile or CxIOFile), with write access.\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- * \return true if everything is ok\r
- * \sa ENUM_CXIMAGE_FORMATS\r
- */\r
-bool CxImage::Encode(CxFile *hFile, DWORD imagetype)\r
-{\r
-\r
-#if CXIMAGE_SUPPORT_BMP\r
-\r
-       if (imagetype==CXIMAGE_FORMAT_BMP){\r
-               CxImageBMP newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_ICO\r
-       if (imagetype==CXIMAGE_FORMAT_ICO){\r
-               CxImageICO newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_TIF\r
-       if (imagetype==CXIMAGE_FORMAT_TIF){\r
-               CxImageTIF newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPG\r
-       if (imagetype==CXIMAGE_FORMAT_JPG){\r
-               CxImageJPG newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_GIF\r
-       if (imagetype==CXIMAGE_FORMAT_GIF){\r
-               CxImageGIF newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNG\r
-       if (imagetype==CXIMAGE_FORMAT_PNG){\r
-               CxImagePNG newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_MNG\r
-       if (imagetype==CXIMAGE_FORMAT_MNG){\r
-               CxImageMNG newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_TGA\r
-       if (imagetype==CXIMAGE_FORMAT_TGA){\r
-               CxImageTGA newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_PCX\r
-       if (imagetype==CXIMAGE_FORMAT_PCX){\r
-               CxImagePCX newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_WBMP\r
-       if (imagetype==CXIMAGE_FORMAT_WBMP){\r
-               CxImageWBMP newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // <vho> - WMF/EMF support\r
-       if (imagetype==CXIMAGE_FORMAT_WMF){\r
-               CxImageWMF newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_JBG\r
-       if (imagetype==CXIMAGE_FORMAT_JBG){\r
-               CxImageJBG newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_JASPER\r
-       if (\r
- #if   CXIMAGE_SUPPORT_JP2\r
-               imagetype==CXIMAGE_FORMAT_JP2 || \r
- #endif\r
- #if   CXIMAGE_SUPPORT_JPC\r
-               imagetype==CXIMAGE_FORMAT_JPC || \r
- #endif\r
- #if   CXIMAGE_SUPPORT_PGX\r
-               imagetype==CXIMAGE_FORMAT_PGX || \r
- #endif\r
- #if   CXIMAGE_SUPPORT_PNM\r
-               imagetype==CXIMAGE_FORMAT_PNM || \r
- #endif\r
- #if   CXIMAGE_SUPPORT_RAS\r
-               imagetype==CXIMAGE_FORMAT_RAS || \r
- #endif\r
-                false ){\r
-               CxImageJAS newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile,imagetype)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_SKA\r
-       if (imagetype==CXIMAGE_FORMAT_SKA){\r
-               CxImageSKA newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_RAW\r
-       if (imagetype==CXIMAGE_FORMAT_RAW){\r
-               CxImageRAW newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-\r
-       strcpy(info.szLastError,"Encode: Unknown format");\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Saves to disk or memory pagecount images, referenced by an array of CxImage pointers.\r
- * \param hFile: file handle.\r
- * \param pImages: array of CxImage pointers.\r
- * \param pagecount: number of images.\r
- * \param imagetype: can be CXIMAGE_FORMAT_TIF or CXIMAGE_FORMAT_GIF.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Encode(FILE * hFile, CxImage ** pImages, int pagecount, DWORD imagetype)\r
-{\r
-       CxIOFile file(hFile);\r
-       return Encode(&file, pImages, pagecount,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Saves to disk or memory pagecount images, referenced by an array of CxImage pointers.\r
- * \param hFile: file handle (CxMemFile or CxIOFile), with write access.\r
- * \param pImages: array of CxImage pointers.\r
- * \param pagecount: number of images.\r
- * \param imagetype: can be CXIMAGE_FORMAT_TIF, CXIMAGE_FORMAT_GIF or CXIMAGE_FORMAT_ICO.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Encode(CxFile * hFile, CxImage ** pImages, int pagecount, DWORD imagetype)\r
-{\r
-#if CXIMAGE_SUPPORT_TIF\r
-       if (imagetype==CXIMAGE_FORMAT_TIF){\r
-               CxImageTIF newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile,pImages,pagecount)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_GIF\r
-       if (imagetype==CXIMAGE_FORMAT_GIF){\r
-               CxImageGIF newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile,pImages,pagecount)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_ICO\r
-       if (imagetype==CXIMAGE_FORMAT_ICO){\r
-               CxImageICO newima;\r
-               newima.Ghost(this);\r
-               if (newima.Encode(hFile,pImages,pagecount)){\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-       strcpy(info.szLastError,"Multipage Encode, Unsupported operation for this format");\r
-       return false;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * exports the image into a RGBA buffer, Useful for OpenGL applications.\r
- * \param buffer: output memory buffer pointer. Must be NULL,\r
- * the function allocates and fill the memory,\r
- * the application must free the buffer, see also FreeMemory().\r
- * \param size: output memory buffer size.\r
- * \param bFlipY: direction of Y axis. default = false.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Encode2RGBA(BYTE * &buffer, long &size, bool bFlipY)\r
-{\r
-       if (buffer!=NULL){\r
-               strcpy(info.szLastError,"the buffer must be empty");\r
-               return false;\r
-       }\r
-       CxMemFile file;\r
-       file.Open();\r
-       if(Encode2RGBA(&file,bFlipY)){\r
-               buffer=file.GetBuffer();\r
-               size=file.Size();\r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * exports the image into a RGBA buffer, Useful for OpenGL applications.\r
- * \param hFile: file handle (CxMemFile or CxIOFile), with write access.\r
- * \param bFlipY: direction of Y axis. default = false.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Encode2RGBA(CxFile *hFile, bool bFlipY)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       for (long y1 = 0; y1 < head.biHeight; y1++) {\r
-               long y = bFlipY ? head.biHeight - 1 - y1 : y1;\r
-               for(long x = 0; x < head.biWidth; x++) {\r
-                       RGBQUAD color = BlindGetPixelColor(x,y);\r
-                       hFile->PutC(color.rgbRed);\r
-                       hFile->PutC(color.rgbGreen);\r
-                       hFile->PutC(color.rgbBlue);\r
-                       hFile->PutC(color.rgbReserved);\r
-               }\r
-       }\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-// For UNICODE support: char -> TCHAR\r
-/**\r
- * Reads from disk the image in a specific format.\r
- * - If decoding fails using the specified image format,\r
- * the function will try the automatic file format recognition.\r
- *\r
- * \param filename: file name\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Load(const TCHAR * filename, DWORD imagetype)\r
-//bool CxImage::Load(const char * filename, DWORD imagetype)\r
-{\r
-       /*FILE* hFile;  //file handle to read the image\r
-       if ((hFile=fopen(filename,"rb"))==NULL)  return false;\r
-       bool bOK = Decode(hFile,imagetype);\r
-       fclose(hFile);*/\r
-\r
-       /* automatic file type recognition */\r
-       bool bOK = false;\r
-       if ( GetTypeIndexFromId(imagetype) ){\r
-               FILE* hFile;    //file handle to read the image\r
-\r
-#ifdef WIN32\r
-               if ((hFile=_tfopen(filename,_T("rb")))==NULL)  return false;    // For UNICODE support\r
-#else\r
-               if ((hFile=fopen(filename,"rb"))==NULL)  return false;\r
-#endif\r
-\r
-               bOK = Decode(hFile,imagetype);\r
-               fclose(hFile);\r
-               if (bOK) return bOK;\r
-       }\r
-\r
-       char szError[256];\r
-       strcpy(szError,info.szLastError); //save the first error\r
-\r
-       // if failed, try automatic recognition of the file...\r
-       FILE* hFile;\r
-\r
-#ifdef WIN32\r
-       if ((hFile=_tfopen(filename,_T("rb")))==NULL)  return false;    // For UNICODE support\r
-#else\r
-       if ((hFile=fopen(filename,"rb"))==NULL)  return false;\r
-#endif\r
-\r
-       bOK = Decode(hFile,CXIMAGE_FORMAT_UNKNOWN);\r
-       fclose(hFile);\r
-\r
-       if (!bOK && imagetype > 0) strcpy(info.szLastError,szError); //restore the first error\r
-\r
-       return bOK;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#ifdef WIN32\r
-//bool CxImage::Load(LPCWSTR filename, DWORD imagetype)\r
-//{\r
-//     /*FILE* hFile;  //file handle to read the image\r
-//     if ((hFile=_wfopen(filename, L"rb"))==NULL)  return false;\r
-//     bool bOK = Decode(hFile,imagetype);\r
-//     fclose(hFile);*/\r
-//\r
-//     /* automatic file type recognition */\r
-//     bool bOK = false;\r
-//     if ( GetTypeIndexFromId(imagetype) ){\r
-//             FILE* hFile;    //file handle to read the image\r
-//             if ((hFile=_wfopen(filename,L"rb"))==NULL)  return false;\r
-//             bOK = Decode(hFile,imagetype);\r
-//             fclose(hFile);\r
-//             if (bOK) return bOK;\r
-//     }\r
-//\r
-//     char szError[256];\r
-//     strcpy(szError,info.szLastError); //save the first error\r
-//\r
-//     // if failed, try automatic recognition of the file...\r
-//     FILE* hFile;    //file handle to read the image\r
-//     if ((hFile=_wfopen(filename,L"rb"))==NULL)  return false;\r
-//     bOK = Decode(hFile,CXIMAGE_FORMAT_UNKNOWN);\r
-//     fclose(hFile);\r
-//\r
-//     if (!bOK && imagetype > 0) strcpy(info.szLastError,szError); //restore the first error\r
-//\r
-//     return bOK;\r
-//}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Loads an image from the application resources.\r
- * \param hRes: the resource handle returned by FindResource().\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS.\r
- * \param hModule: NULL for internal resource, or external application/DLL hinstance returned by LoadLibray.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::LoadResource(HRSRC hRes, DWORD imagetype, HMODULE hModule)\r
-{\r
-       DWORD rsize=SizeofResource(hModule,hRes);\r
-       HGLOBAL hMem=::LoadResource(hModule,hRes);\r
-       if (hMem){\r
-               char* lpVoid=(char*)LockResource(hMem);\r
-               if (lpVoid){\r
-                       // FILE* fTmp=tmpfile(); doesn't work with network\r
-                       /*char tmpPath[MAX_PATH] = {0};\r
-                       char tmpFile[MAX_PATH] = {0};\r
-                       GetTempPath(MAX_PATH,tmpPath);\r
-                       GetTempFileName(tmpPath,"IMG",0,tmpFile);\r
-                       FILE* fTmp=fopen(tmpFile,"w+b");\r
-                       if (fTmp){\r
-                               fwrite(lpVoid,rsize,1,fTmp);\r
-                               fseek(fTmp,0,SEEK_SET);\r
-                               bool bOK = Decode(fTmp,imagetype);\r
-                               fclose(fTmp);\r
-                               DeleteFile(tmpFile);\r
-                               return bOK;\r
-                       }*/\r
-\r
-                       CxMemFile fTmp((BYTE*)lpVoid,rsize);\r
-                       return Decode(&fTmp,imagetype);\r
-               }\r
-       } else strcpy(info.szLastError,"Unable to load resource!");\r
-       return false;\r
-}\r
-#endif //WIN32\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Constructor from file name, see Load()\r
- * \param filename: file name\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- */\r
-// \r
-// > filename: file name\r
-// > imagetype: specify the image format (CXIMAGE_FORMAT_BMP,...)\r
-// For UNICODE support: char -> TCHAR\r
-CxImage::CxImage(const TCHAR * filename, DWORD imagetype)\r
-//CxImage::CxImage(const char * filename, DWORD imagetype)\r
-{\r
-       Startup(imagetype);\r
-       Load(filename,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Constructor from file handle, see Decode()\r
- * \param stream: file handle, with read access.\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- */\r
-CxImage::CxImage(FILE * stream, DWORD imagetype)\r
-{\r
-       Startup(imagetype);\r
-       Decode(stream,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Constructor from CxFile object, see Decode()\r
- * \param stream: file handle (CxMemFile or CxIOFile), with read access.\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- */\r
-CxImage::CxImage(CxFile * stream, DWORD imagetype)\r
-{\r
-       Startup(imagetype);\r
-       Decode(stream,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Constructor from memory buffer, see Decode()\r
- * \param buffer: memory buffer\r
- * \param size: size of buffer\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- */\r
-CxImage::CxImage(BYTE * buffer, DWORD size, DWORD imagetype)\r
-{\r
-       Startup(imagetype);\r
-       CxMemFile stream(buffer,size);\r
-       Decode(&stream,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Loads an image from memory buffer\r
- * \param buffer: memory buffer\r
- * \param size: size of buffer\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Decode(BYTE * buffer, DWORD size, DWORD imagetype)\r
-{\r
-       CxMemFile file(buffer,size);\r
-       return Decode(&file,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Loads an image from file handle.\r
- * \param hFile: file handle, with read access.\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Decode(FILE *hFile, DWORD imagetype)\r
-{\r
-       CxIOFile file(hFile);\r
-       return Decode(&file,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Loads an image from CxFile object\r
- * \param hFile: file handle (CxMemFile or CxIOFile), with read access.\r
- * \param imagetype: file format, see ENUM_CXIMAGE_FORMATS\r
- * \return true if everything is ok\r
- * \sa ENUM_CXIMAGE_FORMATS\r
- */\r
-bool CxImage::Decode(CxFile *hFile, DWORD imagetype)\r
-{\r
-       if (hFile == NULL){\r
-               strcpy(info.szLastError,CXIMAGE_ERR_NOFILE);\r
-               return false;\r
-       }\r
-\r
-       if (imagetype==CXIMAGE_FORMAT_UNKNOWN){\r
-               DWORD pos = hFile->Tell();\r
-#if CXIMAGE_SUPPORT_BMP\r
-               { CxImageBMP newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPG\r
-               { CxImageJPG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_ICO\r
-               { CxImageICO newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_GIF\r
-               { CxImageGIF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNG\r
-               { CxImagePNG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_TIF\r
-               { CxImageTIF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_MNG\r
-               { CxImageMNG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_TGA\r
-               { CxImageTGA newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_PCX\r
-               { CxImagePCX newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_WBMP\r
-               { CxImageWBMP newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS\r
-               { CxImageWMF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_JBG\r
-               { CxImageJBG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_JASPER\r
-               { CxImageJAS newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_SKA\r
-               { CxImageSKA newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAW\r
-               { CxImageRAW newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }\r
-#endif\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_BMP\r
-       if (imagetype==CXIMAGE_FORMAT_BMP){\r
-               CxImageBMP newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPG\r
-       if (imagetype==CXIMAGE_FORMAT_JPG){\r
-               CxImageJPG newima;\r
-               newima.CopyInfo(*this); // <ignacio>\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_ICO\r
-       if (imagetype==CXIMAGE_FORMAT_ICO){\r
-               CxImageICO newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       info.nNumFrames = newima.info.nNumFrames;\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_GIF\r
-       if (imagetype==CXIMAGE_FORMAT_GIF){\r
-               CxImageGIF newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       info.nNumFrames = newima.info.nNumFrames;\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNG\r
-       if (imagetype==CXIMAGE_FORMAT_PNG){\r
-               CxImagePNG newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_TIF\r
-       if (imagetype==CXIMAGE_FORMAT_TIF){\r
-               CxImageTIF newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       info.nNumFrames = newima.info.nNumFrames;\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_MNG\r
-       if (imagetype==CXIMAGE_FORMAT_MNG){\r
-               CxImageMNG newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       info.nNumFrames = newima.info.nNumFrames;\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_TGA\r
-       if (imagetype==CXIMAGE_FORMAT_TGA){\r
-               CxImageTGA newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_PCX\r
-       if (imagetype==CXIMAGE_FORMAT_PCX){\r
-               CxImagePCX newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_WBMP\r
-       if (imagetype==CXIMAGE_FORMAT_WBMP){\r
-               CxImageWBMP newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // vho - WMF support\r
-       if (imagetype == CXIMAGE_FORMAT_WMF){\r
-               CxImageWMF newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_JBG\r
-       if (imagetype==CXIMAGE_FORMAT_JBG){\r
-               CxImageJBG newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_JASPER\r
-       if (\r
- #if   CXIMAGE_SUPPORT_JP2\r
-               imagetype==CXIMAGE_FORMAT_JP2 || \r
- #endif\r
- #if   CXIMAGE_SUPPORT_JPC\r
-               imagetype==CXIMAGE_FORMAT_JPC || \r
- #endif\r
- #if   CXIMAGE_SUPPORT_PGX\r
-               imagetype==CXIMAGE_FORMAT_PGX || \r
- #endif\r
- #if   CXIMAGE_SUPPORT_PNM\r
-               imagetype==CXIMAGE_FORMAT_PNM || \r
- #endif\r
- #if   CXIMAGE_SUPPORT_RAS\r
-               imagetype==CXIMAGE_FORMAT_RAS || \r
- #endif\r
-                false ){\r
-               CxImageJAS newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile,imagetype)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-#if CXIMAGE_SUPPORT_SKA\r
-       if (imagetype==CXIMAGE_FORMAT_SKA){\r
-               CxImageSKA newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_RAW\r
-       if (imagetype==CXIMAGE_FORMAT_RAW){\r
-               CxImageRAW newima;\r
-               newima.CopyInfo(*this);\r
-               if (newima.Decode(hFile)){\r
-                       Transfer(newima);\r
-                       return true;\r
-               } else {\r
-                       strcpy(info.szLastError,newima.GetLastError());\r
-                       return false;\r
-               }\r
-       }\r
-#endif\r
-\r
-       strcpy(info.szLastError,"Decode: Unknown or wrong format");\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Loads an image from CxFile object\r
- * \param hFile: file handle (CxMemFile or CxIOFile), with read access.\r
- * \param imagetype: file format, default = 0 (CXIMAGE_FORMAT_UNKNOWN)\r
- * \return : if imagetype is not 0, the function returns true when imagetype\r
- *  matches the file image format. If imagetype is 0, the function returns true\r
- *  when the file image format is recognized as a supported format.\r
- *  If the returned value is true, use GetHeight(), GetWidth() or GetType()\r
- *  to retrieve the basic image information.\r
- * \sa ENUM_CXIMAGE_FORMATS\r
- */\r
-bool CxImage::CheckFormat(CxFile * hFile, DWORD imagetype)\r
-{\r
-       SetType(CXIMAGE_FORMAT_UNKNOWN);\r
-       SetEscape(-1);\r
-\r
-       if (!Decode(hFile,imagetype))\r
-               return false;\r
-\r
-       if (GetType() == CXIMAGE_FORMAT_UNKNOWN || GetType() != imagetype)\r
-               return false;\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::CheckFormat(BYTE * buffer, DWORD size, DWORD imagetype)\r
-{\r
-       if (buffer==NULL || size==NULL){\r
-               strcpy(info.szLastError,"invalid or empty buffer");\r
-               return false;\r
-       }\r
-       CxMemFile file(buffer,size);\r
-       return CheckFormat(&file,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
+// xImaCodec.cpp : Encode Decode functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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_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, DWORD 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, DWORD 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, DWORD 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(BYTE * &buffer, long &size, DWORD 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, DWORD imagetype)
+{
+
+#if CXIMAGE_SUPPORT_BMP
+
+       if (imagetype==CXIMAGE_FORMAT_BMP){
+               CxImageBMP newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       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)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_TIF
+       if (imagetype==CXIMAGE_FORMAT_TIF){
+               CxImageTIF newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_JPG
+       if (imagetype==CXIMAGE_FORMAT_JPG){
+               CxImageJPG newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       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)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_PNG
+       if (imagetype==CXIMAGE_FORMAT_PNG){
+               CxImagePNG newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_MNG
+       if (imagetype==CXIMAGE_FORMAT_MNG){
+               CxImageMNG newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_TGA
+       if (imagetype==CXIMAGE_FORMAT_TGA){
+               CxImageTGA newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_PCX
+       if (imagetype==CXIMAGE_FORMAT_PCX){
+               CxImagePCX newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+       if (imagetype==CXIMAGE_FORMAT_WBMP){
+               CxImageWBMP newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // <vho> - WMF/EMF support
+       if (imagetype==CXIMAGE_FORMAT_WMF){
+               CxImageWMF newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_JBG
+       if (imagetype==CXIMAGE_FORMAT_JBG){
+               CxImageJBG newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_JASPER
+       if (
+ #if   CXIMAGE_SUPPORT_JP2
+               imagetype==CXIMAGE_FORMAT_JP2 || 
+ #endif
+ #if   CXIMAGE_SUPPORT_JPC
+               imagetype==CXIMAGE_FORMAT_JPC || 
+ #endif
+ #if   CXIMAGE_SUPPORT_PGX
+               imagetype==CXIMAGE_FORMAT_PGX || 
+ #endif
+ #if   CXIMAGE_SUPPORT_PNM
+               imagetype==CXIMAGE_FORMAT_PNM || 
+ #endif
+ #if   CXIMAGE_SUPPORT_RAS
+               imagetype==CXIMAGE_FORMAT_RAS || 
+ #endif
+                false ){
+               CxImageJAS newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile,imagetype)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+
+#if CXIMAGE_SUPPORT_SKA
+       if (imagetype==CXIMAGE_FORMAT_SKA){
+               CxImageSKA newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+
+#if CXIMAGE_SUPPORT_RAW
+       if (imagetype==CXIMAGE_FORMAT_RAW){
+               CxImageRAW newima;
+               newima.Ghost(this);
+               if (newima.Encode(hFile)){
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       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, int pagecount, DWORD 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, int pagecount, DWORD 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(BYTE * &buffer, long &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 (long y1 = 0; y1 < head.biHeight; y1++) {
+               long y = bFlipY ? head.biHeight - 1 - y1 : y1;
+               for(long 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, DWORD imagetype)
+//bool CxImage::Load(const char * filename, DWORD 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, DWORD 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, DWORD imagetype, HMODULE hModule)
+{
+       DWORD 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((BYTE*)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, DWORD imagetype)
+//CxImage::CxImage(const char * filename, DWORD 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, DWORD 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, DWORD 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(BYTE * buffer, DWORD size, DWORD 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(BYTE * buffer, DWORD size, DWORD 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, DWORD 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, DWORD imagetype)
+{
+       if (hFile == NULL){
+               strcpy(info.szLastError,CXIMAGE_ERR_NOFILE);
+               return false;
+       }
+
+       if (imagetype==CXIMAGE_FORMAT_UNKNOWN){
+               DWORD pos = hFile->Tell();
+#if CXIMAGE_SUPPORT_BMP
+               { CxImageBMP newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_JPG
+               { CxImageJPG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_ICO
+               { CxImageICO newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_GIF
+               { CxImageGIF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_PNG
+               { CxImagePNG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_TIF
+               { CxImageTIF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_MNG
+               { CxImageMNG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_TGA
+               { CxImageTGA newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_PCX
+               { CxImagePCX newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+               { CxImageWBMP newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS
+               { CxImageWMF newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_JBG
+               { CxImageJBG newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_JASPER
+               { CxImageJAS newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_SKA
+               { CxImageSKA newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+#if CXIMAGE_SUPPORT_RAW
+               { CxImageRAW newima; newima.CopyInfo(*this); if (newima.Decode(hFile)) { Transfer(newima); return true; } else hFile->Seek(pos,SEEK_SET); }
+#endif
+       }
+
+#if CXIMAGE_SUPPORT_BMP
+       if (imagetype==CXIMAGE_FORMAT_BMP){
+               CxImageBMP newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_JPG
+       if (imagetype==CXIMAGE_FORMAT_JPG){
+               CxImageJPG newima;
+               newima.CopyInfo(*this); // <ignacio>
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_ICO
+       if (imagetype==CXIMAGE_FORMAT_ICO){
+               CxImageICO newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       info.nNumFrames = newima.info.nNumFrames;
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_GIF
+       if (imagetype==CXIMAGE_FORMAT_GIF){
+               CxImageGIF newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       info.nNumFrames = newima.info.nNumFrames;
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_PNG
+       if (imagetype==CXIMAGE_FORMAT_PNG){
+               CxImagePNG newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_TIF
+       if (imagetype==CXIMAGE_FORMAT_TIF){
+               CxImageTIF newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       info.nNumFrames = newima.info.nNumFrames;
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_MNG
+       if (imagetype==CXIMAGE_FORMAT_MNG){
+               CxImageMNG newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       info.nNumFrames = newima.info.nNumFrames;
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_TGA
+       if (imagetype==CXIMAGE_FORMAT_TGA){
+               CxImageTGA newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_PCX
+       if (imagetype==CXIMAGE_FORMAT_PCX){
+               CxImagePCX newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+       if (imagetype==CXIMAGE_FORMAT_WBMP){
+               CxImageWBMP newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS // vho - WMF support
+       if (imagetype == CXIMAGE_FORMAT_WMF){
+               CxImageWMF newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_JBG
+       if (imagetype==CXIMAGE_FORMAT_JBG){
+               CxImageJBG newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_JASPER
+       if (
+ #if   CXIMAGE_SUPPORT_JP2
+               imagetype==CXIMAGE_FORMAT_JP2 || 
+ #endif
+ #if   CXIMAGE_SUPPORT_JPC
+               imagetype==CXIMAGE_FORMAT_JPC || 
+ #endif
+ #if   CXIMAGE_SUPPORT_PGX
+               imagetype==CXIMAGE_FORMAT_PGX || 
+ #endif
+ #if   CXIMAGE_SUPPORT_PNM
+               imagetype==CXIMAGE_FORMAT_PNM || 
+ #endif
+ #if   CXIMAGE_SUPPORT_RAS
+               imagetype==CXIMAGE_FORMAT_RAS || 
+ #endif
+                false ){
+               CxImageJAS newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile,imagetype)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+#if CXIMAGE_SUPPORT_SKA
+       if (imagetype==CXIMAGE_FORMAT_SKA){
+               CxImageSKA newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       return false;
+               }
+       }
+#endif
+
+#if CXIMAGE_SUPPORT_RAW
+       if (imagetype==CXIMAGE_FORMAT_RAW){
+               CxImageRAW newima;
+               newima.CopyInfo(*this);
+               if (newima.Decode(hFile)){
+                       Transfer(newima);
+                       return true;
+               } else {
+                       strcpy(info.szLastError,newima.GetLastError());
+                       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, DWORD imagetype)
+{
+       SetType(CXIMAGE_FORMAT_UNKNOWN);
+       SetEscape(-1);
+
+       if (!Decode(hFile,imagetype))
+               return false;
+
+       if (GetType() == CXIMAGE_FORMAT_UNKNOWN || GetType() != imagetype)
+               return false;
+
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::CheckFormat(BYTE * buffer, DWORD size, DWORD imagetype)
+{
+       if (buffer==NULL || size==NULL){
+               strcpy(info.szLastError,"invalid or empty buffer");
+               return false;
+       }
+       CxMemFile file(buffer,size);
+       return CheckFormat(&file,imagetype);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
index 8d9404b8ad67fe052509e2d2412be68aa9cec3e1..d36e20c2c53994eb020f575be0c5f24c12049eb2 100644 (file)
-/*\r
- * File:       ximaexif.cpp\r
- * Purpose:    EXIF reader\r
- * 18/Aug/2002 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- * based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>\r
- */\r
-\r
-#include "ximajpg.h"\r
-\r
-#if CXIMAGEJPG_SUPPORT_EXIF\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-CxImageJPG::CxExifInfo::CxExifInfo(EXIFINFO* info)\r
-{\r
-       if (info) {\r
-               m_exifinfo = info;\r
-               freeinfo = false;\r
-       } else {\r
-               m_exifinfo = new EXIFINFO;\r
-               memset(m_exifinfo,0,sizeof(EXIFINFO));\r
-               freeinfo = true;\r
-       }\r
-\r
-       m_szLastError[0]='\0';\r
-       ExifImageWidth = MotorolaOrder = 0;\r
-       SectionsRead=0;\r
-       memset(&Sections, 0, MAX_SECTIONS * sizeof(Section_t));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-CxImageJPG::CxExifInfo::~CxExifInfo()\r
-{\r
-       for(int i=0;i<MAX_SECTIONS;i++) if(Sections[i].Data) free(Sections[i].Data);\r
-       if (freeinfo) delete m_exifinfo;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageJPG::CxExifInfo::DecodeExif(CxFile * hFile, int nReadMode)\r
-{\r
-    int a;\r
-    int HaveCom = FALSE;\r
-\r
-    a = hFile->GetC();\r
-\r
-    if (a != 0xff || hFile->GetC() != M_SOI){\r
-        return FALSE;\r
-    }\r
-\r
-    for(;;){\r
-        int itemlen;\r
-        int marker = 0;\r
-        int ll,lh, got;\r
-        BYTE * Data;\r
-\r
-        if (SectionsRead >= MAX_SECTIONS){\r
-                       strcpy(m_szLastError,"Too many sections in jpg file");\r
-                       return false;\r
-        }\r
-\r
-        for (a=0;a<7;a++){\r
-            marker = hFile->GetC();\r
-            if (marker != 0xff) break;\r
-\r
-            if (a >= 6){\r
-                printf("too many padding bytes\n");\r
-                return false;\r
-            }\r
-        }\r
-\r
-        if (marker == 0xff){\r
-            // 0xff is legal padding, but if we get that many, something's wrong.\r
-            strcpy(m_szLastError,"too many padding bytes!");\r
-                       return false;\r
-        }\r
-\r
-        Sections[SectionsRead].Type = marker;\r
-\r
-        // Read the length of the section.\r
-        lh = hFile->GetC();\r
-        ll = hFile->GetC();\r
-\r
-        itemlen = (lh << 8) | ll;\r
-\r
-        if (itemlen < 2){\r
-            strcpy(m_szLastError,"invalid marker");\r
-                       return false;\r
-        }\r
-\r
-        Sections[SectionsRead].Size = itemlen;\r
-\r
-        Data = (BYTE *)malloc(itemlen);\r
-        if (Data == NULL){\r
-            strcpy(m_szLastError,"Could not allocate memory");\r
-                       return false;\r
-        }\r
-        Sections[SectionsRead].Data = Data;\r
-\r
-        // Store first two pre-read bytes.\r
-        Data[0] = (BYTE)lh;\r
-        Data[1] = (BYTE)ll;\r
-\r
-        got = hFile->Read(Data+2, 1, itemlen-2); // Read the whole section.\r
-        if (got != itemlen-2){\r
-            strcpy(m_szLastError,"Premature end of file?");\r
-                       return false;\r
-        }\r
-        SectionsRead += 1;\r
-\r
-        switch(marker){\r
-\r
-            case M_SOS:   // stop before hitting compressed data \r
-                // If reading entire image is requested, read the rest of the data.\r
-                if (nReadMode & EXIF_READ_IMAGE){\r
-                    int cp, ep, size;\r
-                    // Determine how much file is left.\r
-                    cp = hFile->Tell();\r
-                    hFile->Seek(0, SEEK_END);\r
-                    ep = hFile->Tell();\r
-                    hFile->Seek(cp, SEEK_SET);\r
-\r
-                    size = ep-cp;\r
-                    Data = (BYTE *)malloc(size);\r
-                    if (Data == NULL){\r
-                        strcpy(m_szLastError,"could not allocate data for entire image");\r
-                                               return false;\r
-                    }\r
-\r
-                    got = hFile->Read(Data, 1, size);\r
-                    if (got != size){\r
-                        strcpy(m_szLastError,"could not read the rest of the image");\r
-                                               return false;\r
-                    }\r
-\r
-                    Sections[SectionsRead].Data = Data;\r
-                    Sections[SectionsRead].Size = size;\r
-                    Sections[SectionsRead].Type = PSEUDO_IMAGE_MARKER;\r
-                    SectionsRead ++;\r
-                }\r
-                return true;\r
-\r
-            case M_EOI:   // in case it's a tables-only JPEG stream\r
-                printf("No image in jpeg!\n");\r
-                return FALSE;\r
-\r
-            case M_COM: // Comment section\r
-                if (HaveCom || ((nReadMode & EXIF_READ_EXIF) == 0)){\r
-                    // Discard this section.\r
-                    free(Sections[--SectionsRead].Data);\r
-                                       Sections[SectionsRead].Data=0;\r
-                }else{\r
-                    process_COM(Data, itemlen);\r
-                    HaveCom = TRUE;\r
-                }\r
-                break;\r
-\r
-            case M_JFIF:\r
-                // Regular jpegs always have this tag, exif images have the exif\r
-                // marker instead, althogh ACDsee will write images with both markers.\r
-                // this program will re-create this marker on absence of exif marker.\r
-                // hence no need to keep the copy from the file.\r
-                free(Sections[--SectionsRead].Data);\r
-                               Sections[SectionsRead].Data=0;\r
-                break;\r
-\r
-            case M_EXIF:\r
-                // Seen files from some 'U-lead' software with Vivitar scanner\r
-                // that uses marker 31 for non exif stuff.  Thus make sure \r
-                // it says 'Exif' in the section before treating it as exif.\r
-                if ((nReadMode & EXIF_READ_EXIF) && memcmp(Data+2, "Exif", 4) == 0){\r
-                    m_exifinfo->IsExif = process_EXIF((BYTE *)Data+2, itemlen);\r
-                }else{\r
-                    // Discard this section.\r
-                    free(Sections[--SectionsRead].Data);\r
-                                       Sections[SectionsRead].Data=0;\r
-                }\r
-                break;\r
-\r
-            case M_SOF0: \r
-            case M_SOF1: \r
-            case M_SOF2: \r
-            case M_SOF3: \r
-            case M_SOF5: \r
-            case M_SOF6: \r
-            case M_SOF7: \r
-            case M_SOF9: \r
-            case M_SOF10:\r
-            case M_SOF11:\r
-            case M_SOF13:\r
-            case M_SOF14:\r
-            case M_SOF15:\r
-                process_SOFn(Data, marker);\r
-                break;\r
-            default:\r
-                // Skip any other sections.\r
-                //if (ShowTags) printf("Jpeg section marker 0x%02x size %d\n",marker, itemlen);\r
-                break;\r
-        }\r
-    }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/*--------------------------------------------------------------------------\r
-   Process a EXIF marker\r
-   Describes all the drivel that most digital cameras include...\r
---------------------------------------------------------------------------*/\r
-bool CxImageJPG::CxExifInfo::process_EXIF(unsigned char * CharBuf, unsigned int length)\r
-{\r
-    m_exifinfo->FlashUsed = 0; \r
-    /* If it's from a digicam, and it used flash, it says so. */\r
-    m_exifinfo->Comments[0] = '\0';  /* Initial value - null string */\r
-\r
-    ExifImageWidth = 0;\r
-\r
-    {   /* Check the EXIF header component */\r
-        static const unsigned char ExifHeader[] = "Exif\0\0";\r
-        if (memcmp(CharBuf+0, ExifHeader,6)){\r
-                       strcpy(m_szLastError,"Incorrect Exif header");\r
-                       return false;\r
-               }\r
-    }\r
-\r
-    if (memcmp(CharBuf+6,"II",2) == 0){\r
-        MotorolaOrder = 0;\r
-    }else{\r
-        if (memcmp(CharBuf+6,"MM",2) == 0){\r
-            MotorolaOrder = 1;\r
-        }else{\r
-            strcpy(m_szLastError,"Invalid Exif alignment marker.");\r
-                       return false;\r
-        }\r
-    }\r
-\r
-    /* Check the next two values for correctness. */\r
-    if (Get16u(CharBuf+8) != 0x2a){\r
-        strcpy(m_szLastError,"Invalid Exif start (1)");\r
-               return false;\r
-    }\r
-\r
-       int FirstOffset = Get32u(CharBuf+10);\r
-    /* <Richard Collins> \r
-       if (FirstOffset < 8 || FirstOffset > 16){\r
-        // I used to ensure this was set to 8 (website I used indicated its 8)\r
-        // but PENTAX Optio 230 has it set differently, and uses it as offset. (Sept 11 2002)\r
-        strcpy(m_szLastError,"Suspicious offset of first IFD value");\r
-               return false;\r
-    }*/\r
-\r
-    unsigned char * LastExifRefd = CharBuf;\r
-\r
-    /* First directory starts 16 bytes in.  Offsets start at 8 bytes in. */\r
-    if (!ProcessExifDir(CharBuf+14, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))\r
-               return false;\r
-\r
-       /* <Richard Collins> give a chance for a second directory */\r
-       if (FirstOffset > 8) {\r
-               if (!ProcessExifDir(CharBuf+14+FirstOffset-8, CharBuf+6, length-6, m_exifinfo, &LastExifRefd))\r
-                       return false;\r
-       }\r
-\r
-    /* This is how far the interesting (non thumbnail) part of the exif went. */\r
-    // int ExifSettingsLength = LastExifRefd - CharBuf;\r
-\r
-    /* Compute the CCD width, in milimeters. */\r
-    if (m_exifinfo->FocalplaneXRes != 0){\r
-        m_exifinfo->CCDWidth = (float)(ExifImageWidth * m_exifinfo->FocalplaneUnits / m_exifinfo->FocalplaneXRes);\r
-    }\r
-\r
-       return true;\r
-}\r
-//--------------------------------------------------------------------------\r
-// Get 16 bits motorola order (always) for jpeg header stuff.\r
-//--------------------------------------------------------------------------\r
-int CxImageJPG::CxExifInfo::Get16m(void * Short)\r
-{\r
-    return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/*--------------------------------------------------------------------------\r
-   Convert a 16 bit unsigned value from file's native byte order\r
---------------------------------------------------------------------------*/\r
-int CxImageJPG::CxExifInfo::Get16u(void * Short)\r
-{\r
-    if (MotorolaOrder){\r
-        return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];\r
-    }else{\r
-        return (((unsigned char *)Short)[1] << 8) | ((unsigned char *)Short)[0];\r
-    }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/*--------------------------------------------------------------------------\r
-   Convert a 32 bit signed value from file's native byte order\r
---------------------------------------------------------------------------*/\r
-long CxImageJPG::CxExifInfo::Get32s(void * Long)\r
-{\r
-    if (MotorolaOrder){\r
-        return  ((( char *)Long)[0] << 24) | (((unsigned char *)Long)[1] << 16)\r
-              | (((unsigned char *)Long)[2] << 8 ) | (((unsigned char *)Long)[3] << 0 );\r
-    }else{\r
-        return  ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16)\r
-              | (((unsigned char *)Long)[1] << 8 ) | (((unsigned char *)Long)[0] << 0 );\r
-    }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/*--------------------------------------------------------------------------\r
-   Convert a 32 bit unsigned value from file's native byte order\r
---------------------------------------------------------------------------*/\r
-unsigned long CxImageJPG::CxExifInfo::Get32u(void * Long)\r
-{\r
-    return (unsigned long)Get32s(Long) & 0xffffffff;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-/* Describes format descriptor */\r
-static const int BytesPerFormat[] = {0,1,1,2,4,8,1,1,2,4,8,4,8};\r
-#define NUM_FORMATS 12\r
-\r
-#define FMT_BYTE       1 \r
-#define FMT_STRING     2\r
-#define FMT_USHORT     3\r
-#define FMT_ULONG      4\r
-#define FMT_URATIONAL  5\r
-#define FMT_SBYTE      6\r
-#define FMT_UNDEFINED  7\r
-#define FMT_SSHORT     8\r
-#define FMT_SLONG      9\r
-#define FMT_SRATIONAL 10\r
-#define FMT_SINGLE    11\r
-#define FMT_DOUBLE    12\r
-\r
-/* Describes tag values */\r
-\r
-#define TAG_EXIF_VERSION      0x9000\r
-#define TAG_EXIF_OFFSET       0x8769\r
-#define TAG_INTEROP_OFFSET    0xa005\r
-\r
-#define TAG_MAKE              0x010F\r
-#define TAG_MODEL             0x0110\r
-\r
-#define TAG_ORIENTATION       0x0112\r
-#define TAG_XRESOLUTION       0x011A\r
-#define TAG_YRESOLUTION       0x011B\r
-#define TAG_RESOLUTIONUNIT    0x0128\r
-\r
-#define TAG_EXPOSURETIME      0x829A\r
-#define TAG_FNUMBER           0x829D\r
-\r
-#define TAG_SHUTTERSPEED      0x9201\r
-#define TAG_APERTURE          0x9202\r
-#define TAG_BRIGHTNESS        0x9203\r
-#define TAG_MAXAPERTURE       0x9205\r
-#define TAG_FOCALLENGTH       0x920A\r
-\r
-#define TAG_DATETIME_ORIGINAL 0x9003\r
-#define TAG_USERCOMMENT       0x9286\r
-\r
-#define TAG_SUBJECT_DISTANCE  0x9206\r
-#define TAG_FLASH             0x9209\r
-\r
-#define TAG_FOCALPLANEXRES    0xa20E\r
-#define TAG_FOCALPLANEYRES    0xa20F\r
-#define TAG_FOCALPLANEUNITS   0xa210\r
-#define TAG_EXIF_IMAGEWIDTH   0xA002\r
-#define TAG_EXIF_IMAGELENGTH  0xA003\r
-\r
-/* the following is added 05-jan-2001 vcs */\r
-#define TAG_EXPOSURE_BIAS     0x9204\r
-#define TAG_WHITEBALANCE      0x9208\r
-#define TAG_METERING_MODE     0x9207\r
-#define TAG_EXPOSURE_PROGRAM  0x8822\r
-#define TAG_ISO_EQUIVALENT    0x8827\r
-#define TAG_COMPRESSION_LEVEL 0x9102\r
-\r
-#define TAG_THUMBNAIL_OFFSET  0x0201\r
-#define TAG_THUMBNAIL_LENGTH  0x0202\r
-\r
-\r
-/*--------------------------------------------------------------------------\r
-   Process one of the nested EXIF directories.\r
---------------------------------------------------------------------------*/\r
-bool CxImageJPG::CxExifInfo::ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,\r
-                           EXIFINFO * const m_exifinfo, unsigned char ** const LastExifRefdP, int NestingLevel)\r
-{\r
-    int de;\r
-    int a;\r
-    int NumDirEntries;\r
-    unsigned ThumbnailOffset = 0;\r
-    unsigned ThumbnailSize = 0;\r
-\r
-    if (NestingLevel > 4){\r
-        strcpy(m_szLastError,"Maximum directory nesting exceeded (corrupt exif header)");\r
-        return false;\r
-    }\r
-\r
-    NumDirEntries = Get16u(DirStart);\r
-\r
-    if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)){\r
-        strcpy(m_szLastError,"Illegally sized directory");\r
-               return false;\r
-    }\r
-\r
-    for (de=0;de<NumDirEntries;de++){\r
-        int Tag, Format, Components;\r
-        unsigned char * ValuePtr;\r
-            /* This actually can point to a variety of things; it must be\r
-               cast to other types when used.  But we use it as a byte-by-byte\r
-               cursor, so we declare it as a pointer to a generic byte here.\r
-            */\r
-        int ByteCount;\r
-        unsigned char * DirEntry;\r
-        DirEntry = DirStart+2+12*de;\r
-\r
-        Tag = Get16u(DirEntry);\r
-        Format = Get16u(DirEntry+2);\r
-        Components = Get32u(DirEntry+4);\r
-\r
-        if ((Format-1) >= NUM_FORMATS) {\r
-            /* (-1) catches illegal zero case as unsigned underflows to positive large */\r
-            strcpy(m_szLastError,"Illegal format code in EXIF dir");\r
-                       return false;\r
-               }\r
-\r
-        ByteCount = Components * BytesPerFormat[Format];\r
-\r
-        if (ByteCount > 4){\r
-            unsigned OffsetVal;\r
-            OffsetVal = Get32u(DirEntry+8);\r
-            /* If its bigger than 4 bytes, the dir entry contains an offset.*/\r
-            if (OffsetVal+ByteCount > ExifLength){\r
-                /* Bogus pointer offset and / or bytecount value */\r
-                strcpy(m_szLastError,"Illegal pointer offset value in EXIF.");\r
-                               return false;\r
-            }\r
-            ValuePtr = OffsetBase+OffsetVal;\r
-        }else{\r
-            /* 4 bytes or less and value is in the dir entry itself */\r
-            ValuePtr = DirEntry+8;\r
-        }\r
-\r
-        if (*LastExifRefdP < ValuePtr+ByteCount){\r
-            /* Keep track of last byte in the exif header that was\r
-               actually referenced.  That way, we know where the\r
-               discardable thumbnail data begins.\r
-            */\r
-            *LastExifRefdP = ValuePtr+ByteCount;\r
-        }\r
-\r
-        /* Extract useful components of tag */\r
-        switch(Tag){\r
-\r
-            case TAG_MAKE:\r
-                strncpy(m_exifinfo->CameraMake, (char*)ValuePtr, 31);\r
-                break;\r
-\r
-            case TAG_MODEL:\r
-                strncpy(m_exifinfo->CameraModel, (char*)ValuePtr, 39);\r
-                break;\r
-\r
-                       case TAG_EXIF_VERSION:\r
-                               strncpy(m_exifinfo->Version,(char*)ValuePtr, 4);\r
-                               break;\r
-\r
-            case TAG_DATETIME_ORIGINAL:\r
-                strncpy(m_exifinfo->DateTime, (char*)ValuePtr, 19);\r
-                break;\r
-\r
-            case TAG_USERCOMMENT:\r
-                // Olympus has this padded with trailing spaces. Remove these first. \r
-                for (a=ByteCount;;){\r
-                    a--;\r
-                    if (((char*)ValuePtr)[a] == ' '){\r
-                        ((char*)ValuePtr)[a] = '\0';\r
-                    }else{\r
-                        break;\r
-                    }\r
-                    if (a == 0) break;\r
-                }\r
-\r
-                /* Copy the comment */\r
-                if (memcmp(ValuePtr, "ASCII",5) == 0){\r
-                    for (a=5;a<10;a++){\r
-                        char c;\r
-                        c = ((char*)ValuePtr)[a];\r
-                        if (c != '\0' && c != ' '){\r
-                            strncpy(m_exifinfo->Comments, (char*)ValuePtr+a, 199);\r
-                            break;\r
-                        }\r
-                    }\r
-                    \r
-                }else{\r
-                    strncpy(m_exifinfo->Comments, (char*)ValuePtr, 199);\r
-                }\r
-                break;\r
-\r
-            case TAG_FNUMBER:\r
-                /* Simplest way of expressing aperture, so I trust it the most.\r
-                   (overwrite previously computd value if there is one)\r
-                   */\r
-                m_exifinfo->ApertureFNumber = (float)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_APERTURE:\r
-            case TAG_MAXAPERTURE:\r
-                /* More relevant info always comes earlier, so only\r
-                 use this field if we don't have appropriate aperture\r
-                 information yet. \r
-                */\r
-                if (m_exifinfo->ApertureFNumber == 0){\r
-                    m_exifinfo->ApertureFNumber = (float)exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f)*0.5);\r
-                }\r
-                break;\r
-\r
-                       case TAG_BRIGHTNESS:\r
-                               m_exifinfo->Brightness = (float)ConvertAnyFormat(ValuePtr, Format);\r
-                               break;\r
-\r
-            case TAG_FOCALLENGTH:\r
-                /* Nice digital cameras actually save the focal length\r
-                   as a function of how farthey are zoomed in. \r
-                */\r
-\r
-                m_exifinfo->FocalLength = (float)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_SUBJECT_DISTANCE:\r
-                /* Inidcates the distacne the autofocus camera is focused to.\r
-                   Tends to be less accurate as distance increases.\r
-                */\r
-                m_exifinfo->Distance = (float)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_EXPOSURETIME:\r
-                /* Simplest way of expressing exposure time, so I\r
-                   trust it most.  (overwrite previously computd value\r
-                   if there is one) \r
-                */\r
-                m_exifinfo->ExposureTime = \r
-                    (float)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_SHUTTERSPEED:\r
-                /* More complicated way of expressing exposure time,\r
-                   so only use this value if we don't already have it\r
-                   from somewhere else.  \r
-                */\r
-                if (m_exifinfo->ExposureTime == 0){\r
-                    m_exifinfo->ExposureTime = (float)\r
-                        (1/exp(ConvertAnyFormat(ValuePtr, Format)*log(2.0f)));\r
-                }\r
-                break;\r
-\r
-            case TAG_FLASH:\r
-                if ((int)ConvertAnyFormat(ValuePtr, Format) & 7){\r
-                    m_exifinfo->FlashUsed = 1;\r
-                }else{\r
-                    m_exifinfo->FlashUsed = 0;\r
-                }\r
-                break;\r
-\r
-            case TAG_ORIENTATION:\r
-                m_exifinfo->Orientation = (int)ConvertAnyFormat(ValuePtr, Format);\r
-                if (m_exifinfo->Orientation < 1 || m_exifinfo->Orientation > 8){\r
-                    strcpy(m_szLastError,"Undefined rotation value");\r
-                    m_exifinfo->Orientation = 0;\r
-                }\r
-                break;\r
-\r
-            case TAG_EXIF_IMAGELENGTH:\r
-            case TAG_EXIF_IMAGEWIDTH:\r
-                /* Use largest of height and width to deal with images\r
-                   that have been rotated to portrait format.  \r
-                */\r
-                a = (int)ConvertAnyFormat(ValuePtr, Format);\r
-                if (ExifImageWidth < a) ExifImageWidth = a;\r
-                break;\r
-\r
-            case TAG_FOCALPLANEXRES:\r
-                m_exifinfo->FocalplaneXRes = (float)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_FOCALPLANEYRES:\r
-                m_exifinfo->FocalplaneYRes = (float)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-                       case TAG_RESOLUTIONUNIT:\r
-                switch((int)ConvertAnyFormat(ValuePtr, Format)){\r
-                    case 1: m_exifinfo->ResolutionUnit = 1.0f; break; /* 1 inch */\r
-                    case 2:    m_exifinfo->ResolutionUnit = 1.0f; break;\r
-                    case 3: m_exifinfo->ResolutionUnit = 0.3937007874f;    break;  /* 1 centimeter*/\r
-                    case 4: m_exifinfo->ResolutionUnit = 0.03937007874f;   break;  /* 1 millimeter*/\r
-                    case 5: m_exifinfo->ResolutionUnit = 0.00003937007874f;  /* 1 micrometer*/\r
-                }\r
-                break;\r
-\r
-            case TAG_FOCALPLANEUNITS:\r
-                switch((int)ConvertAnyFormat(ValuePtr, Format)){\r
-                    case 1: m_exifinfo->FocalplaneUnits = 1.0f; break; /* 1 inch */\r
-                    case 2:    m_exifinfo->FocalplaneUnits = 1.0f; break;\r
-                    case 3: m_exifinfo->FocalplaneUnits = 0.3937007874f;    break;  /* 1 centimeter*/\r
-                    case 4: m_exifinfo->FocalplaneUnits = 0.03937007874f;   break;  /* 1 millimeter*/\r
-                    case 5: m_exifinfo->FocalplaneUnits = 0.00003937007874f;  /* 1 micrometer*/\r
-                }\r
-                break;\r
-\r
-                // Remaining cases contributed by: Volker C. Schoech <schoech(at)gmx(dot)de>\r
-\r
-            case TAG_EXPOSURE_BIAS:\r
-                m_exifinfo->ExposureBias = (float) ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_WHITEBALANCE:\r
-                m_exifinfo->Whitebalance = (int)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_METERING_MODE:\r
-                m_exifinfo->MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_EXPOSURE_PROGRAM:\r
-                m_exifinfo->ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_ISO_EQUIVALENT:\r
-                m_exifinfo->ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format);\r
-                if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200;\r
-                break;\r
-\r
-            case TAG_COMPRESSION_LEVEL:\r
-                m_exifinfo->CompressionLevel = (int)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_XRESOLUTION:\r
-                m_exifinfo->Xresolution = (float)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-            case TAG_YRESOLUTION:\r
-                m_exifinfo->Yresolution = (float)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_THUMBNAIL_OFFSET:\r
-                ThumbnailOffset = (unsigned)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-            case TAG_THUMBNAIL_LENGTH:\r
-                ThumbnailSize = (unsigned)ConvertAnyFormat(ValuePtr, Format);\r
-                break;\r
-\r
-        }\r
-\r
-        if (Tag == TAG_EXIF_OFFSET || Tag == TAG_INTEROP_OFFSET){\r
-            unsigned char * SubdirStart;\r
-                       unsigned Offset = Get32u(ValuePtr);\r
-                       if (Offset>8){\r
-                               SubdirStart = OffsetBase + Offset;\r
-                               if (SubdirStart < OffsetBase || \r
-                                       SubdirStart > OffsetBase+ExifLength){\r
-                                       strcpy(m_szLastError,"Illegal subdirectory link");\r
-                                       return false;\r
-                               }\r
-                               ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP, NestingLevel+1);\r
-                       }\r
-            continue;\r
-        }\r
-    }\r
-\r
-\r
-    {\r
-        /* In addition to linking to subdirectories via exif tags,\r
-           there's also a potential link to another directory at the end\r
-           of each directory.  This has got to be the result of a\r
-           committee!  \r
-        */\r
-        unsigned char * SubdirStart;\r
-        unsigned Offset;\r
-        Offset = Get16u(DirStart+2+12*NumDirEntries);\r
-        if (Offset){\r
-            SubdirStart = OffsetBase + Offset;\r
-            if (SubdirStart < OffsetBase \r
-                || SubdirStart > OffsetBase+ExifLength){\r
-                strcpy(m_szLastError,"Illegal subdirectory link");\r
-                               return false;\r
-            }\r
-            ProcessExifDir(SubdirStart, OffsetBase, ExifLength, m_exifinfo, LastExifRefdP, NestingLevel+1);\r
-        }\r
-    }\r
-\r
-\r
-    if (ThumbnailSize && ThumbnailOffset){\r
-        if (ThumbnailSize + ThumbnailOffset <= ExifLength){\r
-            /* The thumbnail pointer appears to be valid.  Store it. */\r
-            m_exifinfo->ThumbnailPointer = OffsetBase + ThumbnailOffset;\r
-            m_exifinfo->ThumbnailSize = ThumbnailSize;\r
-        }\r
-    }\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/*--------------------------------------------------------------------------\r
-   Evaluate number, be it int, rational, or float from directory.\r
---------------------------------------------------------------------------*/\r
-double CxImageJPG::CxExifInfo::ConvertAnyFormat(void * ValuePtr, int Format)\r
-{\r
-    double Value;\r
-    Value = 0;\r
-\r
-    switch(Format){\r
-        case FMT_SBYTE:     Value = *(signed char *)ValuePtr;  break;\r
-        case FMT_BYTE:      Value = *(unsigned char *)ValuePtr;        break;\r
-\r
-        case FMT_USHORT:    Value = Get16u(ValuePtr);          break;\r
-        case FMT_ULONG:     Value = Get32u(ValuePtr);          break;\r
-\r
-        case FMT_URATIONAL:\r
-        case FMT_SRATIONAL: \r
-            {\r
-                int Num,Den;\r
-                Num = Get32s(ValuePtr);\r
-                Den = Get32s(4+(char *)ValuePtr);\r
-                if (Den == 0){\r
-                    Value = 0;\r
-                }else{\r
-                    Value = (double)Num/Den;\r
-                }\r
-                break;\r
-            }\r
-\r
-        case FMT_SSHORT:    Value = (signed short)Get16u(ValuePtr);  break;\r
-        case FMT_SLONG:     Value = Get32s(ValuePtr);                break;\r
-\r
-        /* Not sure if this is correct (never seen float used in Exif format)\r
-         */\r
-        case FMT_SINGLE:    Value = (double)*(float *)ValuePtr;      break;\r
-        case FMT_DOUBLE:    Value = *(double *)ValuePtr;             break;\r
-    }\r
-    return Value;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageJPG::CxExifInfo::process_COM (const BYTE * Data, int length)\r
-{\r
-    int ch;\r
-    char Comment[MAX_COMMENT+1];\r
-    int nch;\r
-    int a;\r
-\r
-    nch = 0;\r
-\r
-    if (length > MAX_COMMENT) length = MAX_COMMENT; // Truncate if it won't fit in our structure.\r
-\r
-    for (a=2;a<length;a++){\r
-        ch = Data[a];\r
-\r
-        if (ch == '\r' && Data[a+1] == '\n') continue; // Remove cr followed by lf.\r
-\r
-        if (isprint(ch) || ch == '\n' || ch == '\t'){\r
-            Comment[nch++] = (char)ch;\r
-        }else{\r
-            Comment[nch++] = '?';\r
-        }\r
-    }\r
-\r
-    Comment[nch] = '\0'; // Null terminate\r
-\r
-    //if (ShowTags) printf("COM marker comment: %s\n",Comment);\r
-\r
-    strcpy(m_exifinfo->Comments,Comment);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageJPG::CxExifInfo::process_SOFn (const BYTE * Data, int marker)\r
-{\r
-    int data_precision, num_components;\r
-\r
-    data_precision = Data[2];\r
-    m_exifinfo->Height = Get16m((void*)(Data+3));\r
-    m_exifinfo->Width = Get16m((void*)(Data+5));\r
-    num_components = Data[7];\r
-\r
-    if (num_components == 3){\r
-        m_exifinfo->IsColor = 1;\r
-    }else{\r
-        m_exifinfo->IsColor = 0;\r
-    }\r
-\r
-    m_exifinfo->Process = marker;\r
-\r
-    //if (ShowTags) printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",\r
-    //               ImageInfo.Width, ImageInfo.Height, num_components, data_precision);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * this will work only on a CxImageJPG object, if the image originally has valid EXIF data\r
- \verbatim\r
-       CxImageJPG jpg;\r
-       CxIOFile in,out;\r
-       in.Open("D:\\exif_in.jpg","rb");\r
-       out.Open("D:\\exif_out.jpg","w+b");\r
-       jpg.Decode(&in);\r
-       if (jpg.IsValid()){\r
-               jpg.RotateLeft();\r
-               jpg.Encode(&out);\r
-       }\r
- \endverbatim\r
-*/\r
-bool CxImageJPG::CxExifInfo::EncodeExif(CxFile * hFile)\r
-{\r
-    int a;\r
-\r
-    if (FindSection(M_SOS)==NULL){\r
-               strcpy(m_szLastError,"Can't write exif : didn't read all");\r
-               return false;\r
-    }\r
-\r
-    // Initial static jpeg marker.\r
-       hFile->PutC(0xff);\r
-       hFile->PutC(0xd8);\r
-    \r
-    if (Sections[0].Type != M_EXIF && Sections[0].Type != M_JFIF){\r
-        // The image must start with an exif or jfif marker.  If we threw those away, create one.\r
-        static BYTE JfifHead[18] = {\r
-            0xff, M_JFIF,\r
-            0x00, 0x10, 'J' , 'F' , 'I' , 'F' , 0x00, 0x01, \r
-            0x01, 0x01, 0x01, 0x2C, 0x01, 0x2C, 0x00, 0x00 \r
-        };\r
-        hFile->Write(JfifHead, 18, 1);\r
-    }\r
-\r
-    // Write all the misc sections\r
-    for (a=0;a<SectionsRead-1;a++){\r
-        hFile->PutC(0xff);\r
-        hFile->PutC((unsigned char)(Sections[a].Type));\r
-        hFile->Write(Sections[a].Data, Sections[a].Size, 1);\r
-    }\r
-\r
-    // Write the remaining image data.\r
-    hFile->Write(Sections[a].Data, Sections[a].Size, 1);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageJPG::CxExifInfo::DiscardAllButExif()\r
-{\r
-    Section_t ExifKeeper;\r
-    Section_t CommentKeeper;\r
-    int a;\r
-\r
-    memset(&ExifKeeper, 0, sizeof(ExifKeeper));\r
-    memset(&CommentKeeper, 0, sizeof(ExifKeeper));\r
-\r
-    for (a=0;a<SectionsRead;a++){\r
-        if (Sections[a].Type == M_EXIF && ExifKeeper.Type == 0){\r
-            ExifKeeper = Sections[a];\r
-        }else if (Sections[a].Type == M_COM && CommentKeeper.Type == 0){\r
-            CommentKeeper = Sections[a];\r
-        }else{\r
-            free(Sections[a].Data);\r
-                       Sections[a].Data = 0;\r
-        }\r
-    }\r
-    SectionsRead = 0;\r
-    if (ExifKeeper.Type){\r
-        Sections[SectionsRead++] = ExifKeeper;\r
-    }\r
-    if (CommentKeeper.Type){\r
-        Sections[SectionsRead++] = CommentKeeper;\r
-    }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void* CxImageJPG::CxExifInfo::FindSection(int SectionType)\r
-{\r
-    int a;\r
-    for (a=0;a<SectionsRead-1;a++){\r
-        if (Sections[a].Type == SectionType){\r
-            return &Sections[a];\r
-        }\r
-    }\r
-    // Could not be found.\r
-    return NULL;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif         // CXIMAGEJPG_SUPPORT_EXIF\r
-\r
+/*
+ * File:       ximaexif.cpp
+ * Purpose:    EXIF reader
+ * 18/Aug/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ * 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(int 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, int nReadMode)
+{
+    int a;
+    int HaveCom = FALSE;
+
+    a = hFile->GetC();
+
+    if (a != 0xff || hFile->GetC() != M_SOI){
+        return FALSE;
+    }
+
+    for(;;){
+        int itemlen;
+        int marker = 0;
+        int ll,lh, got;
+        BYTE * 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 = (BYTE *)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] = (BYTE)lh;
+        Data[1] = (BYTE)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){
+                    int 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 = (BYTE *)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((BYTE *)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(unsigned char * CharBuf, unsigned int 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 unsigned char 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;
+    }
+
+       int 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;
+    }*/
+
+    unsigned char * 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. */
+    // int 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.
+//--------------------------------------------------------------------------
+int CxImageJPG::CxExifInfo::Get16m(void * Short)
+{
+    return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+   Convert a 16 bit unsigned value from file's native byte order
+--------------------------------------------------------------------------*/
+int CxImageJPG::CxExifInfo::Get16u(void * Short)
+{
+    if (MotorolaOrder){
+        return (((unsigned char *)Short)[0] << 8) | ((unsigned char *)Short)[1];
+    }else{
+        return (((unsigned char *)Short)[1] << 8) | ((unsigned char *)Short)[0];
+    }
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+   Convert a 32 bit signed value from file's native byte order
+--------------------------------------------------------------------------*/
+long CxImageJPG::CxExifInfo::Get32s(void * Long)
+{
+    if (MotorolaOrder){
+        return  ((( char *)Long)[0] << 24) | (((unsigned char *)Long)[1] << 16)
+              | (((unsigned char *)Long)[2] << 8 ) | (((unsigned char *)Long)[3] << 0 );
+    }else{
+        return  ((( char *)Long)[3] << 24) | (((unsigned char *)Long)[2] << 16)
+              | (((unsigned char *)Long)[1] << 8 ) | (((unsigned char *)Long)[0] << 0 );
+    }
+}
+////////////////////////////////////////////////////////////////////////////////
+/*--------------------------------------------------------------------------
+   Convert a 32 bit unsigned value from file's native byte order
+--------------------------------------------------------------------------*/
+unsigned long CxImageJPG::CxExifInfo::Get32u(void * Long)
+{
+    return (unsigned long)Get32s(Long) & 0xffffffff;
+}
+////////////////////////////////////////////////////////////////////////////////
+
+/* Describes format descriptor */
+static const int 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(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,
+                           EXIFINFO * const m_exifinfo, unsigned char ** const LastExifRefdP, int NestingLevel)
+{
+    int de;
+    int a;
+    int 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++){
+        int Tag, Format, Components;
+        unsigned char * 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.
+            */
+        int ByteCount;
+        unsigned char * 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 ((int)ConvertAnyFormat(ValuePtr, Format) & 7){
+                    m_exifinfo->FlashUsed = 1;
+                }else{
+                    m_exifinfo->FlashUsed = 0;
+                }
+                break;
+
+            case TAG_ORIENTATION:
+                m_exifinfo->Orientation = (int)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 = (int)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((int)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((int)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 = (int)ConvertAnyFormat(ValuePtr, Format);
+                break;
+
+            case TAG_METERING_MODE:
+                m_exifinfo->MeteringMode = (int)ConvertAnyFormat(ValuePtr, Format);
+                break;
+
+            case TAG_EXPOSURE_PROGRAM:
+                m_exifinfo->ExposureProgram = (int)ConvertAnyFormat(ValuePtr, Format);
+                break;
+
+            case TAG_ISO_EQUIVALENT:
+                m_exifinfo->ISOequivalent = (int)ConvertAnyFormat(ValuePtr, Format);
+                if ( m_exifinfo->ISOequivalent < 50 ) m_exifinfo->ISOequivalent *= 200;
+                break;
+
+            case TAG_COMPRESSION_LEVEL:
+                m_exifinfo->CompressionLevel = (int)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){
+            unsigned char * 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!  
+        */
+        unsigned char * 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 int, rational, or float from directory.
+--------------------------------------------------------------------------*/
+double CxImageJPG::CxExifInfo::ConvertAnyFormat(void * ValuePtr, int Format)
+{
+    double Value;
+    Value = 0;
+
+    switch(Format){
+        case FMT_SBYTE:     Value = *(signed char *)ValuePtr;  break;
+        case FMT_BYTE:      Value = *(unsigned char *)ValuePtr;        break;
+
+        case FMT_USHORT:    Value = Get16u(ValuePtr);          break;
+        case FMT_ULONG:     Value = Get32u(ValuePtr);          break;
+
+        case FMT_URATIONAL:
+        case FMT_SRATIONAL: 
+            {
+                int 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 = (signed short)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 BYTE * Data, int length)
+{
+    int ch;
+    char Comment[MAX_COMMENT+1];
+    int nch;
+    int 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 BYTE * Data, int marker)
+{
+    int 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)
+{
+    int 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 BYTE 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((unsigned char)(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;
+    int 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(int SectionType)
+{
+    int 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
+
index f4e185675a5e3fa5c6543f08ef1b2a024b52cc38..e81d3c6c8e2487d85c9a310c10aec0dfc2927339 100644 (file)
-// ximage.cpp : main implementation file\r
-/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// CxImage \r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Initialize the internal structures\r
- */\r
-void CxImage::Startup(DWORD imagetype)\r
-{\r
-       //init pointers\r
-       pDib = pSelection = pAlpha = NULL;\r
-       ppLayers = ppFrames = NULL;\r
-       //init structures\r
-       memset(&head,0,sizeof(BITMAPINFOHEADER));\r
-       memset(&info,0,sizeof(CXIMAGEINFO));\r
-       //init default attributes\r
-    info.dwType = imagetype;\r
-       info.fQuality = 90.0f;\r
-       info.nAlphaMax = 255;\r
-       info.nBkgndIndex = -1;\r
-       info.bEnabled = true;\r
-       SetXDPI(CXIMAGE_DEFAULT_DPI);\r
-       SetYDPI(CXIMAGE_DEFAULT_DPI);\r
-\r
-       short test = 1;\r
-       info.bLittleEndianHost = (*((char *) &test) == 1);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Empty image constructor\r
- * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS\r
- */\r
-CxImage::CxImage(DWORD imagetype)\r
-{\r
-       Startup(imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Call this function to destroy image pixels, alpha channel, selection and sub layers.\r
- * - Attributes are not erased, but IsValid returns false.\r
- *\r
- * \return true if everything is freed, false if the image is a Ghost\r
- */\r
-bool CxImage::Destroy()\r
-{\r
-       //free this only if it's valid and it's not a ghost\r
-       if (info.pGhost==NULL){\r
-               if (ppLayers) { \r
-                       for(long n=0; n<info.nNumLayers;n++){ delete ppLayers[n]; }\r
-                       delete [] ppLayers; ppLayers=0; info.nNumLayers = 0;\r
-               }\r
-               if (pSelection) {free(pSelection); pSelection=0;}\r
-               if (pAlpha) {free(pAlpha); pAlpha=0;}\r
-               if (pDib) {free(pDib); pDib=0;}\r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::DestroyFrames()\r
-{\r
-       if (info.pGhost==NULL) {\r
-               if (ppFrames) {\r
-                       for (long n=0; n<info.nNumFrames; n++) { delete ppFrames[n]; }\r
-                       delete [] ppFrames; ppFrames = NULL; info.nNumFrames = 0;\r
-               }\r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sized image constructor\r
- * \param dwWidth: width\r
- * \param dwHeight: height\r
- * \param wBpp: bit per pixel, can be 1, 4, 8, 24\r
- * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS\r
- */\r
-CxImage::CxImage(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype)\r
-{\r
-       Startup(imagetype);\r
-       Create(dwWidth,dwHeight,wBpp,imagetype);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * image constructor from existing source\r
- * \param src: source image.\r
- * \param copypixels: copy the pixels from the source image into the new image.\r
- * \param copyselection: copy the selection from source\r
- * \param copyalpha: copy the alpha channel from source\r
- * \sa Copy\r
- */\r
-CxImage::CxImage(const CxImage &src, bool copypixels, bool copyselection, bool copyalpha)\r
-{\r
-       Startup(src.GetType());\r
-       Copy(src,copypixels,copyselection,copyalpha);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Copies the image from an exsisting source\r
- * \param src: source image.\r
- * \param copypixels: copy the pixels from the source image into the new image.\r
- * \param copyselection: copy the selection from source\r
- * \param copyalpha: copy the alpha channel from source\r
- */\r
-void CxImage::Copy(const CxImage &src, bool copypixels, bool copyselection, bool copyalpha)\r
-{\r
-       // if the source is a ghost, the copy is still a ghost\r
-       if (src.info.pGhost){\r
-               Ghost(&src);\r
-               return;\r
-       }\r
-       //copy the attributes\r
-       memcpy(&info,&src.info,sizeof(CXIMAGEINFO));\r
-       memcpy(&head,&src.head,sizeof(BITMAPINFOHEADER)); // [andy] - fix for bitmap header DPI\r
-       //rebuild the image\r
-       Create(src.GetWidth(),src.GetHeight(),src.GetBpp(),src.GetType());\r
-       //copy the pixels and the palette, or at least copy the palette only.\r
-       if (copypixels && pDib && src.pDib) memcpy(pDib,src.pDib,GetSize());\r
-       else SetPalette(src.GetPalette());\r
-       long nSize = head.biWidth * head.biHeight;\r
-       //copy the selection\r
-       if (copyselection && src.pSelection){\r
-               if (pSelection) free(pSelection);\r
-               pSelection = (BYTE*)malloc(nSize);\r
-               memcpy(pSelection,src.pSelection,nSize);\r
-       }\r
-       //copy the alpha channel\r
-       if (copyalpha && src.pAlpha){\r
-               if (pAlpha) free(pAlpha);\r
-               pAlpha = (BYTE*)malloc(nSize);\r
-               memcpy(pAlpha,src.pAlpha,nSize);\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Copies the image attributes from an existing image.\r
- * - Works only on an empty image, and the image will be still empty.\r
- * - <b> Use it before Create() </b>\r
- */\r
-void CxImage::CopyInfo(const CxImage &src)\r
-{\r
-       if (pDib==NULL) memcpy(&info,&src.info,sizeof(CXIMAGEINFO));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa Copy\r
- */\r
-CxImage& CxImage::operator = (const CxImage& isrc)\r
-{\r
-       if (this != &isrc) Copy(isrc);\r
-       return *this;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Initializes or rebuilds the image.\r
- * \param dwWidth: width\r
- * \param dwHeight: height\r
- * \param wBpp: bit per pixel, can be 1, 4, 8, 24\r
- * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS\r
- * \return pointer to the internal pDib object; NULL if an error occurs.\r
- */\r
-void* CxImage::Create(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype)\r
-{\r
-       // destroy the existing image (if any)\r
-       if (!Destroy())\r
-               return NULL;\r
-\r
-       // prevent further actions if width or height are not vaild <Balabasnia>\r
-       if ((dwWidth == 0) || (dwHeight == 0)){\r
-               strcpy(info.szLastError,"CxImage::Create : width and height must be greater than zero");\r
-               return NULL;\r
-       }\r
-\r
-    // Make sure bits per pixel is valid\r
-    if         (wBpp <= 1)     wBpp = 1;\r
-    else if (wBpp <= 4)        wBpp = 4;\r
-    else if (wBpp <= 8)        wBpp = 8;\r
-    else                               wBpp = 24;\r
-\r
-       // limit memory requirements (and also a check for bad parameters)\r
-       if (((dwWidth*dwHeight*wBpp)>>3) > CXIMAGE_MAX_MEMORY ||\r
-               ((dwWidth*dwHeight*wBpp)/wBpp) != (dwWidth*dwHeight))\r
-       {\r
-               strcpy(info.szLastError,"CXIMAGE_MAX_MEMORY exceeded");\r
-               return NULL;\r
-       }\r
-\r
-       // set the correct bpp value\r
-    switch (wBpp){\r
-        case 1:\r
-            head.biClrUsed = 2;        break;\r
-        case 4:\r
-            head.biClrUsed = 16; break;\r
-        case 8:\r
-            head.biClrUsed = 256; break;\r
-        default:\r
-            head.biClrUsed = 0;\r
-    }\r
-\r
-       //set the common image informations\r
-    info.dwEffWidth = ((((wBpp * dwWidth) + 31) / 32) * 4);\r
-    info.dwType = imagetype;\r
-\r
-    // initialize BITMAPINFOHEADER\r
-       head.biSize = sizeof(BITMAPINFOHEADER); //<ralphw>\r
-    head.biWidth = dwWidth;            // fill in width from parameter\r
-    head.biHeight = dwHeight;  // fill in height from parameter\r
-    head.biPlanes = 1;                 // must be 1\r
-    head.biBitCount = (WORD)wBpp;              // from parameter\r
-    head.biCompression = BI_RGB;    \r
-    head.biSizeImage = info.dwEffWidth * dwHeight;\r
-//    head.biXPelsPerMeter = 0; See SetXDPI\r
-//    head.biYPelsPerMeter = 0; See SetYDPI\r
-//    head.biClrImportant = 0;  See SetClrImportant\r
-\r
-       pDib = malloc(GetSize()); // alloc memory block to store our bitmap\r
-    if (!pDib){\r
-               strcpy(info.szLastError,"CxImage::Create can't allocate memory");\r
-               return NULL;\r
-       }\r
-\r
-       //clear the palette\r
-       RGBQUAD* pal=GetPalette();\r
-       if (pal) memset(pal,0,GetPaletteSize());\r
-       //Destroy the existing selection\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       if (pSelection) SelectionDelete();\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-       //Destroy the existing alpha channel\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (pAlpha) AlphaDelete();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-    // use our bitmap info structure to fill in first part of\r
-    // our DIB with the BITMAPINFOHEADER\r
-    BITMAPINFOHEADER*  lpbi;\r
-       lpbi = (BITMAPINFOHEADER*)(pDib);\r
-    *lpbi = head;\r
-\r
-       info.pImage=GetBits();\r
-\r
-    return pDib; //return handle to the DIB\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return pointer to the image pixels. <b> USE CAREFULLY </b>\r
- */\r
-BYTE* CxImage::GetBits(DWORD row)\r
-{ \r
-       if (pDib){\r
-               if (row) {\r
-                       if (row<(DWORD)head.biHeight){\r
-                               return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize() + (info.dwEffWidth * row));\r
-                       } else {\r
-                               return NULL;\r
-                       }\r
-               } else {\r
-                       return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize());\r
-               }\r
-       }\r
-       return NULL;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return the size in bytes of the internal pDib object\r
- */\r
-long CxImage::GetSize()\r
-{\r
-       return head.biSize + head.biSizeImage + GetPaletteSize();\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if the coordinates are inside the image\r
- * \return true if x and y are both inside the image\r
- */\r
-bool CxImage::IsInside(long x, long y)\r
-{\r
-  return (0<=y && y<head.biHeight && 0<=x && x<head.biWidth);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the image bits to the specified value\r
- * - for indexed images, the output color is set by the palette entries.\r
- * - for RGB images, the output color is a shade of gray.\r
- */\r
-void CxImage::Clear(BYTE bval)\r
-{\r
-       if (pDib == 0) return;\r
-\r
-       if (GetBpp() == 1){\r
-               if (bval > 0) bval = 255;\r
-       }\r
-       if (GetBpp() == 4){\r
-               bval = (BYTE)(17*(0x0F & bval));\r
-       }\r
-\r
-       memset(info.pImage,bval,head.biSizeImage);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Transfers the image from an existing source image. The source becomes empty.\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::Transfer(CxImage &from, bool bTransferFrames /*=true*/)\r
-{\r
-       if (!Destroy())\r
-               return false;\r
-\r
-       memcpy(&head,&from.head,sizeof(BITMAPINFOHEADER));\r
-       memcpy(&info,&from.info,sizeof(CXIMAGEINFO));\r
-\r
-       pDib = from.pDib;\r
-       pSelection = from.pSelection;\r
-       pAlpha = from.pAlpha;\r
-       ppLayers = from.ppLayers;\r
-\r
-       memset(&from.head,0,sizeof(BITMAPINFOHEADER));\r
-       memset(&from.info,0,sizeof(CXIMAGEINFO));\r
-       from.pDib = from.pSelection = from.pAlpha = NULL;\r
-       from.ppLayers = NULL;\r
-\r
-       if (bTransferFrames){\r
-               DestroyFrames();\r
-               ppFrames = from.ppFrames;\r
-               from.ppFrames = NULL;\r
-       }\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * (this) points to the same pDib owned by (*from), the image remains in (*from)\r
- * but (this) has the access to the pixels. <b>Use carefully !!!</b>\r
- */\r
-void CxImage::Ghost(const CxImage *from)\r
-{\r
-       if (from){\r
-               memcpy(&head,&from->head,sizeof(BITMAPINFOHEADER));\r
-               memcpy(&info,&from->info,sizeof(CXIMAGEINFO));\r
-               pDib = from->pDib;\r
-               pSelection = from->pSelection;\r
-               pAlpha = from->pAlpha;\r
-               ppLayers = from->ppLayers;\r
-               ppFrames = from->ppFrames;\r
-               info.pGhost=(CxImage *)from;\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * turns a 16 or 32 bit bitfield image into a RGB image\r
- */\r
-void CxImage::Bitfield2RGB(BYTE *src, DWORD redmask, DWORD greenmask, DWORD bluemask, BYTE bpp)\r
-{\r
-       switch (bpp){\r
-       case 16:\r
-       {\r
-               DWORD ns[3]={0,0,0};\r
-               // compute the number of shift for each mask\r
-               for (int i=0;i<16;i++){\r
-                       if ((redmask>>i)&0x01) ns[0]++;\r
-                       if ((greenmask>>i)&0x01) ns[1]++;\r
-                       if ((bluemask>>i)&0x01) ns[2]++;\r
-               }\r
-               ns[1]+=ns[0]; ns[2]+=ns[1];     ns[0]=8-ns[0]; ns[1]-=8; ns[2]-=8;\r
-               // dword aligned width for 16 bit image\r
-               long effwidth2=(((head.biWidth + 1) / 2) * 4);\r
-               WORD w;\r
-               long y2,y3,x2,x3;\r
-               BYTE *p=info.pImage;\r
-               // scan the buffer in reverse direction to avoid reallocations\r
-               for (long y=head.biHeight-1; y>=0; y--){\r
-                       y2=effwidth2*y;\r
-                       y3=info.dwEffWidth*y;\r
-                       for (long x=head.biWidth-1; x>=0; x--){\r
-                               x2 = 2*x+y2;\r
-                               x3 = 3*x+y3;\r
-                               w = (WORD)(src[x2]+256*src[1+x2]);\r
-                               p[  x3]=(BYTE)((w & bluemask)<<ns[0]);\r
-                               p[1+x3]=(BYTE)((w & greenmask)>>ns[1]);\r
-                               p[2+x3]=(BYTE)((w & redmask)>>ns[2]);\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       case 32:\r
-       {\r
-               DWORD ns[3]={0,0,0};\r
-               // compute the number of shift for each mask\r
-               for (int i=8;i<32;i+=8){\r
-                       if (redmask>>i) ns[0]++;\r
-                       if (greenmask>>i) ns[1]++;\r
-                       if (bluemask>>i) ns[2]++;\r
-               }\r
-               // dword aligned width for 32 bit image\r
-               long effwidth4 = head.biWidth * 4;\r
-               long y4,y3,x4,x3;\r
-               BYTE *p=info.pImage;\r
-               // scan the buffer in reverse direction to avoid reallocations\r
-               for (long y=head.biHeight-1; y>=0; y--){\r
-                       y4=effwidth4*y;\r
-                       y3=info.dwEffWidth*y;\r
-                       for (long x=head.biWidth-1; x>=0; x--){\r
-                               x4 = 4*x+y4;\r
-                               x3 = 3*x+y3;\r
-                               p[  x3]=src[ns[2]+x4];\r
-                               p[1+x3]=src[ns[1]+x4];\r
-                               p[2+x3]=src[ns[0]+x4];\r
-                       }\r
-               }\r
-       }\r
-\r
-       }\r
-       return;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Creates an image from a generic buffer\r
- * \param pArray: source memory buffer\r
- * \param dwWidth: image width\r
- * \param dwHeight: image height\r
- * \param dwBitsperpixel: can be 1,4,8,24,32\r
- * \param dwBytesperline: line alignment, in bytes, for a single row stored in pArray\r
- * \param bFlipImage: tune this parameter if the image is upsidedown\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::CreateFromArray(BYTE* pArray,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage)\r
-{\r
-       if (pArray==NULL) return false;\r
-       if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)||\r
-               (dwBitsperpixel==24)||(dwBitsperpixel==32))) return false;\r
-\r
-       if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false;\r
-\r
-       if (dwBitsperpixel<24) SetGrayPalette();\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (dwBitsperpixel==32) AlphaCreate();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       BYTE *dst,*src;\r
-\r
-       for (DWORD y = 0; y<dwHeight; y++) {\r
-               dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;\r
-               src = pArray + y * dwBytesperline;\r
-               if (dwBitsperpixel==32){\r
-                       for(DWORD x=0;x<dwWidth;x++){\r
-                               *dst++=src[0];\r
-                               *dst++=src[1];\r
-                               *dst++=src[2];\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               AlphaSet(x,(bFlipImage?(dwHeight-1-y):y),src[3]);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                               src+=4;\r
-                       }\r
-               } else {\r
-                       memcpy(dst,src,min(info.dwEffWidth,dwBytesperline));\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa CreateFromArray\r
- */\r
-bool CxImage::CreateFromMatrix(BYTE** ppMatrix,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage)\r
-{\r
-       if (ppMatrix==NULL) return false;\r
-       if (!((dwBitsperpixel==1)||(dwBitsperpixel==4)||(dwBitsperpixel==8)||\r
-               (dwBitsperpixel==24)||(dwBitsperpixel==32))) return false;\r
-\r
-       if (!Create(dwWidth,dwHeight,dwBitsperpixel)) return false;\r
-\r
-       if (dwBitsperpixel<24) SetGrayPalette();\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (dwBitsperpixel==32) AlphaCreate();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       BYTE *dst,*src;\r
-\r
-       for (DWORD y = 0; y<dwHeight; y++) {\r
-               dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;\r
-               src = ppMatrix[y];\r
-               if (src){\r
-                       if (dwBitsperpixel==32){\r
-                               for(DWORD x=0;x<dwWidth;x++){\r
-                                       *dst++=src[0];\r
-                                       *dst++=src[1];\r
-                                       *dst++=src[2];\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       AlphaSet(x,(bFlipImage?(dwHeight-1-y):y),src[3]);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                                       src+=4;\r
-                               }\r
-                       } else {\r
-                               memcpy(dst,src,min(info.dwEffWidth,dwBytesperline));\r
-                       }\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return lightness difference between elem1 and elem2\r
- */\r
-int CxImage::CompareColors(const void *elem1, const void *elem2)\r
-{\r
-       RGBQUAD* c1 = (RGBQUAD*)elem1;\r
-       RGBQUAD* c2 = (RGBQUAD*)elem2;\r
-\r
-       int g1 = (int)RGB2GRAY(c1->rgbRed,c1->rgbGreen,c1->rgbBlue);\r
-       int g2 = (int)RGB2GRAY(c2->rgbRed,c2->rgbGreen,c2->rgbBlue);\r
-       \r
-       return (g1-g2);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * simply calls "if (memblock) free(memblock);".\r
- * Useful when calling Encode for a memory buffer,\r
- * from a DLL compiled with different memory management options.\r
- * CxImage::FreeMemory will use the same memory environment used by Encode. \r
- * \author [livecn]\r
- */\r
-void CxImage::FreeMemory(void* memblock)\r
-{\r
-       if (memblock)\r
-               free(memblock);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-//EOF\r
+// ximage.cpp : main implementation file
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximage.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// CxImage 
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Initialize the internal structures
+ */
+void CxImage::Startup(DWORD 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;
+       SetXDPI(CXIMAGE_DEFAULT_DPI);
+       SetYDPI(CXIMAGE_DEFAULT_DPI);
+
+       short test = 1;
+       info.bLittleEndianHost = (*((char *) &test) == 1);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Empty image constructor
+ * \param imagetype: (optional) set the image format, see ENUM_CXIMAGE_FORMATS
+ */
+CxImage::CxImage(DWORD 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(long 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 (long 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(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD 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());
+       long nSize = head.biWidth * head.biHeight;
+       //copy the selection
+       if (copyselection && src.pSelection){
+               if (pSelection) free(pSelection);
+               pSelection = (BYTE*)malloc(nSize);
+               memcpy(pSelection,src.pSelection,nSize);
+       }
+       //copy the alpha channel
+       if (copyalpha && src.pAlpha){
+               if (pAlpha) free(pAlpha);
+               pAlpha = (BYTE*)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(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD 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 (and also a check for bad parameters)
+       if (((dwWidth*dwHeight*wBpp)>>3) > CXIMAGE_MAX_MEMORY ||
+               ((dwWidth*dwHeight*wBpp)/wBpp) != (dwWidth*dwHeight))
+       {
+               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 = (WORD)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>
+ */
+BYTE* CxImage::GetBits(DWORD row)
+{ 
+       if (pDib){
+               if (row) {
+                       if (row<(DWORD)head.biHeight){
+                               return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize() + (info.dwEffWidth * row));
+                       } else {
+                               return NULL;
+                       }
+               } else {
+                       return ((BYTE*)pDib + *(DWORD*)pDib + GetPaletteSize());
+               }
+       }
+       return NULL;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return the size in bytes of the internal pDib object
+ */
+long 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(long x, long 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(BYTE bval)
+{
+       if (pDib == 0) return;
+
+       if (GetBpp() == 1){
+               if (bval > 0) bval = 255;
+       }
+       if (GetBpp() == 4){
+               bval = (BYTE)(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(BYTE *src, DWORD redmask, DWORD greenmask, DWORD bluemask, BYTE bpp)
+{
+       switch (bpp){
+       case 16:
+       {
+               DWORD ns[3]={0,0,0};
+               // compute the number of shift for each mask
+               for (int 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
+               long effwidth2=(((head.biWidth + 1) / 2) * 4);
+               WORD w;
+               long y2,y3,x2,x3;
+               BYTE *p=info.pImage;
+               // scan the buffer in reverse direction to avoid reallocations
+               for (long y=head.biHeight-1; y>=0; y--){
+                       y2=effwidth2*y;
+                       y3=info.dwEffWidth*y;
+                       for (long x=head.biWidth-1; x>=0; x--){
+                               x2 = 2*x+y2;
+                               x3 = 3*x+y3;
+                               w = (WORD)(src[x2]+256*src[1+x2]);
+                               p[  x3]=(BYTE)((w & bluemask)<<ns[0]);
+                               p[1+x3]=(BYTE)((w & greenmask)>>ns[1]);
+                               p[2+x3]=(BYTE)((w & redmask)>>ns[2]);
+                       }
+               }
+               break;
+       }
+       case 32:
+       {
+               DWORD ns[3]={0,0,0};
+               // compute the number of shift for each mask
+               for (int 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
+               long effwidth4 = head.biWidth * 4;
+               long y4,y3,x4,x3;
+               BYTE *p=info.pImage;
+               // scan the buffer in reverse direction to avoid reallocations
+               for (long y=head.biHeight-1; y>=0; y--){
+                       y4=effwidth4*y;
+                       y3=info.dwEffWidth*y;
+                       for (long 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(BYTE* pArray,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD 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
+
+       BYTE *dst,*src;
+
+       for (DWORD y = 0; y<dwHeight; y++) {
+               dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;
+               src = pArray + y * dwBytesperline;
+               if (dwBitsperpixel==32){
+                       for(DWORD 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(BYTE** ppMatrix,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD 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
+
+       BYTE *dst,*src;
+
+       for (DWORD y = 0; y<dwHeight; y++) {
+               dst = info.pImage + (bFlipImage?(dwHeight-1-y):y) * info.dwEffWidth;
+               src = ppMatrix[y];
+               if (src){
+                       if (dwBitsperpixel==32){
+                               for(DWORD 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
+ */
+int CxImage::CompareColors(const void *elem1, const void *elem2)
+{
+       RGBQUAD* c1 = (RGBQUAD*)elem1;
+       RGBQUAD* c2 = (RGBQUAD*)elem2;
+
+       int g1 = (int)RGB2GRAY(c1->rgbRed,c1->rgbGreen,c1->rgbBlue);
+       int g2 = (int)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
index 80ea91490e4d8b414705a65c460286e0b8fc7160..17d6b9ac58d83570af7746e12f445e6a08908364 100644 (file)
-/*\r
- * File:       ximage.h\r
- * Purpose:    General Purpose Image Class \r
- */\r
-/*\r
-  --------------------------------------------------------------------------------\r
-\r
-       COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:\r
-\r
-       CxImage version 6.0.0 02/Feb/2008\r
-\r
-       CxImage : Copyright (C) 2001 - 2008, Davide Pizzolato\r
-\r
-       Original CImage and CImageIterator implementation are:\r
-       Copyright (C) 1995, Alejandro Aguilar Sierra (asierra(at)servidor(dot)unam(dot)mx)\r
-\r
-       Covered code is provided under this license on an "as is" basis, without warranty\r
-       of any kind, either expressed or implied, including, without limitation, warranties\r
-       that the covered code is free of defects, merchantable, fit for a particular purpose\r
-       or non-infringing. The entire risk as to the quality and performance of the covered\r
-       code is with you. Should any covered code prove defective in any respect, you (not\r
-       the initial developer or any other contributor) assume the cost of any necessary\r
-       servicing, repair or correction. This disclaimer of warranty constitutes an essential\r
-       part of this license. No use of any covered code is authorized hereunder except under\r
-       this disclaimer.\r
-\r
-       Permission is hereby granted to use, copy, modify, and distribute this\r
-       source code, or portions hereof, for any purpose, including commercial applications,\r
-       freely and without fee, subject to the following restrictions: \r
-\r
-       1. The origin of this software must not be misrepresented; you must not\r
-       claim that you wrote the original software. If you use this software\r
-       in a product, an acknowledgment in the product documentation would be\r
-       appreciated but is not required.\r
-\r
-       2. Altered source versions must be plainly marked as such, and must not be\r
-       misrepresented as being the original software.\r
-\r
-       3. This notice may not be removed or altered from any source distribution.\r
-\r
-  --------------------------------------------------------------------------------\r
-\r
-       Other information about CxImage, and the latest version, can be found at the\r
-       CxImage home page: http://www.xdp.it/cximage/\r
-\r
-  --------------------------------------------------------------------------------\r
- */\r
-#if !defined(__CXIMAGE_H)\r
-#define __CXIMAGE_H\r
-\r
-#if _MSC_VER > 1000\r
-#pragma once\r
-#endif \r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-#include "xfile.h"\r
-#include "xiofile.h"\r
-#include "xmemfile.h"\r
-#include "ximadef.h"   //<vho> adjust some #define\r
-\r
-/* see "ximacfg.h" for CxImage configuration options */\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// CxImage formats enumerator\r
-enum ENUM_CXIMAGE_FORMATS{\r
-CXIMAGE_FORMAT_UNKNOWN = 0,\r
-#if CXIMAGE_SUPPORT_BMP\r
-CXIMAGE_FORMAT_BMP = 1,\r
-#endif\r
-#if CXIMAGE_SUPPORT_GIF\r
-CXIMAGE_FORMAT_GIF = 2,\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPG\r
-CXIMAGE_FORMAT_JPG = 3,\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNG\r
-CXIMAGE_FORMAT_PNG = 4,\r
-#endif\r
-#if CXIMAGE_SUPPORT_ICO\r
-CXIMAGE_FORMAT_ICO = 5,\r
-#endif\r
-#if CXIMAGE_SUPPORT_TIF\r
-CXIMAGE_FORMAT_TIF = 6,\r
-#endif\r
-#if CXIMAGE_SUPPORT_TGA\r
-CXIMAGE_FORMAT_TGA = 7,\r
-#endif\r
-#if CXIMAGE_SUPPORT_PCX\r
-CXIMAGE_FORMAT_PCX = 8,\r
-#endif\r
-#if CXIMAGE_SUPPORT_WBMP\r
-CXIMAGE_FORMAT_WBMP = 9,\r
-#endif\r
-#if CXIMAGE_SUPPORT_WMF\r
-CXIMAGE_FORMAT_WMF = 10,\r
-#endif\r
-#if CXIMAGE_SUPPORT_JP2\r
-CXIMAGE_FORMAT_JP2 = 11,\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPC\r
-CXIMAGE_FORMAT_JPC = 12,\r
-#endif\r
-#if CXIMAGE_SUPPORT_PGX\r
-CXIMAGE_FORMAT_PGX = 13,\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNM\r
-CXIMAGE_FORMAT_PNM = 14,\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAS\r
-CXIMAGE_FORMAT_RAS = 15,\r
-#endif\r
-#if CXIMAGE_SUPPORT_JBG\r
-CXIMAGE_FORMAT_JBG = 16,\r
-#endif\r
-#if CXIMAGE_SUPPORT_MNG\r
-CXIMAGE_FORMAT_MNG = 17,\r
-#endif\r
-#if CXIMAGE_SUPPORT_SKA\r
-CXIMAGE_FORMAT_SKA = 18,\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAW\r
-CXIMAGE_FORMAT_RAW = 19,\r
-#endif\r
-CMAX_IMAGE_FORMATS = CXIMAGE_SUPPORT_BMP + CXIMAGE_SUPPORT_GIF + CXIMAGE_SUPPORT_JPG +\r
-                                        CXIMAGE_SUPPORT_PNG + CXIMAGE_SUPPORT_MNG + CXIMAGE_SUPPORT_ICO +\r
-                                        CXIMAGE_SUPPORT_TIF + CXIMAGE_SUPPORT_TGA + CXIMAGE_SUPPORT_PCX +\r
-                                        CXIMAGE_SUPPORT_WBMP+ CXIMAGE_SUPPORT_WMF +\r
-                                        CXIMAGE_SUPPORT_JBG + CXIMAGE_SUPPORT_JP2 + CXIMAGE_SUPPORT_JPC +\r
-                                        CXIMAGE_SUPPORT_PGX + CXIMAGE_SUPPORT_PNM + CXIMAGE_SUPPORT_RAS +\r
-                                        CXIMAGE_SUPPORT_SKA + CXIMAGE_SUPPORT_RAW + 1\r
-};\r
-\r
-/////////////////////////////////////////////////////////////////////////////\r
-// CxImage class\r
-/////////////////////////////////////////////////////////////////////////////\r
-class DLL_EXP CxImage\r
-{\r
-//extensible information collector\r
-typedef struct tagCxImageInfo {\r
-       DWORD   dwEffWidth;                     ///< DWORD aligned scan line width\r
-       BYTE*   pImage;                         ///< THE IMAGE BITS\r
-       CxImage* pGhost;                        ///< if this is a ghost, pGhost points to the body\r
-       CxImage* pParent;                       ///< if this is a layer, pParent points to the body\r
-       DWORD   dwType;                         ///< original image format\r
-       char    szLastError[256];       ///< debugging\r
-       long    nProgress;                      ///< monitor\r
-       long    nEscape;                        ///< escape\r
-       long    nBkgndIndex;            ///< used for GIF, PNG, MNG\r
-       RGBQUAD nBkgndColor;            ///< used for RGB transparency\r
-       float   fQuality;                       ///< used for JPEG, JPEG2000 (0.0f ... 100.0f)\r
-       BYTE    nJpegScale;                     ///< used for JPEG [ignacio]\r
-       long    nFrame;                         ///< used for TIF, GIF, MNG : actual frame\r
-       long    nNumFrames;                     ///< used for TIF, GIF, MNG : total number of frames\r
-       DWORD   dwFrameDelay;           ///< used for GIF, MNG\r
-       long    xDPI;                           ///< horizontal resolution\r
-       long    yDPI;                           ///< vertical resolution\r
-       RECT    rSelectionBox;          ///< bounding rectangle\r
-       BYTE    nAlphaMax;                      ///< max opacity (fade)\r
-       bool    bAlphaPaletteEnabled; ///< true if alpha values in the palette are enabled.\r
-       bool    bEnabled;                       ///< enables the painting functions\r
-       long    xOffset;\r
-       long    yOffset;\r
-       DWORD   dwCodecOpt[CMAX_IMAGE_FORMATS]; ///< for GIF, TIF : 0=def.1=unc,2=fax3,3=fax4,4=pack,5=jpg\r
-       RGBQUAD last_c;                         ///< for GetNearestIndex optimization\r
-       BYTE    last_c_index;\r
-       bool    last_c_isvalid;\r
-       long    nNumLayers;\r
-       DWORD   dwFlags;                        ///< 0x??00000 = reserved, 0x00??0000 = blend mode, 0x0000???? = layer id - user flags\r
-       BYTE    dispmeth;\r
-       bool    bGetAllFrames;\r
-       bool    bLittleEndianHost;\r
-\r
-} CXIMAGEINFO;\r
-\r
-public:\r
-       //public structures\r
-struct rgb_color { BYTE r,g,b; };\r
-\r
-#if CXIMAGE_SUPPORT_WINDOWS\r
-// <VATI> text placement data\r
-// members must be initialized with the InitTextInfo(&this) function.\r
-typedef struct tagCxTextInfo\r
-{\r
-#if defined (_WIN32_WCE)\r
-       TCHAR    text[256];  ///< text for windows CE\r
-#else\r
-       TCHAR    text[4096]; ///< text (char -> TCHAR for UNICODE [Cesar M])\r
-#endif\r
-       LOGFONT  lfont;      ///< font and codepage data\r
-    COLORREF fcolor;     ///< foreground color\r
-    long     align;      ///< DT_CENTER, DT_RIGHT, DT_LEFT aligment for multiline text\r
-    BYTE     smooth;     ///< text smoothing option. Default is false.\r
-    BYTE     opaque;     ///< text has background or hasn't. Default is true.\r
-                                                ///< data for background (ignored if .opaque==FALSE) \r
-    COLORREF bcolor;     ///< background color\r
-    float    b_opacity;  ///< opacity value for background between 0.0-1.0 Default is 0. (opaque)\r
-    BYTE     b_outline;  ///< outline width for background (zero: no outline)\r
-    BYTE     b_round;    ///< rounding radius for background rectangle. % of the height, between 0-50. Default is 10.\r
-                         ///< (backgr. always has a frame: width = 3 pixel + 10% of height by default.)\r
-} CXTEXTINFO;\r
-#endif\r
-\r
-public:\r
-/** \addtogroup Constructors */ //@{\r
-       CxImage(DWORD imagetype = 0);\r
-       CxImage(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype = 0);\r
-       CxImage(const CxImage &src, bool copypixels = true, bool copyselection = true, bool copyalpha = true);\r
-       CxImage(const TCHAR * filename, DWORD imagetype);       // For UNICODE support: char -> TCHAR\r
-       CxImage(FILE * stream, DWORD imagetype);\r
-       CxImage(CxFile * stream, DWORD imagetype);\r
-       CxImage(BYTE * buffer, DWORD size, DWORD imagetype);\r
-       virtual ~CxImage() { DestroyFrames(); Destroy(); };\r
-       CxImage& operator = (const CxImage&);\r
-//@}\r
-\r
-/** \addtogroup Initialization */ //@{\r
-       void*   Create(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype = 0);\r
-       bool    Destroy();\r
-       bool    DestroyFrames();\r
-       void    Clear(BYTE bval=0);\r
-       void    Copy(const CxImage &src, bool copypixels = true, bool copyselection = true, bool copyalpha = true);\r
-       bool    Transfer(CxImage &from, bool bTransferFrames = true);\r
-       bool    CreateFromArray(BYTE* pArray,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage);\r
-       bool    CreateFromMatrix(BYTE** ppMatrix,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage);\r
-       void    FreeMemory(void* memblock);\r
-\r
-       DWORD Dump(BYTE * dst);\r
-       DWORD UnDump(const BYTE * src);\r
-       DWORD DumpSize();\r
-\r
-//@}\r
-\r
-/** \addtogroup Attributes */ //@{\r
-       long    GetSize();\r
-       BYTE*   GetBits(DWORD row = 0);\r
-       BYTE    GetColorType();\r
-       void*   GetDIB() const;\r
-       DWORD   GetHeight() const;\r
-       DWORD   GetWidth() const;\r
-       DWORD   GetEffWidth() const;\r
-       DWORD   GetNumColors() const;\r
-       WORD    GetBpp() const;\r
-       DWORD   GetType() const;\r
-       const char*     GetLastError();\r
-       static const TCHAR* GetVersion();\r
-       static const float GetVersionNumber();\r
-\r
-       DWORD   GetFrameDelay() const;\r
-       void    SetFrameDelay(DWORD d);\r
-\r
-       void    GetOffset(long *x,long *y);\r
-       void    SetOffset(long x,long y);\r
-\r
-       BYTE    GetJpegQuality() const;\r
-       void    SetJpegQuality(BYTE q);\r
-       float   GetJpegQualityF() const;\r
-       void    SetJpegQualityF(float q);\r
-\r
-       BYTE    GetJpegScale() const;\r
-       void    SetJpegScale(BYTE q);\r
-\r
-       long    GetXDPI() const;\r
-       long    GetYDPI() const;\r
-       void    SetXDPI(long dpi);\r
-       void    SetYDPI(long dpi);\r
-\r
-       DWORD   GetClrImportant() const;\r
-       void    SetClrImportant(DWORD ncolors = 0);\r
-\r
-       long    GetProgress() const;\r
-       long    GetEscape() const;\r
-       void    SetProgress(long p);\r
-       void    SetEscape(long i);\r
-\r
-       long    GetTransIndex() const;\r
-       RGBQUAD GetTransColor();\r
-       void    SetTransIndex(long idx);\r
-       void    SetTransColor(RGBQUAD rgb);\r
-       bool    IsTransparent() const;\r
-\r
-       DWORD   GetCodecOption(DWORD imagetype = 0);\r
-       bool    SetCodecOption(DWORD opt, DWORD imagetype = 0);\r
-\r
-       DWORD   GetFlags() const;\r
-       void    SetFlags(DWORD flags, bool bLockReservedFlags = true);\r
-\r
-       BYTE    GetDisposalMethod() const;\r
-       void    SetDisposalMethod(BYTE dm);\r
-\r
-       bool    SetType(DWORD type);\r
-\r
-       static DWORD GetNumTypes();\r
-       static DWORD GetTypeIdFromName(const TCHAR* ext);\r
-       static DWORD GetTypeIdFromIndex(const DWORD index);\r
-       static DWORD GetTypeIndexFromId(const DWORD id);\r
-\r
-       bool    GetRetreiveAllFrames() const;\r
-       void    SetRetreiveAllFrames(bool flag);\r
-       CxImage * GetFrame(long nFrame) const;\r
-\r
-       //void* GetUserData() const {return info.pUserData;}\r
-       //void  SetUserData(void* pUserData) {info.pUserData = pUserData;}\r
-//@}\r
-\r
-/** \addtogroup Palette\r
- * These functions have no effects on RGB images and in this case the returned value is always 0.\r
- * @{ */\r
-       bool    IsGrayScale();\r
-       bool    IsIndexed() const;\r
-       bool    IsSamePalette(CxImage &img, bool bCheckAlpha = true);\r
-       DWORD   GetPaletteSize();\r
-       RGBQUAD* GetPalette() const;\r
-       RGBQUAD GetPaletteColor(BYTE idx);\r
-       bool    GetPaletteColor(BYTE i, BYTE* r, BYTE* g, BYTE* b);\r
-       BYTE    GetNearestIndex(RGBQUAD c);\r
-       void    BlendPalette(COLORREF cr,long perc);\r
-       void    SetGrayPalette();\r
-       void    SetPalette(DWORD n, BYTE *r, BYTE *g, BYTE *b);\r
-       void    SetPalette(RGBQUAD* pPal,DWORD nColors=256);\r
-       void    SetPalette(rgb_color *rgb,DWORD nColors=256);\r
-       void    SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha=0);\r
-       void    SetPaletteColor(BYTE idx, RGBQUAD c);\r
-       void    SetPaletteColor(BYTE idx, COLORREF cr);\r
-       void    SwapIndex(BYTE idx1, BYTE idx2);\r
-       void    SwapRGB2BGR();\r
-       void    SetStdPalette();\r
-//@}\r
-\r
-/** \addtogroup Pixel */ //@{\r
-       bool    IsInside(long x, long y);\r
-       bool    IsTransparent(long x,long y);\r
-       bool    GetTransparentMask(CxImage* iDst = 0);\r
-       RGBQUAD GetPixelColor(long x,long y, bool bGetAlpha = true);\r
-       BYTE    GetPixelIndex(long x,long y);\r
-       BYTE    GetPixelGray(long x, long y);\r
-       void    SetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha = false);\r
-       void    SetPixelColor(long x,long y,COLORREF cr);\r
-       void    SetPixelIndex(long x,long y,BYTE i);\r
-       void    DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha=false);\r
-       void    DrawLine(int StartX, int EndX, int StartY, int EndY, COLORREF cr);\r
-       void    BlendPixelColor(long x,long y,RGBQUAD c, float blend, bool bSetAlpha = false);\r
-//@}\r
-\r
-protected:\r
-/** \addtogroup Protected */ //@{\r
-       BYTE BlindGetPixelIndex(const long x,const long y);\r
-       RGBQUAD BlindGetPixelColor(const long x,const long y, bool bGetAlpha = true);\r
-       void *BlindGetPixelPointer(const long x,const  long y);\r
-       void BlindSetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha = false);\r
-       void BlindSetPixelIndex(long x,long y,BYTE i);\r
-//@}\r
-\r
-public:\r
-\r
-#if CXIMAGE_SUPPORT_INTERPOLATION\r
-/** \addtogroup Interpolation */ //@{\r
-       //overflow methods:\r
-       enum OverflowMethod {\r
-               OM_COLOR=1,\r
-               OM_BACKGROUND=2,\r
-               OM_TRANSPARENT=3,\r
-               OM_WRAP=4,\r
-               OM_REPEAT=5,\r
-               OM_MIRROR=6\r
-       };\r
-       void OverflowCoordinates(float &x, float &y, OverflowMethod const ofMethod);\r
-       void OverflowCoordinates(long  &x, long &y, OverflowMethod const ofMethod);\r
-       RGBQUAD GetPixelColorWithOverflow(long x, long y, OverflowMethod const ofMethod=OM_BACKGROUND, RGBQUAD* const rplColor=0);\r
-       //interpolation methods:\r
-       enum InterpolationMethod {\r
-               IM_NEAREST_NEIGHBOUR=1,\r
-               IM_BILINEAR             =2,\r
-               IM_BSPLINE              =3,\r
-               IM_BICUBIC              =4,\r
-               IM_BICUBIC2             =5,\r
-               IM_LANCZOS              =6,\r
-               IM_BOX                  =7,\r
-               IM_HERMITE              =8,\r
-               IM_HAMMING              =9,\r
-               IM_SINC                 =10,\r
-               IM_BLACKMAN             =11,\r
-               IM_BESSEL               =12,\r
-               IM_GAUSSIAN             =13,\r
-               IM_QUADRATIC    =14,\r
-               IM_MITCHELL             =15,\r
-               IM_CATROM               =16,\r
-               IM_HANNING              =17,\r
-               IM_POWER                =18\r
-       };\r
-       RGBQUAD GetPixelColorInterpolated(float x,float y, InterpolationMethod const inMethod=IM_BILINEAR, OverflowMethod const ofMethod=OM_BACKGROUND, RGBQUAD* const rplColor=0);\r
-       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);\r
-//@}\r
-\r
-protected:\r
-/** \addtogroup Protected */ //@{\r
-       void  AddAveragingCont(RGBQUAD const &color, float const surf, float &rr, float &gg, float &bb, float &aa);\r
-//@}\r
-\r
-/** \addtogroup Kernels */ //@{\r
-public:\r
-       static float KernelBSpline(const float x);\r
-       static float KernelLinear(const float t);\r
-       static float KernelCubic(const float t);\r
-       static float KernelGeneralizedCubic(const float t, const float a=-1);\r
-       static float KernelLanczosSinc(const float t, const float r = 3);\r
-       static float KernelBox(const float x);\r
-       static float KernelHermite(const float x);\r
-       static float KernelHamming(const float x);\r
-       static float KernelSinc(const float x);\r
-       static float KernelBlackman(const float x);\r
-       static float KernelBessel_J1(const float x);\r
-       static float KernelBessel_P1(const float x);\r
-       static float KernelBessel_Q1(const float x);\r
-       static float KernelBessel_Order1(float x);\r
-       static float KernelBessel(const float x);\r
-       static float KernelGaussian(const float x);\r
-       static float KernelQuadratic(const float x);\r
-       static float KernelMitchell(const float x);\r
-       static float KernelCatrom(const float x);\r
-       static float KernelHanning(const float x);\r
-       static float KernelPower(const float x, const float a = 2);\r
-//@}\r
-#endif //CXIMAGE_SUPPORT_INTERPOLATION\r
-       \r
-/** \addtogroup Painting */ //@{\r
-#if CXIMAGE_SUPPORT_WINDOWS\r
-       long    Blt(HDC pDC, long x=0, long y=0);\r
-       HBITMAP MakeBitmap(HDC hdc = NULL);\r
-       HANDLE  CopyToHandle();\r
-       bool    CreateFromHANDLE(HANDLE hMem);          //Windows objects (clipboard)\r
-       bool    CreateFromHBITMAP(HBITMAP hbmp, HPALETTE hpal=0);       //Windows resource\r
-       bool    CreateFromHICON(HICON hico);\r
-       long    Draw(HDC hdc, long x=0, long y=0, long cx = -1, long cy = -1, RECT* pClipRect = 0, bool bSmooth = false);\r
-       long    Draw(HDC hdc, const RECT& rect, RECT* pClipRect=NULL, bool bSmooth = false);\r
-       long    Stretch(HDC hdc, long xoffset, long yoffset, long xsize, long ysize, DWORD dwRop = SRCCOPY);\r
-       long    Stretch(HDC hdc, const RECT& rect, DWORD dwRop = SRCCOPY);\r
-       long    Tile(HDC hdc, RECT *rc);\r
-       long    Draw2(HDC hdc, long x=0, long y=0, long cx = -1, long cy = -1);\r
-       long    Draw2(HDC hdc, const RECT& rect);\r
-       //long  DrawString(HDC hdc, long x, long y, const char* text, RGBQUAD color, const char* font, long lSize=0, long lWeight=400, BYTE bItalic=0, BYTE bUnderline=0, bool bSetAlpha=false);\r
-       long    DrawString(HDC hdc, long x, long y, const TCHAR* text, RGBQUAD color, const TCHAR* font, long lSize=0, long lWeight=400, BYTE bItalic=0, BYTE bUnderline=0, bool bSetAlpha=false);\r
-       // <VATI> extensions\r
-       long    DrawStringEx(HDC hdc, long x, long y, CXTEXTINFO *pTextType, bool bSetAlpha=false );\r
-       void    InitTextInfo( CXTEXTINFO *txt );\r
-#endif //CXIMAGE_SUPPORT_WINDOWS\r
-//@}\r
-\r
-       // file operations\r
-#if CXIMAGE_SUPPORT_DECODE\r
-/** \addtogroup Decode */ //@{\r
-#ifdef WIN32\r
-       //bool Load(LPCWSTR filename, DWORD imagetype=0);\r
-       bool LoadResource(HRSRC hRes, DWORD imagetype, HMODULE hModule=NULL);\r
-#endif\r
-       // For UNICODE support: char -> TCHAR\r
-       bool Load(const TCHAR* filename, DWORD imagetype=0);\r
-       //bool Load(const char * filename, DWORD imagetype=0);\r
-       bool Decode(FILE * hFile, DWORD imagetype);\r
-       bool Decode(CxFile * hFile, DWORD imagetype);\r
-       bool Decode(BYTE * buffer, DWORD size, DWORD imagetype);\r
-\r
-       bool CheckFormat(CxFile * hFile, DWORD imagetype = 0);\r
-       bool CheckFormat(BYTE * buffer, DWORD size, DWORD imagetype = 0);\r
-//@}\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-protected:\r
-/** \addtogroup Protected */ //@{\r
-       bool EncodeSafeCheck(CxFile *hFile);\r
-//@}\r
-\r
-public:\r
-/** \addtogroup Encode */ //@{\r
-#ifdef WIN32\r
-       //bool Save(LPCWSTR filename, DWORD imagetype=0);\r
-#endif\r
-       // For UNICODE support: char -> TCHAR\r
-       bool Save(const TCHAR* filename, DWORD imagetype);\r
-       //bool Save(const char * filename, DWORD imagetype=0);\r
-       bool Encode(FILE * hFile, DWORD imagetype);\r
-       bool Encode(CxFile * hFile, DWORD imagetype);\r
-       bool Encode(CxFile * hFile, CxImage ** pImages, int pagecount, DWORD imagetype);\r
-       bool Encode(FILE *hFile, CxImage ** pImages, int pagecount, DWORD imagetype);\r
-       bool Encode(BYTE * &buffer, long &size, DWORD imagetype);\r
-\r
-       bool Encode2RGBA(CxFile *hFile, bool bFlipY = false);\r
-       bool Encode2RGBA(BYTE * &buffer, long &size, bool bFlipY = false);\r
-//@}\r
-#endif //CXIMAGE_SUPPORT_ENCODE\r
-\r
-/** \addtogroup Attributes */ //@{\r
-       //misc.\r
-       bool IsValid() const;\r
-       bool IsEnabled() const;\r
-       void Enable(bool enable=true);\r
-\r
-       // frame operations\r
-       long GetNumFrames() const;\r
-       long GetFrame() const;\r
-       void SetFrame(long nFrame);\r
-//@}\r
-\r
-#if CXIMAGE_SUPPORT_BASICTRANSFORMATIONS\r
-/** \addtogroup BasicTransformations */ //@{\r
-       bool GrayScale();\r
-       bool Flip(bool bFlipSelection = false, bool bFlipAlpha = true);\r
-       bool Mirror(bool bMirrorSelection = false, bool bMirrorAlpha = true);\r
-       bool Negative();\r
-       bool RotateLeft(CxImage* iDst = NULL);\r
-       bool RotateRight(CxImage* iDst = NULL);\r
-//@}\r
-#endif //CXIMAGE_SUPPORT_BASICTRANSFORMATIONS\r
-\r
-#if CXIMAGE_SUPPORT_TRANSFORMATION\r
-/** \addtogroup Transformations */ //@{\r
-       // image operations\r
-       bool Rotate(float angle, CxImage* iDst = NULL);\r
-       bool Rotate2(float angle, CxImage *iDst = NULL, InterpolationMethod inMethod=IM_BILINEAR,\r
-                OverflowMethod ofMethod=OM_BACKGROUND, RGBQUAD *replColor=0,\r
-                bool const optimizeRightAngles=true, bool const bKeepOriginalSize=false);\r
-       bool Rotate180(CxImage* iDst = NULL);\r
-       bool Resample(long newx, long newy, int mode = 1, CxImage* iDst = NULL);\r
-       bool Resample2(long newx, long newy, InterpolationMethod const inMethod=IM_BICUBIC2,\r
-                               OverflowMethod const ofMethod=OM_REPEAT, CxImage* const iDst = NULL,\r
-                               bool const disableAveraging=false);\r
-       bool DecreaseBpp(DWORD nbit, bool errordiffusion, RGBQUAD* ppal = 0, DWORD clrimportant = 0);\r
-       bool IncreaseBpp(DWORD nbit);\r
-       bool Dither(long method = 0);\r
-       bool Crop(long left, long top, long right, long bottom, CxImage* iDst = NULL);\r
-       bool Crop(const RECT& rect, CxImage* iDst = NULL);\r
-       bool CropRotatedRectangle( long topx, long topy, long width, long height, float angle, CxImage* iDst = NULL);\r
-       bool Skew(float xgain, float ygain, long xpivot=0, long ypivot=0, bool bEnableInterpolation = false);\r
-       bool Expand(long left, long top, long right, long bottom, RGBQUAD canvascolor, CxImage* iDst = 0);\r
-       bool Expand(long newx, long newy, RGBQUAD canvascolor, CxImage* iDst = 0);\r
-       bool Thumbnail(long newx, long newy, RGBQUAD canvascolor, CxImage* iDst = 0);\r
-       bool CircleTransform(int type,long rmax=0,float Koeff=1.0f);\r
-       bool RedEyeRemove(float strength = 0.8f);\r
-       bool QIShrink(long newx, long newy, CxImage* const iDst = NULL, bool bChangeBpp = false);\r
-\r
-//@}\r
-#endif //CXIMAGE_SUPPORT_TRANSFORMATION\r
-\r
-#if CXIMAGE_SUPPORT_DSP\r
-/** \addtogroup DSP */ //@{\r
-       bool Contour();\r
-       bool HistogramStretch(long method = 0, double threshold = 0);\r
-       bool HistogramEqualize();\r
-       bool HistogramNormalize();\r
-       bool HistogramRoot();\r
-       bool HistogramLog();\r
-       long Histogram(long* red, long* green = 0, long* blue = 0, long* gray = 0, long colorspace = 0);\r
-       bool Jitter(long radius=2);\r
-       bool Repair(float radius = 0.25f, long niterations = 1, long colorspace = 0);\r
-       bool Combine(CxImage* r,CxImage* g,CxImage* b,CxImage* a, long colorspace = 0);\r
-       bool FFT2(CxImage* srcReal, CxImage* srcImag, CxImage* dstReal, CxImage* dstImag, long direction = 1, bool bForceFFT = true, bool bMagnitude = true);\r
-       bool Noise(long level);\r
-       bool Median(long Ksize=3);\r
-       bool Gamma(float gamma);\r
-       bool GammaRGB(float gammaR, float gammaG, float gammaB);\r
-       bool ShiftRGB(long r, long g, long b);\r
-       bool Threshold(BYTE level);\r
-       bool Threshold(CxImage* pThresholdMask);\r
-       bool Threshold2(BYTE level, bool bDirection, RGBQUAD nBkgndColor, bool bSetAlpha = false);\r
-       bool Colorize(BYTE hue, BYTE sat, float blend = 1.0f);\r
-       bool Light(long brightness, long contrast = 0);\r
-       float Mean();\r
-       bool Filter(long* kernel, long Ksize, long Kfactor, long Koffset);\r
-       bool Erode(long Ksize=2);\r
-       bool Dilate(long Ksize=2);\r
-       bool Edge(long Ksize=2);\r
-       void HuePalette(float correction=1);\r
-       enum ImageOpType { OpAdd, OpAnd, OpXor, OpOr, OpMask, OpSrcCopy, OpDstCopy, OpSub, OpSrcBlend, OpScreen, OpAvg };\r
-       void Mix(CxImage & imgsrc2, ImageOpType op, long lXOffset = 0, long lYOffset = 0, bool bMixAlpha = false);\r
-       void MixFrom(CxImage & imagesrc2, long lXOffset, long lYOffset);\r
-       bool UnsharpMask(float radius = 5.0f, float amount = 0.5f, int threshold = 0);\r
-       bool Lut(BYTE* pLut);\r
-       bool Lut(BYTE* pLutR, BYTE* pLutG, BYTE* pLutB, BYTE* pLutA = 0);\r
-       bool GaussianBlur(float radius = 1.0f, CxImage* iDst = 0);\r
-       bool TextBlur(BYTE threshold = 100, BYTE decay = 2, BYTE max_depth = 5, bool bBlurHorizontal = true, bool bBlurVertical = true, CxImage* iDst = 0);\r
-       bool SelectiveBlur(float radius = 1.0f, BYTE threshold = 25, CxImage* iDst = 0);\r
-       bool Solarize(BYTE level = 128, bool bLinkedChannels = true);\r
-       bool FloodFill(const long xStart, const long yStart, const RGBQUAD cFillColor, const BYTE tolerance = 0,\r
-                                       BYTE nOpacity = 255, const bool bSelectFilledArea = false, const BYTE nSelectionLevel = 255);\r
-       bool Saturate(const long saturation, const long colorspace = 1);\r
-       bool ConvertColorSpace(const long dstColorSpace, const long srcColorSpace);\r
-       int  OptimalThreshold(long method = 0, RECT * pBox = 0, CxImage* pContrastMask = 0);\r
-       bool AdaptiveThreshold(long method = 0, long nBoxSize = 64, CxImage* pContrastMask = 0, long nBias = 0, float fGlobalLocalBalance = 0.5f);\r
-\r
-//@}\r
-\r
-protected:\r
-/** \addtogroup Protected */ //@{\r
-       bool IsPowerof2(long x);\r
-       bool FFT(int dir,int m,double *x,double *y);\r
-       bool DFT(int dir,long m,double *x1,double *y1,double *x2,double *y2);\r
-       bool RepairChannel(CxImage *ch, float radius);\r
-       // <nipper>\r
-       int gen_convolve_matrix (float radius, float **cmatrix_p);\r
-       float* gen_lookup_table (float *cmatrix, int cmatrix_length);\r
-       void blur_line (float *ctable, float *cmatrix, int cmatrix_length, BYTE* cur_col, BYTE* dest_col, int y, long bytes);\r
-       void blur_text (BYTE threshold, BYTE decay, BYTE max_depth, CxImage* iSrc, CxImage* iDst, BYTE bytes);\r
-//@}\r
-\r
-public:\r
-/** \addtogroup ColorSpace */ //@{\r
-       bool SplitRGB(CxImage* r,CxImage* g,CxImage* b);\r
-       bool SplitYUV(CxImage* y,CxImage* u,CxImage* v);\r
-       bool SplitHSL(CxImage* h,CxImage* s,CxImage* l);\r
-       bool SplitYIQ(CxImage* y,CxImage* i,CxImage* q);\r
-       bool SplitXYZ(CxImage* x,CxImage* y,CxImage* z);\r
-       bool SplitCMYK(CxImage* c,CxImage* m,CxImage* y,CxImage* k);\r
-       static RGBQUAD HSLtoRGB(COLORREF cHSLColor);\r
-       static RGBQUAD RGBtoHSL(RGBQUAD lRGBColor);\r
-       static RGBQUAD HSLtoRGB(RGBQUAD lHSLColor);\r
-       static RGBQUAD YUVtoRGB(RGBQUAD lYUVColor);\r
-       static RGBQUAD RGBtoYUV(RGBQUAD lRGBColor);\r
-       static RGBQUAD YIQtoRGB(RGBQUAD lYIQColor);\r
-       static RGBQUAD RGBtoYIQ(RGBQUAD lRGBColor);\r
-       static RGBQUAD XYZtoRGB(RGBQUAD lXYZColor);\r
-       static RGBQUAD RGBtoXYZ(RGBQUAD lRGBColor);\r
-#endif //CXIMAGE_SUPPORT_DSP\r
-       static RGBQUAD RGBtoRGBQUAD(COLORREF cr);\r
-       static COLORREF RGBQUADtoRGB (RGBQUAD c);\r
-//@}\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-/** \addtogroup Selection */ //@{\r
-       bool SelectionClear(BYTE level = 0);\r
-       bool SelectionCreate();\r
-       bool SelectionDelete();\r
-       bool SelectionInvert();\r
-       bool SelectionMirror();\r
-       bool SelectionFlip();\r
-       bool SelectionAddRect(RECT r, BYTE level = 255);\r
-       bool SelectionAddEllipse(RECT r, BYTE level = 255);\r
-       bool SelectionAddPolygon(POINT *points, long npoints, BYTE level = 255);\r
-       bool SelectionAddColor(RGBQUAD c, BYTE level = 255);\r
-       bool SelectionAddPixel(long x, long y, BYTE level = 255);\r
-       bool SelectionCopy(CxImage &from);\r
-       bool SelectionIsInside(long x, long y);\r
-       bool SelectionIsValid();\r
-       void SelectionGetBox(RECT& r);\r
-       bool SelectionToHRGN(HRGN& region);\r
-       bool SelectionSplit(CxImage *dest);\r
-       BYTE SelectionGet(const long x,const long y);\r
-       bool SelectionSet(CxImage &from);\r
-       void SelectionRebuildBox();\r
-       BYTE* SelectionGetPointer(const long x = 0,const long y = 0);\r
-//@}\r
-\r
-protected:\r
-/** \addtogroup Protected */ //@{\r
-       bool BlindSelectionIsInside(long x, long y);\r
-       BYTE BlindSelectionGet(const long x,const long y);\r
-       void SelectionSet(const long x,const long y,const BYTE level);\r
-//@}\r
-\r
-public:\r
-\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-/** \addtogroup Alpha */ //@{\r
-       void AlphaClear();\r
-       bool AlphaCreate();\r
-       void AlphaDelete();\r
-       void AlphaInvert();\r
-       bool AlphaMirror();\r
-       bool AlphaFlip();\r
-       bool AlphaCopy(CxImage &from);\r
-       bool AlphaSplit(CxImage *dest);\r
-       void AlphaStrip();\r
-       void AlphaSet(BYTE level);\r
-       bool AlphaSet(CxImage &from);\r
-       void AlphaSet(const long x,const long y,const BYTE level);\r
-       BYTE AlphaGet(const long x,const long y);\r
-       BYTE AlphaGetMax() const;\r
-       void AlphaSetMax(BYTE nAlphaMax);\r
-       bool AlphaIsValid();\r
-       BYTE* AlphaGetPointer(const long x = 0,const long y = 0);\r
-       bool AlphaFromTransparency();\r
-\r
-       void AlphaPaletteClear();\r
-       void AlphaPaletteEnable(bool enable=true);\r
-       bool AlphaPaletteIsEnabled();\r
-       bool AlphaPaletteIsValid();\r
-       bool AlphaPaletteSplit(CxImage *dest);\r
-//@}\r
-\r
-protected:\r
-/** \addtogroup Protected */ //@{\r
-       BYTE BlindAlphaGet(const long x,const long y);\r
-//@}\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-public:\r
-#if CXIMAGE_SUPPORT_LAYERS\r
-/** \addtogroup Layers */ //@{\r
-       bool LayerCreate(long position = -1);\r
-       bool LayerDelete(long position = -1);\r
-       void LayerDeleteAll();\r
-       CxImage* GetLayer(long position);\r
-       CxImage* GetParent() const;\r
-       long GetNumLayers() const;\r
-       long LayerDrawAll(HDC hdc, long x=0, long y=0, long cx = -1, long cy = -1, RECT* pClipRect = 0, bool bSmooth = false);\r
-       long LayerDrawAll(HDC hdc, const RECT& rect, RECT* pClipRect=NULL, bool bSmooth = false);\r
-//@}\r
-#endif //CXIMAGE_SUPPORT_LAYERS\r
-\r
-protected:\r
-/** \addtogroup Protected */ //@{\r
-       void Startup(DWORD imagetype = 0);\r
-       void CopyInfo(const CxImage &src);\r
-       void Ghost(const CxImage *src);\r
-       void RGBtoBGR(BYTE *buffer, int length);\r
-       static float HueToRGB(float n1,float n2, float hue);\r
-       void Bitfield2RGB(BYTE *src, DWORD redmask, DWORD greenmask, DWORD bluemask, BYTE bpp);\r
-       static int CompareColors(const void *elem1, const void *elem2);\r
-       short ntohs(const short word);\r
-       long ntohl(const long dword);\r
-       void bihtoh(BITMAPINFOHEADER* bih);\r
-\r
-       void*                           pDib; //contains the header, the palette, the pixels\r
-    BITMAPINFOHEADER    head; //standard header\r
-       CXIMAGEINFO                     info; //extended information\r
-       BYTE*                           pSelection;     //selected region\r
-       BYTE*                           pAlpha; //alpha channel\r
-       CxImage**                       ppLayers; //generic layers\r
-       CxImage**                       ppFrames;\r
-//@}\r
-};\r
-\r
-////////////////////////////////////////////////////////////////////////////\r
-#endif // !defined(__CXIMAGE_H)\r
+/*
+ * File:       ximage.h
+ * Purpose:    General Purpose Image Class 
+ */
+/*
+  --------------------------------------------------------------------------------
+
+       COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+       CxImage version 6.0.0 02/Feb/2008
+
+       CxImage : Copyright (C) 2001 - 2008, 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 
+
+/////////////////////////////////////////////////////////////////////////////
+#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
+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 + 1
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage class
+/////////////////////////////////////////////////////////////////////////////
+class DLL_EXP CxImage
+{
+//extensible information collector
+typedef struct tagCxImageInfo {
+       DWORD   dwEffWidth;                     ///< DWORD aligned scan line width
+       BYTE*   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
+       DWORD   dwType;                         ///< original image format
+       char    szLastError[256];       ///< debugging
+       long    nProgress;                      ///< monitor
+       long    nEscape;                        ///< escape
+       long    nBkgndIndex;            ///< used for GIF, PNG, MNG
+       RGBQUAD nBkgndColor;            ///< used for RGB transparency
+       float   fQuality;                       ///< used for JPEG, JPEG2000 (0.0f ... 100.0f)
+       BYTE    nJpegScale;                     ///< used for JPEG [ignacio]
+       long    nFrame;                         ///< used for TIF, GIF, MNG : actual frame
+       long    nNumFrames;                     ///< used for TIF, GIF, MNG : total number of frames
+       DWORD   dwFrameDelay;           ///< used for GIF, MNG
+       long    xDPI;                           ///< horizontal resolution
+       long    yDPI;                           ///< vertical resolution
+       RECT    rSelectionBox;          ///< bounding rectangle
+       BYTE    nAlphaMax;                      ///< max opacity (fade)
+       bool    bAlphaPaletteEnabled; ///< true if alpha values in the palette are enabled.
+       bool    bEnabled;                       ///< enables the painting functions
+       long    xOffset;
+       long    yOffset;
+       DWORD   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
+       BYTE    last_c_index;
+       bool    last_c_isvalid;
+       long    nNumLayers;
+       DWORD   dwFlags;                        ///< 0x??00000 = reserved, 0x00??0000 = blend mode, 0x0000???? = layer id - user flags
+       BYTE    dispmeth;
+       bool    bGetAllFrames;
+       bool    bLittleEndianHost;
+
+} CXIMAGEINFO;
+
+public:
+       //public structures
+struct rgb_color { BYTE 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
+    long     align;      ///< DT_CENTER, DT_RIGHT, DT_LEFT aligment for multiline text
+    BYTE     smooth;     ///< text smoothing option. Default is false.
+    BYTE     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)
+    BYTE     b_outline;  ///< outline width for background (zero: no outline)
+    BYTE     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(DWORD imagetype = 0);
+       CxImage(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype = 0);
+       CxImage(const CxImage &src, bool copypixels = true, bool copyselection = true, bool copyalpha = true);
+       CxImage(const TCHAR * filename, DWORD imagetype);       // For UNICODE support: char -> TCHAR
+       CxImage(FILE * stream, DWORD imagetype);
+       CxImage(CxFile * stream, DWORD imagetype);
+       CxImage(BYTE * buffer, DWORD size, DWORD imagetype);
+       virtual ~CxImage() { DestroyFrames(); Destroy(); };
+       CxImage& operator = (const CxImage&);
+//@}
+
+/** \addtogroup Initialization */ //@{
+       void*   Create(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype = 0);
+       bool    Destroy();
+       bool    DestroyFrames();
+       void    Clear(BYTE 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(BYTE* pArray,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage);
+       bool    CreateFromMatrix(BYTE** ppMatrix,DWORD dwWidth,DWORD dwHeight,DWORD dwBitsperpixel, DWORD dwBytesperline, bool bFlipImage);
+       void    FreeMemory(void* memblock);
+
+       DWORD Dump(BYTE * dst);
+       DWORD UnDump(const BYTE * src);
+       DWORD DumpSize();
+
+//@}
+
+/** \addtogroup Attributes */ //@{
+       long    GetSize();
+       BYTE*   GetBits(DWORD row = 0);
+       BYTE    GetColorType();
+       void*   GetDIB() const;
+       DWORD   GetHeight() const;
+       DWORD   GetWidth() const;
+       DWORD   GetEffWidth() const;
+       DWORD   GetNumColors() const;
+       WORD    GetBpp() const;
+       DWORD   GetType() const;
+       const char*     GetLastError();
+       static const TCHAR* GetVersion();
+       static const float GetVersionNumber();
+
+       DWORD   GetFrameDelay() const;
+       void    SetFrameDelay(DWORD d);
+
+       void    GetOffset(long *x,long *y);
+       void    SetOffset(long x,long y);
+
+       BYTE    GetJpegQuality() const;
+       void    SetJpegQuality(BYTE q);
+       float   GetJpegQualityF() const;
+       void    SetJpegQualityF(float q);
+
+       BYTE    GetJpegScale() const;
+       void    SetJpegScale(BYTE q);
+
+       long    GetXDPI() const;
+       long    GetYDPI() const;
+       void    SetXDPI(long dpi);
+       void    SetYDPI(long dpi);
+
+       DWORD   GetClrImportant() const;
+       void    SetClrImportant(DWORD ncolors = 0);
+
+       long    GetProgress() const;
+       long    GetEscape() const;
+       void    SetProgress(long p);
+       void    SetEscape(long i);
+
+       long    GetTransIndex() const;
+       RGBQUAD GetTransColor();
+       void    SetTransIndex(long idx);
+       void    SetTransColor(RGBQUAD rgb);
+       bool    IsTransparent() const;
+
+       DWORD   GetCodecOption(DWORD imagetype = 0);
+       bool    SetCodecOption(DWORD opt, DWORD imagetype = 0);
+
+       DWORD   GetFlags() const;
+       void    SetFlags(DWORD flags, bool bLockReservedFlags = true);
+
+       BYTE    GetDisposalMethod() const;
+       void    SetDisposalMethod(BYTE dm);
+
+       bool    SetType(DWORD type);
+
+       static DWORD GetNumTypes();
+       static DWORD GetTypeIdFromName(const TCHAR* ext);
+       static DWORD GetTypeIdFromIndex(const DWORD index);
+       static DWORD GetTypeIndexFromId(const DWORD id);
+
+       bool    GetRetreiveAllFrames() const;
+       void    SetRetreiveAllFrames(bool flag);
+       CxImage * GetFrame(long 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);
+       DWORD   GetPaletteSize();
+       RGBQUAD* GetPalette() const;
+       RGBQUAD GetPaletteColor(BYTE idx);
+       bool    GetPaletteColor(BYTE i, BYTE* r, BYTE* g, BYTE* b);
+       BYTE    GetNearestIndex(RGBQUAD c);
+       void    BlendPalette(COLORREF cr,long perc);
+       void    SetGrayPalette();
+       void    SetPalette(DWORD n, BYTE *r, BYTE *g, BYTE *b);
+       void    SetPalette(RGBQUAD* pPal,DWORD nColors=256);
+       void    SetPalette(rgb_color *rgb,DWORD nColors=256);
+       void    SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha=0);
+       void    SetPaletteColor(BYTE idx, RGBQUAD c);
+       void    SetPaletteColor(BYTE idx, COLORREF cr);
+       void    SwapIndex(BYTE idx1, BYTE idx2);
+       void    SwapRGB2BGR();
+       void    SetStdPalette();
+//@}
+
+/** \addtogroup Pixel */ //@{
+       bool    IsInside(long x, long y);
+       bool    IsTransparent(long x,long y);
+       bool    GetTransparentMask(CxImage* iDst = 0);
+       RGBQUAD GetPixelColor(long x,long y, bool bGetAlpha = true);
+       BYTE    GetPixelIndex(long x,long y);
+       BYTE    GetPixelGray(long x, long y);
+       void    SetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha = false);
+       void    SetPixelColor(long x,long y,COLORREF cr);
+       void    SetPixelIndex(long x,long y,BYTE i);
+       void    DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha=false);
+       void    DrawLine(int StartX, int EndX, int StartY, int EndY, COLORREF cr);
+       void    BlendPixelColor(long x,long y,RGBQUAD c, float blend, bool bSetAlpha = false);
+//@}
+
+protected:
+/** \addtogroup Protected */ //@{
+       BYTE BlindGetPixelIndex(const long x,const long y);
+       RGBQUAD BlindGetPixelColor(const long x,const long y, bool bGetAlpha = true);
+       void *BlindGetPixelPointer(const long x,const  long y);
+       void BlindSetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha = false);
+       void BlindSetPixelIndex(long x,long y,BYTE 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(long  &x, long &y, OverflowMethod const ofMethod);
+       RGBQUAD GetPixelColorWithOverflow(long x, long 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
+       long    Blt(HDC pDC, long x=0, long y=0);
+       HBITMAP MakeBitmap(HDC hdc = NULL);
+       HANDLE  CopyToHandle();
+       bool    CreateFromHANDLE(HANDLE hMem);          //Windows objects (clipboard)
+       bool    CreateFromHBITMAP(HBITMAP hbmp, HPALETTE hpal=0);       //Windows resource
+       bool    CreateFromHICON(HICON hico);
+       long    Draw(HDC hdc, long x=0, long y=0, long cx = -1, long cy = -1, RECT* pClipRect = 0, bool bSmooth = false);
+       long    Draw(HDC hdc, const RECT& rect, RECT* pClipRect=NULL, bool bSmooth = false);
+       long    Stretch(HDC hdc, long xoffset, long yoffset, long xsize, long ysize, DWORD dwRop = SRCCOPY);
+       long    Stretch(HDC hdc, const RECT& rect, DWORD dwRop = SRCCOPY);
+       long    Tile(HDC hdc, RECT *rc);
+       long    Draw2(HDC hdc, long x=0, long y=0, long cx = -1, long cy = -1);
+       long    Draw2(HDC hdc, const RECT& rect);
+       //long  DrawString(HDC hdc, long x, long y, const char* text, RGBQUAD color, const char* font, long lSize=0, long lWeight=400, BYTE bItalic=0, BYTE bUnderline=0, bool bSetAlpha=false);
+       long    DrawString(HDC hdc, long x, long y, const TCHAR* text, RGBQUAD color, const TCHAR* font, long lSize=0, long lWeight=400, BYTE bItalic=0, BYTE bUnderline=0, bool bSetAlpha=false);
+       // <VATI> extensions
+       long    DrawStringEx(HDC hdc, long x, long y, CXTEXTINFO *pTextType, bool bSetAlpha=false );
+       void    InitTextInfo( CXTEXTINFO *txt );
+#endif //CXIMAGE_SUPPORT_WINDOWS
+//@}
+
+       // file operations
+#if CXIMAGE_SUPPORT_DECODE
+/** \addtogroup Decode */ //@{
+#ifdef WIN32
+       //bool Load(LPCWSTR filename, DWORD imagetype=0);
+       bool LoadResource(HRSRC hRes, DWORD imagetype, HMODULE hModule=NULL);
+#endif
+       // For UNICODE support: char -> TCHAR
+       bool Load(const TCHAR* filename, DWORD imagetype=0);
+       //bool Load(const char * filename, DWORD imagetype=0);
+       bool Decode(FILE * hFile, DWORD imagetype);
+       bool Decode(CxFile * hFile, DWORD imagetype);
+       bool Decode(BYTE * buffer, DWORD size, DWORD imagetype);
+
+       bool CheckFormat(CxFile * hFile, DWORD imagetype = 0);
+       bool CheckFormat(BYTE * buffer, DWORD size, DWORD 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, DWORD imagetype=0);
+#endif
+       // For UNICODE support: char -> TCHAR
+       bool Save(const TCHAR* filename, DWORD imagetype);
+       //bool Save(const char * filename, DWORD imagetype=0);
+       bool Encode(FILE * hFile, DWORD imagetype);
+       bool Encode(CxFile * hFile, DWORD imagetype);
+       bool Encode(CxFile * hFile, CxImage ** pImages, int pagecount, DWORD imagetype);
+       bool Encode(FILE *hFile, CxImage ** pImages, int pagecount, DWORD imagetype);
+       bool Encode(BYTE * &buffer, long &size, DWORD imagetype);
+
+       bool Encode2RGBA(CxFile *hFile, bool bFlipY = false);
+       bool Encode2RGBA(BYTE * &buffer, long &size, bool bFlipY = false);
+//@}
+#endif //CXIMAGE_SUPPORT_ENCODE
+
+/** \addtogroup Attributes */ //@{
+       //misc.
+       bool IsValid() const;
+       bool IsEnabled() const;
+       void Enable(bool enable=true);
+
+       // frame operations
+       long GetNumFrames() const;
+       long GetFrame() const;
+       void SetFrame(long 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);
+//@}
+#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(long newx, long newy, int mode = 1, CxImage* iDst = NULL);
+       bool Resample2(long newx, long newy, InterpolationMethod const inMethod=IM_BICUBIC2,
+                               OverflowMethod const ofMethod=OM_REPEAT, CxImage* const iDst = NULL,
+                               bool const disableAveraging=false);
+       bool DecreaseBpp(DWORD nbit, bool errordiffusion, RGBQUAD* ppal = 0, DWORD clrimportant = 0);
+       bool IncreaseBpp(DWORD nbit);
+       bool Dither(long method = 0);
+       bool Crop(long left, long top, long right, long bottom, CxImage* iDst = NULL);
+       bool Crop(const RECT& rect, CxImage* iDst = NULL);
+       bool CropRotatedRectangle( long topx, long topy, long width, long height, float angle, CxImage* iDst = NULL);
+       bool Skew(float xgain, float ygain, long xpivot=0, long ypivot=0, bool bEnableInterpolation = false);
+       bool Expand(long left, long top, long right, long bottom, RGBQUAD canvascolor, CxImage* iDst = 0);
+       bool Expand(long newx, long newy, RGBQUAD canvascolor, CxImage* iDst = 0);
+       bool Thumbnail(long newx, long newy, RGBQUAD canvascolor, CxImage* iDst = 0);
+       bool CircleTransform(int type,long rmax=0,float Koeff=1.0f);
+       bool RedEyeRemove(float strength = 0.8f);
+       bool QIShrink(long newx, long newy, CxImage* const iDst = NULL, bool bChangeBpp = false);
+
+//@}
+#endif //CXIMAGE_SUPPORT_TRANSFORMATION
+
+#if CXIMAGE_SUPPORT_DSP
+/** \addtogroup DSP */ //@{
+       bool Contour();
+       bool HistogramStretch(long method = 0, double threshold = 0);
+       bool HistogramEqualize();
+       bool HistogramNormalize();
+       bool HistogramRoot();
+       bool HistogramLog();
+       long Histogram(long* red, long* green = 0, long* blue = 0, long* gray = 0, long colorspace = 0);
+       bool Jitter(long radius=2);
+       bool Repair(float radius = 0.25f, long niterations = 1, long colorspace = 0);
+       bool Combine(CxImage* r,CxImage* g,CxImage* b,CxImage* a, long colorspace = 0);
+       bool FFT2(CxImage* srcReal, CxImage* srcImag, CxImage* dstReal, CxImage* dstImag, long direction = 1, bool bForceFFT = true, bool bMagnitude = true);
+       bool Noise(long level);
+       bool Median(long Ksize=3);
+       bool Gamma(float gamma);
+       bool GammaRGB(float gammaR, float gammaG, float gammaB);
+       bool ShiftRGB(long r, long g, long b);
+       bool Threshold(BYTE level);
+       bool Threshold(CxImage* pThresholdMask);
+       bool Threshold2(BYTE level, bool bDirection, RGBQUAD nBkgndColor, bool bSetAlpha = false);
+       bool Colorize(BYTE hue, BYTE sat, float blend = 1.0f);
+       bool Light(long brightness, long contrast = 0);
+       float Mean();
+       bool Filter(long* kernel, long Ksize, long Kfactor, long Koffset);
+       bool Erode(long Ksize=2);
+       bool Dilate(long Ksize=2);
+       bool Edge(long Ksize=2);
+       void HuePalette(float correction=1);
+       enum ImageOpType { OpAdd, OpAnd, OpXor, OpOr, OpMask, OpSrcCopy, OpDstCopy, OpSub, OpSrcBlend, OpScreen, OpAvg };
+       void Mix(CxImage & imgsrc2, ImageOpType op, long lXOffset = 0, long lYOffset = 0, bool bMixAlpha = false);
+       void MixFrom(CxImage & imagesrc2, long lXOffset, long lYOffset);
+       bool UnsharpMask(float radius = 5.0f, float amount = 0.5f, int threshold = 0);
+       bool Lut(BYTE* pLut);
+       bool Lut(BYTE* pLutR, BYTE* pLutG, BYTE* pLutB, BYTE* pLutA = 0);
+       bool GaussianBlur(float radius = 1.0f, CxImage* iDst = 0);
+       bool TextBlur(BYTE threshold = 100, BYTE decay = 2, BYTE max_depth = 5, bool bBlurHorizontal = true, bool bBlurVertical = true, CxImage* iDst = 0);
+       bool SelectiveBlur(float radius = 1.0f, BYTE threshold = 25, CxImage* iDst = 0);
+       bool Solarize(BYTE level = 128, bool bLinkedChannels = true);
+       bool FloodFill(const long xStart, const long yStart, const RGBQUAD cFillColor, const BYTE tolerance = 0,
+                                       BYTE nOpacity = 255, const bool bSelectFilledArea = false, const BYTE nSelectionLevel = 255);
+       bool Saturate(const long saturation, const long colorspace = 1);
+       bool ConvertColorSpace(const long dstColorSpace, const long srcColorSpace);
+       int  OptimalThreshold(long method = 0, RECT * pBox = 0, CxImage* pContrastMask = 0);
+       bool AdaptiveThreshold(long method = 0, long nBoxSize = 64, CxImage* pContrastMask = 0, long nBias = 0, float fGlobalLocalBalance = 0.5f);
+
+//@}
+
+protected:
+/** \addtogroup Protected */ //@{
+       bool IsPowerof2(long x);
+       bool FFT(int dir,int m,double *x,double *y);
+       bool DFT(int dir,long m,double *x1,double *y1,double *x2,double *y2);
+       bool RepairChannel(CxImage *ch, float radius);
+       // <nipper>
+       int gen_convolve_matrix (float radius, float **cmatrix_p);
+       float* gen_lookup_table (float *cmatrix, int cmatrix_length);
+       void blur_line (float *ctable, float *cmatrix, int cmatrix_length, BYTE* cur_col, BYTE* dest_col, int y, long bytes);
+       void blur_text (BYTE threshold, BYTE decay, BYTE max_depth, CxImage* iSrc, CxImage* iDst, BYTE 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);
+//@}
+
+#if CXIMAGE_SUPPORT_SELECTION
+/** \addtogroup Selection */ //@{
+       bool SelectionClear(BYTE level = 0);
+       bool SelectionCreate();
+       bool SelectionDelete();
+       bool SelectionInvert();
+       bool SelectionMirror();
+       bool SelectionFlip();
+       bool SelectionAddRect(RECT r, BYTE level = 255);
+       bool SelectionAddEllipse(RECT r, BYTE level = 255);
+       bool SelectionAddPolygon(POINT *points, long npoints, BYTE level = 255);
+       bool SelectionAddColor(RGBQUAD c, BYTE level = 255);
+       bool SelectionAddPixel(long x, long y, BYTE level = 255);
+       bool SelectionCopy(CxImage &from);
+       bool SelectionIsInside(long x, long y);
+       bool SelectionIsValid();
+       void SelectionGetBox(RECT& r);
+       bool SelectionToHRGN(HRGN& region);
+       bool SelectionSplit(CxImage *dest);
+       BYTE SelectionGet(const long x,const long y);
+       bool SelectionSet(CxImage &from);
+       void SelectionRebuildBox();
+       BYTE* SelectionGetPointer(const long x = 0,const long y = 0);
+//@}
+
+protected:
+/** \addtogroup Protected */ //@{
+       bool BlindSelectionIsInside(long x, long y);
+       BYTE BlindSelectionGet(const long x,const long y);
+       void SelectionSet(const long x,const long y,const BYTE 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(BYTE level);
+       bool AlphaSet(CxImage &from);
+       void AlphaSet(const long x,const long y,const BYTE level);
+       BYTE AlphaGet(const long x,const long y);
+       BYTE AlphaGetMax() const;
+       void AlphaSetMax(BYTE nAlphaMax);
+       bool AlphaIsValid();
+       BYTE* AlphaGetPointer(const long x = 0,const long y = 0);
+       bool AlphaFromTransparency();
+
+       void AlphaPaletteClear();
+       void AlphaPaletteEnable(bool enable=true);
+       bool AlphaPaletteIsEnabled();
+       bool AlphaPaletteIsValid();
+       bool AlphaPaletteSplit(CxImage *dest);
+//@}
+
+protected:
+/** \addtogroup Protected */ //@{
+       BYTE BlindAlphaGet(const long x,const long y);
+//@}
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+public:
+#if CXIMAGE_SUPPORT_LAYERS
+/** \addtogroup Layers */ //@{
+       bool LayerCreate(long position = -1);
+       bool LayerDelete(long position = -1);
+       void LayerDeleteAll();
+       CxImage* GetLayer(long position);
+       CxImage* GetParent() const;
+       long GetNumLayers() const;
+       long LayerDrawAll(HDC hdc, long x=0, long y=0, long cx = -1, long cy = -1, RECT* pClipRect = 0, bool bSmooth = false);
+       long LayerDrawAll(HDC hdc, const RECT& rect, RECT* pClipRect=NULL, bool bSmooth = false);
+//@}
+#endif //CXIMAGE_SUPPORT_LAYERS
+
+protected:
+/** \addtogroup Protected */ //@{
+       void Startup(DWORD imagetype = 0);
+       void CopyInfo(const CxImage &src);
+       void Ghost(const CxImage *src);
+       void RGBtoBGR(BYTE *buffer, int length);
+       static float HueToRGB(float n1,float n2, float hue);
+       void Bitfield2RGB(BYTE *src, DWORD redmask, DWORD greenmask, DWORD bluemask, BYTE bpp);
+       static int CompareColors(const void *elem1, const void *elem2);
+       short ntohs(const short word);
+       long ntohl(const long dword);
+       void bihtoh(BITMAPINFOHEADER* bih);
+
+       void*                           pDib; //contains the header, the palette, the pixels
+    BITMAPINFOHEADER    head; //standard header
+       CXIMAGEINFO                     info; //extended information
+       BYTE*                           pSelection;     //selected region
+       BYTE*                           pAlpha; //alpha channel
+       CxImage**                       ppLayers; //generic layers
+       CxImage**                       ppFrames;
+//@}
+};
+
+////////////////////////////////////////////////////////////////////////////
+#endif // !defined(__CXIMAGE_H)
index d119f0fa736b8e19f6b33e97b3093f0c71df137f..740717c730107874c3cbdebaca305a358e185bb0 100644 (file)
-/*\r
- * File:       ximagif.cpp\r
- * Purpose:    Platform Independent GIF Image Class Loader and Writer\r
- * 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximagif.h"\r
-\r
-#if CXIMAGE_SUPPORT_GIF\r
-\r
-#include "ximaiter.h"\r
-\r
-#if defined (_WIN32_WCE)\r
-       #define assert(s)\r
-#else\r
-       #include <assert.h>\r
-#endif\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageGIF::Decode(CxFile *fp)\r
-{\r
-       /* AD - for transparency */\r
-       struct_dscgif dscgif;\r
-       struct_image image;\r
-       struct_TabCol TabCol;\r
-\r
-       if (fp == NULL) return false;\r
-\r
-       fp->Read(&dscgif,/*sizeof(dscgif)*/13,1);\r
-       //if (strncmp(dscgif.header,"GIF8",3)!=0) {\r
-       if (strncmp(dscgif.header,"GIF8",4)!=0) return FALSE;\r
-\r
-       // Avoid Byte order problem with Mac <AMSN>\r
-       dscgif.scrheight = ntohs(dscgif.scrheight);\r
-       dscgif.scrwidth = ntohs(dscgif.scrwidth);\r
-\r
-       if (info.nEscape == -1) {\r
-               // Return output dimensions only\r
-               head.biWidth = dscgif.scrwidth;\r
-               head.biHeight = dscgif.scrheight;\r
-               info.dwType = CXIMAGE_FORMAT_GIF;\r
-               return true;\r
-       }\r
-\r
-       /* AD - for interlace */\r
-       TabCol.sogct = (short)(1 << ((dscgif.pflds & 0x07)+1));\r
-       TabCol.colres = (short)(((dscgif.pflds & 0x70) >> 4) + 1);\r
-\r
-       // assume that the image is a truecolor-gif if\r
-       // 1) no global color map found\r
-       // 2) (image.w, image.h) of the 1st image != (dscgif.scrwidth, dscgif.scrheight)\r
-       long bTrueColor=0;\r
-       CxImage* imaRGB=NULL;\r
-\r
-       // Global colour map?\r
-       if (dscgif.pflds & 0x80)\r
-               fp->Read(TabCol.paleta,sizeof(struct rgb_color)*TabCol.sogct,1);\r
-       else \r
-               bTrueColor++;   //first chance for a truecolor gif\r
-\r
-       long first_transparent_index = 0;\r
-\r
-       int iImage = 0;\r
-       info.nNumFrames=get_num_frames(fp,&TabCol,&dscgif);\r
-\r
-       if ((info.nFrame<0)||(info.nFrame>=info.nNumFrames)) return false;\r
-\r
-       //it cannot be a true color GIF with only one frame\r
-       if (info.nNumFrames == 1)\r
-               bTrueColor=0;\r
-\r
-       char ch;\r
-       bool bPreviousWasNull = true;\r
-       int  prevdispmeth = 0;\r
-       CxImage *previousFrame = NULL;\r
-\r
-       for (BOOL bContinue = TRUE; bContinue; )\r
-       {\r
-               if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;}\r
-\r
-               if (info.nEscape > 0) return false; // <vho> - cancel decoding\r
-               if (bPreviousWasNull || ch==0)\r
-               {\r
-                       switch (ch)\r
-                       {\r
-                       case '!': // extension\r
-                               {\r
-                               bContinue = DecodeExtension(fp);\r
-                               break;\r
-                               }\r
-                       case ',': // image\r
-                               {\r
-                               assert(sizeof(image) == 9);\r
-                               fp->Read(&image,sizeof(image),1);\r
-                               //avoid byte order problems with Solaris <candan> <AMSN>\r
-                               image.l = ntohs(image.l);\r
-                               image.t = ntohs(image.t);\r
-                               image.w = ntohs(image.w);\r
-                               image.h = ntohs(image.h);\r
-\r
-                               if (((image.l + image.w) > dscgif.scrwidth)||((image.t + image.h) > dscgif.scrheight))\r
-                                       break;\r
-\r
-                               // check if it could be a truecolor gif\r
-                               if ((iImage==0) && (image.w != dscgif.scrwidth) && (image.h != dscgif.scrheight))\r
-                                       bTrueColor++;\r
-\r
-                               rgb_color  locpal[256];                         //Local Palette \r
-                               rgb_color* pcurpal = TabCol.paleta;     //Current Palette \r
-                               short palcount = TabCol.sogct;          //Current Palette color count  \r
-\r
-                               // Local colour map?\r
-                               if (image.pf & 0x80) {\r
-                                       palcount = (short)(1 << ((image.pf & 0x07) +1));\r
-                                       assert(3 == sizeof(struct rgb_color));\r
-                                       fp->Read(locpal,sizeof(struct rgb_color)*palcount,1);\r
-                                       pcurpal = locpal;\r
-                               }\r
-\r
-                               int bpp; //<DP> select the correct bit per pixel value\r
-                               if              (palcount <= 2)  bpp = 1;\r
-                               else if (palcount <= 16) bpp = 4;\r
-                               else                                     bpp = 8;\r
-\r
-                               CxImageGIF backimage;\r
-                               backimage.CopyInfo(*this);\r
-                               if (iImage==0){\r
-                                       //first frame: build image background\r
-                                       backimage.Create(dscgif.scrwidth, dscgif.scrheight, bpp, CXIMAGE_FORMAT_GIF);\r
-                                       first_transparent_index = info.nBkgndIndex;\r
-                                       backimage.Clear((BYTE)gifgce.transpcolindex);\r
-                                       previousFrame = new CxImage(backimage);\r
-                                       previousFrame->SetRetreiveAllFrames(false);\r
-                               } else {\r
-                               //generic frame: handle disposal method from previous one\r
-                               /*Values :  0 -   No disposal specified. The decoder is\r
-                                                                 not required to take any action.\r
-                                                       1 -   Do not dispose. The graphic is to be left\r
-                                                                 in place.\r
-                                                       2 -   Restore to background color. The area used by the\r
-                                                                 graphic must be restored to the background color.\r
-                                                       3 -   Restore to previous. The decoder is required to\r
-                                                                 restore the area overwritten by the graphic with\r
-                                                                 what was there prior to rendering the graphic.\r
-                               */\r
-                               /*      backimage.Copy(*this);\r
-                                       if (prevdispmeth==2){\r
-                                               backimage.Clear((BYTE)first_transparent_index);\r
-                                       }*/\r
-                                       if (prevdispmeth==2){\r
-                                               backimage.Copy(*this,false,false,false);\r
-                                               backimage.Clear((BYTE)first_transparent_index);\r
-                                       } else if (prevdispmeth==3) {\r
-                                               backimage.Copy(*this,false,false,false);\r
-                                               backimage.Create(previousFrame->GetWidth(),\r
-                                                       previousFrame->GetHeight(),\r
-                                                       previousFrame->GetBpp(),CXIMAGE_FORMAT_GIF);\r
-                                               memcpy(backimage.GetDIB(),previousFrame->GetDIB(),\r
-                                                       backimage.GetSize());\r
-                                               backimage.AlphaSet(*previousFrame);\r
-                                       } else {\r
-                                               backimage.Copy(*this);\r
-                                       }\r
-                               }\r
-\r
-                               //active frame\r
-                               Create(image.w, image.h, bpp, CXIMAGE_FORMAT_GIF);\r
-\r
-                               if ((image.pf & 0x80) || (dscgif.pflds & 0x80)) {\r
-                                       unsigned char r[256], g[256], b[256];\r
-                                       int i, has_white = 0;\r
-\r
-                                       for (i=0; i < palcount; i++) {\r
-                                               r[i] = pcurpal[i].r;\r
-                                               g[i] = pcurpal[i].g;\r
-                                               b[i] = pcurpal[i].b;\r
-                                               if (RGB(r[i],g[i],b[i]) == 0xFFFFFF) has_white = 1;\r
-                                       }\r
-\r
-                                       // Force transparency colour white...\r
-                                       //if (0) if (info.nBkgndIndex >= 0)\r
-                                       //      r[info.nBkgndIndex] = g[info.nBkgndIndex] = b[info.nBkgndIndex] = 255;\r
-                                       // Fill in with white // AD\r
-                                       if (info.nBkgndIndex >= 0) {\r
-                                               while (i < 256) {\r
-                                                       has_white = 1;\r
-                                                       r[i] = g[i] = b[i] = 255;\r
-                                                       i++;\r
-                                               }\r
-                                       }\r
-\r
-                                       // Force last colour to white...   // AD\r
-                                       //if ((info.nBkgndIndex >= 0) && !has_white) {\r
-                                       //      r[255] = g[255] = b[255] = 255;\r
-                                       //}\r
-\r
-                                       SetPalette((info.nBkgndIndex >= 0 ? 256 : palcount), r, g, b);\r
-                               }\r
-\r
-                               CImageIterator* iter = new CImageIterator(this);\r
-                               iter->Upset();\r
-                               int badcode=0;\r
-                               ibf = GIFBUFTAM+1;\r
-\r
-                               interlaced = image.pf & 0x40;\r
-                               iheight = image.h;\r
-                               istep = 8;\r
-                               iypos = 0;\r
-                               ipass = 0;\r
-\r
-                               long pos_start = fp->Tell();\r
-                               //if (interlaced) log << "Interlaced" << endl;\r
-                               decoder(fp, iter, image.w, badcode);\r
-                               delete iter;\r
-\r
-                               if (info.nEscape) return false; // <vho> - cancel decoding\r
-\r
-                               if (bTrueColor<2 ){ //standard GIF: mix frame with background\r
-                                       backimage.GifMix(*this,image);\r
-                                       backimage.SetTransIndex(first_transparent_index);\r
-                                       backimage.SetPalette(GetPalette());\r
-                                       Transfer(backimage,false);\r
-                               } else { //it's a truecolor gif!\r
-                                       //force full image decoding\r
-                                       info.nFrame=info.nNumFrames-1;\r
-                                       //build the RGB image\r
-                                       if (imaRGB==NULL) imaRGB = new CxImage(dscgif.scrwidth,dscgif.scrheight,24,CXIMAGE_FORMAT_GIF);\r
-                                       //copy the partial image into the full RGB image\r
-                                       for(long y=0;y<image.h;y++){\r
-                                               for (long x=0;x<image.w;x++){\r
-                                                       imaRGB->SetPixelColor(x+image.l,dscgif.scrheight-1-image.t-y,GetPixelColor(x,image.h-y-1));\r
-                                               }\r
-                                       }\r
-                               }\r
-\r
-                               prevdispmeth = (gifgce.flags >> 2) & 0x7;\r
-\r
-                               //restore the correct position in the file for the next image\r
-                               if (badcode){\r
-                                       seek_next_image(fp,pos_start);\r
-                               } else {\r
-                                       fp->Seek(-(ibfmax - ibf - 1), SEEK_CUR);\r
-                               }\r
-\r
-                               if (info.bGetAllFrames && imaRGB == NULL) {\r
-                                       if (iImage == 0) {\r
-                                               DestroyFrames();\r
-                                               ppFrames = new CxImage*[info.nNumFrames];\r
-                                               for(int frameIdx = 0; frameIdx < info.nNumFrames; frameIdx++){\r
-                                                       ppFrames[frameIdx] = NULL;\r
-                                               }\r
-                                       }\r
-                                       ppFrames[iImage] = new CxImage(*this);\r
-                                       ppFrames[iImage]->SetRetreiveAllFrames(false);\r
-                               }\r
-                               if (prevdispmeth <= 1) {\r
-                                       delete previousFrame;\r
-                                       previousFrame = new CxImage(*this);\r
-                                       previousFrame->SetRetreiveAllFrames(false);\r
-                               }\r
-\r
-                               if (info.nFrame==iImage) bContinue=false; else iImage++;\r
-\r
-                               break;\r
-                               }\r
-                       case ';': //terminator\r
-                               bContinue=false;\r
-                               break;\r
-                       default:\r
-                               bPreviousWasNull = (ch==0);\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-\r
-       if (bTrueColor>=2 && imaRGB){\r
-               if (gifgce.flags & 0x1){\r
-                       imaRGB->SetTransColor(GetPaletteColor((BYTE)info.nBkgndIndex));\r
-                       imaRGB->SetTransIndex(0);\r
-               }\r
-               Transfer(*imaRGB);\r
-       }\r
-       delete imaRGB;\r
-\r
-       delete previousFrame;\r
-\r
-       return true;\r
-\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageGIF::DecodeExtension(CxFile *fp)\r
-{\r
-       bool bContinue;\r
-       unsigned char count;\r
-       unsigned char fc;\r
-\r
-       bContinue = (1 == fp->Read(&fc, sizeof(fc), 1));\r
-       if (bContinue) {\r
-               /* AD - for transparency */\r
-               if (fc == 0xF9) {\r
-                       bContinue = (1 == fp->Read(&count, sizeof(count), 1));\r
-                       if (bContinue) {\r
-                               assert(sizeof(gifgce) == 4);\r
-                               bContinue = (count == fp->Read(&gifgce, 1, sizeof(gifgce)));\r
-                               gifgce.delaytime = ntohs(gifgce.delaytime); // Avoid Byte order problem with Mac <AMSN>\r
-                               if (bContinue) {\r
-                                       info.nBkgndIndex  = (gifgce.flags & 0x1) ? gifgce.transpcolindex : -1;\r
-                                       info.dwFrameDelay = gifgce.delaytime;\r
-                                       SetDisposalMethod((gifgce.flags >> 2) & 0x7);\r
-               }       }       }\r
-\r
-               if (fc == 0xFE) { //<DP> Comment block\r
-                       bContinue = (1 == fp->Read(&count, sizeof(count), 1));\r
-                       if (bContinue) {\r
-                               bContinue = (1 == fp->Read(m_comment, count, 1));\r
-                               m_comment[count]='\0';\r
-               }       }\r
-\r
-               if (fc == 0xFF) { //<DP> Application Extension block\r
-                       bContinue = (1 == fp->Read(&count, sizeof(count), 1));\r
-                       if (bContinue) {\r
-                               bContinue = (count==11);\r
-                               if (bContinue){\r
-                                       char AppID[11];\r
-                                       bContinue = (1 == fp->Read(AppID, count, 1));\r
-                                       if (bContinue) {\r
-                                               bContinue = (1 == fp->Read(&count, sizeof(count), 1));\r
-                                               if (bContinue) {\r
-                                                       BYTE* dati = (BYTE*)malloc(count);\r
-                                                       bContinue = (dati!=NULL);\r
-                                                       if (bContinue){\r
-                                                               bContinue = (1 == fp->Read(dati, count, 1));\r
-                                                               if (count>2){\r
-                                                                       m_loops = dati[1]+256*dati[2];\r
-                                                               }\r
-                                                       }\r
-                                                       free(dati);\r
-               }       }       }       }       }\r
-\r
-               while (bContinue && fp->Read(&count, sizeof(count), 1) && count) {\r
-                       //log << "Skipping " << count << " bytes" << endl;\r
-                       fp->Seek(count, SEEK_CUR);\r
-               }\r
-       }\r
-       return bContinue;\r
-\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-//   - This external (machine specific) function is expected to return\r
-// either the next BYTE from the GIF file, or a negative error number.\r
-int CxImageGIF::get_byte(CxFile* file)\r
-{\r
-       if (ibf>=GIFBUFTAM){\r
-               // FW 06/02/98 >>>\r
-               ibfmax = (int)file->Read( buf , 1 , GIFBUFTAM) ;\r
-               if( ibfmax < GIFBUFTAM ) buf[ ibfmax ] = 255 ;\r
-               // FW 06/02/98 <<<\r
-               ibf = 0;\r
-       }\r
-       if (ibf>=ibfmax) return -1; //<DP> avoid overflows\r
-       return buf[ibf++];\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/*   - This function takes a full line of pixels (one BYTE per pixel) and\r
- * displays them (or does whatever your program wants with them...).  It\r
- * should return zero, or negative if an error or some other event occurs\r
- * which would require aborting the decode process...  Note that the length\r
- * passed will almost always be equal to the line length passed to the\r
- * decoder function, with the sole exception occurring when an ending code\r
- * occurs in an odd place in the GIF file...  In any case, linelen will be\r
- * equal to the number of pixels passed...\r
-*/\r
-int CxImageGIF::out_line(CImageIterator* iter, unsigned char *pixels, int linelen)\r
-{\r
-       if (iter == NULL || pixels == NULL)\r
-               return -1;\r
-\r
-       //<DP> for 1 & 4 bpp images, the pixels are compressed\r
-       if (head.biBitCount < 8){\r
-               for(long x=0;x<head.biWidth;x++){\r
-                       BYTE pos;\r
-                       BYTE* iDst= pixels + (x*head.biBitCount >> 3);\r
-                       if (head.biBitCount==4){\r
-                               pos = (BYTE)(4*(1-x%2));\r
-                               *iDst &= ~(0x0F<<pos);\r
-                               *iDst |= ((pixels[x] & 0x0F)<<pos);\r
-                       } else if (head.biBitCount==1){\r
-                               pos = (BYTE)(7-x%8);\r
-                               *iDst &= ~(0x01<<pos);\r
-                               *iDst |= ((pixels[x] & 0x01)<<pos);\r
-                       }\r
-               }\r
-       }\r
-\r
-       /* AD - for interlace */\r
-       if (interlaced) {\r
-               iter->SetY(iheight-iypos-1);\r
-               iter->SetRow(pixels, linelen);\r
-\r
-               if ((iypos += istep) >= iheight) {\r
-                       do {\r
-                               if (ipass++ > 0) istep /= 2;\r
-                               iypos = istep / 2;\r
-                       }\r
-                       while (iypos > iheight);\r
-               }\r
-               return 0;\r
-       } else {\r
-               if (iter->ItOK()) {\r
-                       iter->SetRow(pixels, linelen);\r
-                       (void)iter->PrevRow();\r
-                       return 0;\r
-               } else {\r
-                       //       puts("chafeo");\r
-                       return -1;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-// SaveFile - writes GIF87a gif file\r
-// Randy Spann 6/15/97\r
-// R.Spann@ConnRiver.net\r
-bool CxImageGIF::Encode(CxFile * fp)\r
-{\r
-       if (EncodeSafeCheck(fp)) return false;\r
-\r
-       if(head.biBitCount > 8) {\r
-               //strcpy(info.szLastError,"GIF Images must be 8 bit or less");\r
-               //return FALSE;\r
-               return EncodeRGB(fp);\r
-       }\r
-\r
-       if ( GetNumFrames()>1 && ppFrames ) {\r
-               return Encode(fp, ppFrames, GetNumFrames() );\r
-       }\r
-\r
-       EncodeHeader(fp);\r
-\r
-       EncodeExtension(fp);\r
-\r
-       EncodeComment(fp);\r
-\r
-       EncodeBody(fp);\r
-\r
-       fp->PutC(';'); // Write the GIF file terminator\r
-\r
-       return true; // done!\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageGIF::Encode(CxFile * fp, CxImage ** pImages, int pagecount, bool bLocalColorMap, bool bLocalDispMeth)\r
-{\r
-  cx_try {\r
-       if (fp==NULL) cx_throw("invalid file pointer");\r
-       if (pImages==NULL || pagecount<=0 || pImages[0]==NULL) cx_throw("multipage GIF, no images!");\r
-\r
-       int i;\r
-       for (i=0; i<pagecount; i++){\r
-               if (pImages[i]==NULL)\r
-                       cx_throw("Bad image pointer");\r
-               if (!(pImages[i]->IsValid()))\r
-                       cx_throw("Empty image");\r
-               if (pImages[i]->GetNumColors()==0)\r
-                       cx_throw("CxImageGIF::Encode cannot create animated GIFs with a true color frame. Use DecreaseBpp before");\r
-       }\r
-\r
-       CxImageGIF ghost;\r
-\r
-       //write the first image\r
-       ghost.Ghost(pImages[0]);\r
-       ghost.EncodeHeader(fp);\r
-\r
-       if (m_loops!=1){\r
-               ghost.SetLoops(max(0,m_loops-1));\r
-               ghost.EncodeLoopExtension(fp);\r
-       }\r
-\r
-       if (bLocalDispMeth) {\r
-               ghost.EncodeExtension(fp);\r
-       } else {\r
-               BYTE dm = ghost.GetDisposalMethod();\r
-               ghost.SetDisposalMethod(GetDisposalMethod());\r
-               ghost.EncodeExtension(fp);\r
-               ghost.SetDisposalMethod(dm);\r
-       }\r
-\r
-       EncodeComment(fp);\r
-\r
-       ghost.EncodeBody(fp);\r
-\r
-       for (i=1; i<pagecount; i++){\r
-               ghost.Ghost(pImages[i]);\r
-\r
-               if (bLocalDispMeth) {\r
-                       ghost.EncodeExtension(fp);\r
-               } else {\r
-                       BYTE dm = ghost.GetDisposalMethod();\r
-                       ghost.SetDisposalMethod(GetDisposalMethod());\r
-                       ghost.EncodeExtension(fp);\r
-                       ghost.SetDisposalMethod(dm);\r
-               }\r
-\r
-               ghost.EncodeBody(fp,bLocalColorMap);\r
-       }\r
-\r
-       fp->PutC(';'); // Write the GIF file terminator\r
-\r
-  } cx_catch {\r
-         if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-         return false;\r
-  }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::EncodeHeader(CxFile *fp)\r
-{\r
-       fp->Write("GIF89a",1,6);           //GIF Header\r
-\r
-       Putword(head.biWidth,fp);                          //Logical screen descriptor\r
-       Putword(head.biHeight,fp);\r
-\r
-       BYTE Flags;\r
-       if (head.biClrUsed==0){\r
-               Flags=0x11;\r
-       } else {\r
-               Flags = 0x80;\r
-               Flags |=(head.biBitCount - 1) << 5;\r
-               Flags |=(head.biBitCount - 1);\r
-       }\r
-\r
-       fp->PutC(Flags); //GIF "packed fields"\r
-       fp->PutC(0);     //GIF "BackGround"\r
-       fp->PutC(0);     //GIF "pixel aspect ratio"\r
-\r
-       if (head.biClrUsed!=0){\r
-               RGBQUAD* pPal = GetPalette();\r
-               for(DWORD i=0; i<head.biClrUsed; ++i) \r
-               {\r
-                       fp->PutC(pPal[i].rgbRed);\r
-                       fp->PutC(pPal[i].rgbGreen);\r
-                       fp->PutC(pPal[i].rgbBlue);\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::EncodeExtension(CxFile *fp)\r
-{\r
-       // TRK BEGIN : transparency\r
-       fp->PutC('!');\r
-       fp->PutC(TRANSPARENCY_CODE);\r
-\r
-       gifgce.flags = 0;\r
-       gifgce.flags |= ((info.nBkgndIndex != -1) ? 1 : 0);\r
-       gifgce.flags |= ((GetDisposalMethod() & 0x7) << 2);\r
-       gifgce.delaytime = (WORD)info.dwFrameDelay;\r
-       gifgce.transpcolindex = (BYTE)info.nBkgndIndex;    \r
-\r
-       //Invert byte order in case we use a byte order arch, then set it back <AMSN>\r
-       gifgce.delaytime = ntohs(gifgce.delaytime);\r
-       fp->PutC(sizeof(gifgce));\r
-       fp->Write(&gifgce, sizeof(gifgce), 1);\r
-       gifgce.delaytime = ntohs(gifgce.delaytime);\r
-\r
-       fp->PutC(0);\r
-       // TRK END\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::EncodeLoopExtension(CxFile *fp)\r
-{\r
-       fp->PutC('!');          //byte  1  : 33 (hex 0x21) GIF Extension code\r
-       fp->PutC(255);          //byte  2  : 255 (hex 0xFF) Application Extension Label\r
-       fp->PutC(11);           //byte  3  : 11 (hex (0x0B) Length of Application Block (eleven bytes of data to follow)\r
-       fp->Write("NETSCAPE2.0",11,1);\r
-       fp->PutC(3);                    //byte 15  : 3 (hex 0x03) Length of Data Sub-Block (three bytes of data to follow)\r
-       fp->PutC(1);                    //byte 16  : 1 (hex 0x01)\r
-       Putword(m_loops,fp); //bytes 17 to 18 : 0 to 65535, an unsigned integer in lo-hi byte format. \r
-                                               //This indicate the number of iterations the loop should be executed.\r
-       fp->PutC(0);                    //bytes 19       : 0 (hex 0x00) a Data Sub-block Terminator. \r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::EncodeBody(CxFile *fp, bool bLocalColorMap)\r
-{\r
-       curx = 0;\r
-       cury = head.biHeight - 1;       //because we read the image bottom to top\r
-       CountDown = (long)head.biWidth * (long)head.biHeight;\r
-\r
-       fp->PutC(',');\r
-\r
-       Putword(info.xOffset,fp);\r
-       Putword(info.yOffset,fp);\r
-       Putword(head.biWidth,fp);\r
-       Putword(head.biHeight,fp);\r
-\r
-       BYTE Flags=0x00; //non-interlaced (0x40 = interlaced) (0x80 = LocalColorMap)\r
-       if (bLocalColorMap)     { Flags|=0x80; Flags|=head.biBitCount-1; }\r
-       fp->PutC(Flags);\r
-\r
-       if (bLocalColorMap){\r
-               Flags|=0x87;\r
-               RGBQUAD* pPal = GetPalette();\r
-               for(DWORD i=0; i<head.biClrUsed; ++i) \r
-               {\r
-                       fp->PutC(pPal[i].rgbRed);\r
-                       fp->PutC(pPal[i].rgbGreen);\r
-                       fp->PutC(pPal[i].rgbBlue);\r
-               }\r
-       }\r
-\r
-       int InitCodeSize = head.biBitCount <=1 ? 2 : head.biBitCount;\r
-        // Write out the initial code size\r
-       fp->PutC((BYTE)InitCodeSize);\r
-\r
-        // Go and actually compress the data\r
-       switch (GetCodecOption(CXIMAGE_FORMAT_GIF))\r
-       {\r
-       case 1: //uncompressed\r
-               compressNONE(InitCodeSize+1, fp);\r
-               break;\r
-       case 2: //RLE\r
-               compressRLE(InitCodeSize+1, fp);\r
-               break;\r
-       default: //LZW\r
-               compressLZW(InitCodeSize+1, fp);\r
-       }\r
-\r
-        // Write out a Zero-length packet (to end the series)\r
-       fp->PutC(0);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::EncodeComment(CxFile *fp)\r
-{\r
-       unsigned long n = (unsigned long) strlen(m_comment);\r
-       if (n>255) n=255;\r
-       if (n) {\r
-               fp->PutC('!');  //extension code:\r
-               fp->PutC(254);  //comment extension\r
-               fp->PutC((BYTE)n);      //size of comment\r
-               fp->Write(m_comment,n,1);\r
-               fp->PutC(0);    //block terminator\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageGIF::EncodeRGB(CxFile *fp)\r
-{\r
-       EncodeHeader(fp);\r
-\r
-//     EncodeLoopExtension(fp);\r
-\r
-       EncodeComment(fp);\r
-\r
-       unsigned long w,h;\r
-       w=h=0;\r
-       const long cellw = 17;\r
-       const long cellh = 15;\r
-       CxImageGIF tmp;\r
-       for (long y=0;y<head.biHeight;y+=cellh){\r
-               for (long x=0;x<head.biWidth;x+=cellw){\r
-                       if ((head.biWidth -x)<cellw) w=head.biWidth -x; else w=cellw;\r
-                       if ((head.biHeight-y)<cellh) h=head.biHeight-y; else h=cellh;\r
-\r
-                       if (w!=tmp.GetWidth() || h!=tmp.GetHeight()) tmp.Create(w,h,8);\r
-\r
-                       if (IsTransparent()){\r
-                               tmp.SetTransIndex(0);\r
-                               tmp.SetPaletteColor(0,GetTransColor());\r
-                       }\r
-\r
-                       BYTE i;\r
-                       for (unsigned long j=0;j<h;j++){\r
-                               for (unsigned long k=0;k<w;k++){\r
-                                       i=(BYTE)(1+k+cellw*j);\r
-                                       tmp.SetPaletteColor(i,GetPixelColor(x+k,head.biHeight-y-h+j));\r
-                                       tmp.SetPixelIndex(k,j,tmp.GetNearestIndex(tmp.GetPaletteColor(i)));\r
-                               }\r
-                       }\r
-\r
-                       tmp.SetOffset(x,y);\r
-                       tmp.EncodeExtension(fp);\r
-                       tmp.EncodeBody(fp,true);\r
-               }\r
-       }\r
-\r
-       fp->PutC(';'); // Write the GIF file terminator\r
-\r
-       return true; // done!\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Return the next pixel from the image\r
-// <DP> fix for 1 & 4 bpp images\r
-int CxImageGIF::GifNextPixel( )\r
-{\r
-       if( CountDown == 0 ) return EOF;\r
-       --CountDown;\r
-       int r = GetPixelIndex(curx,cury);\r
-       // Bump the current X position\r
-       ++curx;\r
-       if( curx == head.biWidth ){\r
-               curx = 0;\r
-               cury--;              //bottom to top\r
-       }\r
-       return r;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::Putword(int w, CxFile *fp )\r
-{\r
-       fp->PutC((BYTE)(w & 0xff));\r
-       fp->PutC((BYTE)((w >> 8) & 0xff));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::compressNONE( int init_bits, CxFile* outfile)\r
-{\r
-       register long c;\r
-       register long ent;\r
-\r
-       // g_init_bits - initial number of bits\r
-       // g_outfile   - pointer to output file\r
-       g_init_bits = init_bits;\r
-       g_outfile = outfile;\r
-\r
-        // Set up the necessary values\r
-       cur_accum = cur_bits = clear_flg = 0;\r
-       maxcode = (short)MAXCODE(n_bits = g_init_bits);\r
-       code_int maxmaxcode = (code_int)1 << MAXBITSCODES;\r
-\r
-       ClearCode = (1 << (init_bits - 1));\r
-       EOFCode = ClearCode + 1;\r
-       free_ent = (short)(ClearCode + 2);\r
-\r
-       a_count=0;\r
-       ent = GifNextPixel( );\r
-\r
-       output( (code_int)ClearCode );\r
-\r
-       while ( ent != EOF ) {    \r
-               c = GifNextPixel();\r
-\r
-               output ( (code_int) ent );\r
-               ent = c;\r
-               if ( free_ent < maxmaxcode ) {  \r
-                       free_ent++;\r
-               } else {\r
-                       free_ent=(short)(ClearCode+2);\r
-                       clear_flg=1;\r
-                       output((code_int)ClearCode);\r
-               }\r
-       }\r
-        // Put out the final code.\r
-       output( (code_int) EOFCode );\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-/***************************************************************************\r
- *\r
- *  GIFCOMPR.C       -     LZW GIF Image compression routines\r
- *\r
- ***************************************************************************/\r
-\r
-void CxImageGIF::compressLZW( int init_bits, CxFile* outfile)\r
-{\r
-       register long fcode;\r
-       register long c;\r
-       register long ent;\r
-       register long hshift;\r
-       register long disp;\r
-       register long i;\r
-\r
-       // g_init_bits - initial number of bits\r
-       // g_outfile   - pointer to output file\r
-       g_init_bits = init_bits;\r
-       g_outfile = outfile;\r
-\r
-        // Set up the necessary values\r
-       cur_accum = cur_bits = clear_flg = 0;\r
-       maxcode = (short)MAXCODE(n_bits = g_init_bits);\r
-       code_int maxmaxcode = (code_int)1 << MAXBITSCODES;\r
-\r
-       ClearCode = (1 << (init_bits - 1));\r
-       EOFCode = ClearCode + 1;\r
-       free_ent = (short)(ClearCode + 2);\r
-\r
-       a_count=0;\r
-       ent = GifNextPixel( );\r
-\r
-       hshift = 0;\r
-       for ( fcode = (long) HSIZE;  fcode < 65536L; fcode *= 2L )      ++hshift;\r
-       hshift = 8 - hshift;                /* set hash code range bound */\r
-       cl_hash((long)HSIZE);        /* clear hash table */\r
-       output( (code_int)ClearCode );\r
-\r
-       while ( (c = GifNextPixel( )) != EOF ) {    \r
-\r
-               fcode = (long) (((long) c << MAXBITSCODES) + ent);\r
-               i = (((code_int)c << hshift) ^ ent);    /* xor hashing */\r
-\r
-               if ( HashTabOf (i) == fcode ) {\r
-                       ent = CodeTabOf (i);\r
-                       continue;\r
-               } else if ( (long)HashTabOf (i) < 0 )      /* empty slot */\r
-                       goto nomatch;\r
-               disp = HSIZE - i;           /* secondary hash (after G. Knott) */\r
-               if ( i == 0 )   disp = 1;\r
-probe:\r
-               if ( (i -= disp) < 0 )  i += HSIZE;\r
-               if ( HashTabOf (i) == fcode ) { ent = CodeTabOf (i); continue; }\r
-               if ( (long)HashTabOf (i) > 0 )  goto probe;\r
-nomatch:\r
-               output ( (code_int) ent );\r
-               ent = c;\r
-               if ( free_ent < maxmaxcode ) {  \r
-                       CodeTabOf (i) = free_ent++; /* code -> hashtable */\r
-                       HashTabOf (i) = fcode;\r
-               } else {\r
-                       cl_hash((long)HSIZE);\r
-                       free_ent=(short)(ClearCode+2);\r
-                       clear_flg=1;\r
-                       output((code_int)ClearCode);\r
-               }\r
-       }\r
-        // Put out the final code.\r
-       output( (code_int)ent );\r
-       output( (code_int) EOFCode );\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-static const unsigned long code_mask[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,\r
-                                                                 0x001F, 0x003F, 0x007F, 0x00FF,\r
-                                                                 0x01FF, 0x03FF, 0x07FF, 0x0FFF,\r
-                                                                 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::output( code_int  code)\r
-{\r
-       cur_accum &= code_mask[ cur_bits ];\r
-\r
-       if( cur_bits > 0 )\r
-               cur_accum |= ((long)code << cur_bits);\r
-       else\r
-               cur_accum = code;\r
-\r
-       cur_bits += n_bits;\r
-\r
-       while( cur_bits >= 8 ) {\r
-               char_out( (unsigned int)(cur_accum & 0xff) );\r
-               cur_accum >>= 8;\r
-               cur_bits -= 8;\r
-       }\r
-\r
-       /*\r
-        * If the next entry is going to be too big for the code size,\r
-        * then increase it, if possible.\r
-        */\r
-\r
-       if ( free_ent > maxcode || clear_flg ) {\r
-               if( clear_flg ) {\r
-                       maxcode = (short)MAXCODE(n_bits = g_init_bits);\r
-                       clear_flg = 0;\r
-               } else {\r
-                       ++n_bits;\r
-                       if ( n_bits == MAXBITSCODES )\r
-                               maxcode = (code_int)1 << MAXBITSCODES; /* should NEVER generate this code */\r
-                       else\r
-                               maxcode = (short)MAXCODE(n_bits);\r
-               }\r
-       }\r
-       \r
-       if( code == EOFCode ) {\r
-                // At EOF, write the rest of the buffer.\r
-               while( cur_bits > 0 ) {\r
-                       char_out( (unsigned int)(cur_accum & 0xff) );\r
-                       cur_accum >>= 8;\r
-                       cur_bits -= 8;\r
-               }\r
-       \r
-               flush_char();\r
-               g_outfile->Flush();\r
-\r
-               if(g_outfile->Error()) strcpy(info.szLastError,"Write Error in GIF file");\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-void CxImageGIF::cl_hash(long hsize)\r
-\r
-{\r
-       register long *htab_p = htab+hsize;\r
-\r
-       register long i;\r
-       register long m1 = -1L;\r
-\r
-       i = hsize - 16;\r
-\r
-       do {\r
-               *(htab_p-16)=m1;\r
-               *(htab_p-15)=m1;\r
-               *(htab_p-14)=m1;\r
-               *(htab_p-13)=m1;\r
-               *(htab_p-12)=m1;\r
-               *(htab_p-11)=m1;\r
-               *(htab_p-10)=m1;\r
-               *(htab_p-9)=m1;\r
-               *(htab_p-8)=m1;\r
-               *(htab_p-7)=m1;\r
-               *(htab_p-6)=m1;\r
-               *(htab_p-5)=m1;\r
-               *(htab_p-4)=m1;\r
-               *(htab_p-3)=m1;\r
-               *(htab_p-2)=m1;\r
-               *(htab_p-1)=m1;\r
-               \r
-               htab_p-=16;\r
-       } while ((i-=16) >=0);\r
-\r
-       for (i+=16;i>0;--i)\r
-               *--htab_p=m1;\r
-}\r
-\r
-/*******************************************************************************\r
-*   GIF specific\r
-*******************************************************************************/\r
-\r
-void CxImageGIF::char_out(int c)\r
-{\r
-       accum[a_count++]=(char)c;\r
-       if (a_count >=254)\r
-               flush_char();\r
-}\r
-\r
-void CxImageGIF::flush_char()\r
-{\r
-       if (a_count > 0) {\r
-               g_outfile->PutC((BYTE)a_count);\r
-               g_outfile->Write(accum,1,a_count);\r
-               a_count=0;\r
-       }\r
-}\r
-\r
-/*******************************************************************************\r
-*   GIF decoder\r
-*******************************************************************************/\r
-/* DECODE.C - An LZW decoder for GIF\r
- * Copyright (C) 1987, by Steven A. Bennett\r
- * Copyright (C) 1994, C++ version by Alejandro Aguilar Sierra\r
-*\r
- * Permission is given by the author to freely redistribute and include\r
- * this code in any program as long as this credit is given where due.\r
- *\r
- * In accordance with the above, I want to credit Steve Wilhite who wrote\r
- * the code which this is heavily inspired by...\r
- *\r
- * GIF and 'Graphics Interchange Format' are trademarks (tm) of\r
- * Compuserve, Incorporated, an H&R Block Company.\r
- *\r
- * Release Notes: This file contains a decoder routine for GIF images\r
- * which is similar, structurally, to the original routine by Steve Wilhite.\r
- * It is, however, somewhat noticably faster in most cases.\r
- *\r
- */\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-short CxImageGIF::init_exp(short size)\r
-{\r
-       curr_size = (short)(size + 1);\r
-       top_slot = (short)(1 << curr_size);\r
-       clear = (short)(1 << size);\r
-       ending = (short)(clear + 1);\r
-       slot = newcodes = (short)(ending + 1);\r
-       navail_bytes = nbits_left = 0;\r
-\r
-       memset(stack,0,MAX_CODES + 1);\r
-       memset(prefix,0,MAX_CODES + 1);\r
-       memset(suffix,0,MAX_CODES + 1);\r
-       return(0);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-/* get_next_code()\r
- * - gets the next code from the GIF file.  Returns the code, or else\r
- * a negative number in case of file errors...\r
- */\r
-short CxImageGIF::get_next_code(CxFile* file)\r
-{\r
-       short i, x;\r
-       DWORD ret;\r
-\r
-       if (nbits_left == 0) {\r
-               if (navail_bytes <= 0) {\r
-                       /* Out of bytes in current block, so read next block */\r
-                       pbytes = byte_buff;\r
-                       if ((navail_bytes = (short)get_byte(file)) < 0)\r
-                               return(navail_bytes);\r
-                       else if (navail_bytes) {\r
-                               for (i = 0; i < navail_bytes; ++i) {\r
-                                       if ((x = (short)get_byte(file)) < 0) return(x);\r
-                                       byte_buff[i] = (BYTE)x;\r
-                               }\r
-                       }\r
-               }\r
-               b1 = *pbytes++;\r
-               nbits_left = 8;\r
-               --navail_bytes;\r
-       }\r
-\r
-       if (navail_bytes<0) return ending; // prevent deadlocks (thanks to Mike Melnikov)\r
-\r
-       ret = b1 >> (8 - nbits_left);\r
-       while (curr_size > nbits_left){\r
-               if (navail_bytes <= 0){\r
-                       /* Out of bytes in current block, so read next block*/\r
-                       pbytes = byte_buff;\r
-                       if ((navail_bytes = (short)get_byte(file)) < 0)\r
-                               return(navail_bytes);\r
-                       else if (navail_bytes){\r
-                               for (i = 0; i < navail_bytes; ++i){\r
-                                       if ((x = (short)get_byte(file)) < 0) return(x);\r
-                                       byte_buff[i] = (BYTE)x;\r
-                               }\r
-                       }\r
-               }\r
-               b1 = *pbytes++;\r
-               ret |= b1 << nbits_left;\r
-               nbits_left += 8;\r
-               --navail_bytes;\r
-       }\r
-       nbits_left = (short)(nbits_left-curr_size);\r
-       ret &= code_mask[curr_size];\r
-       return((short)(ret));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-/* short decoder(linewidth)\r
- *    short linewidth;               * Pixels per line of image *\r
- *\r
- * - This function decodes an LZW image, according to the method used\r
- * in the GIF spec.  Every *linewidth* "characters" (ie. pixels) decoded\r
- * will generate a call to out_line(), which is a user specific function\r
- * to display a line of pixels.  The function gets it's codes from\r
- * get_next_code() which is responsible for reading blocks of data and\r
- * seperating them into the proper size codes.  Finally, get_byte() is\r
- * the global routine to read the next BYTE from the GIF file.\r
- *\r
- * It is generally a good idea to have linewidth correspond to the actual\r
- * width of a line (as specified in the Image header) to make your own\r
- * code a bit simpler, but it isn't absolutely necessary.\r
- *\r
- * Returns: 0 if successful, else negative.  (See ERRS.H)\r
- *\r
- */\r
-/* bad_code_count is incremented each time an out of range code is read.\r
- * When this value is non-zero after a decode, your GIF file is probably\r
- * corrupt in some way...\r
- */\r
-short CxImageGIF::decoder(CxFile* file, CImageIterator* iter, short linewidth, int &bad_code_count)\r
-{\r
-       register BYTE *sp, *bufptr;\r
-       BYTE *buf;\r
-       register short code, fc, oc, bufcnt;\r
-       short c, size, ret;\r
-\r
-       /* Initialize for decoding a new image... */\r
-       bad_code_count = 0;\r
-       if ((size = (short)get_byte(file)) < 0) return(size);\r
-       if (size < 2 || 9 < size)                               return(BAD_CODE_SIZE);\r
-       // out_line = outline;\r
-       init_exp(size);\r
-       //printf("L %d %x\n",linewidth,size);\r
-\r
-       /* Initialize in case they forgot to put in a clear code.\r
-        * (This shouldn't happen, but we'll try and decode it anyway...)\r
-        */\r
-       oc = fc = 0;\r
-\r
-   /* Allocate space for the decode buffer */\r
-       if ((buf = new BYTE[linewidth + 1]) == NULL) return(OUT_OF_MEMORY);\r
-\r
-   /* Set up the stack pointer and decode buffer pointer */\r
-       sp = stack;\r
-       bufptr = buf;\r
-       bufcnt = linewidth;\r
-\r
-   /* This is the main loop.  For each code we get we pass through the\r
-       * linked list of prefix codes, pushing the corresponding "character" for\r
-       * each code onto the stack.  When the list reaches a single "character"\r
-       * we push that on the stack too, and then start unstacking each\r
-    * character for output in the correct order.  Special handling is\r
-       * included for the clear code, and the whole thing ends when we get\r
-    * an ending code.\r
-    */\r
-       while ((c = get_next_code(file)) != ending) {\r
-               /* If we had a file error, return without completing the decode*/\r
-               if (c < 0){\r
-                       delete [] buf;\r
-                       return(0);\r
-               }\r
-               /* If the code is a clear code, reinitialize all necessary items.*/\r
-               if (c == clear){\r
-                       curr_size = (short)(size + 1);\r
-                       slot = newcodes;\r
-                       top_slot = (short)(1 << curr_size);\r
-\r
-                       /* Continue reading codes until we get a non-clear code\r
-                       * (Another unlikely, but possible case...)\r
-                       */\r
-                       while ((c = get_next_code(file)) == clear);\r
-\r
-                       /* If we get an ending code immediately after a clear code\r
-                       * (Yet another unlikely case), then break out of the loop.\r
-                       */\r
-                       if (c == ending) break;\r
-\r
-                       /* Finally, if the code is beyond the range of already set codes,\r
-                       * (This one had better NOT happen...  I have no idea what will\r
-                       * result from this, but I doubt it will look good...) then set it\r
-                       * to color zero.\r
-                       */\r
-                       if (c >= slot) c = 0;\r
-                       oc = fc = c;\r
-\r
-                       /* And let us not forget to put the char into the buffer... And\r
-                       * if, on the off chance, we were exactly one pixel from the end\r
-                       * of the line, we have to send the buffer to the out_line()\r
-                       * routine...\r
-                       */\r
-                       *bufptr++ = (BYTE)c;\r
-                       if (--bufcnt == 0) {\r
-                               if (iter) {\r
-                                       if ((ret = (short)out_line(iter, buf, linewidth)) < 0) {\r
-                                               delete [] buf;\r
-                                               return(ret);\r
-                                       }\r
-                               }\r
-                               bufptr = buf;\r
-                               bufcnt = linewidth;\r
-            }\r
-               } else {\r
-                       /* In this case, it's not a clear code or an ending code, so\r
-                       * it must be a code code...  So we can now decode the code into\r
-                       * a stack of character codes. (Clear as mud, right?)\r
-                       */\r
-                       code = c;\r
-\r
-                       /* Here we go again with one of those off chances...  If, on the\r
-                       * off chance, the code we got is beyond the range of those already\r
-                       * set up (Another thing which had better NOT happen...) we trick\r
-                       * the decoder into thinking it actually got the last code read.\r
-                       * (Hmmn... I'm not sure why this works...  But it does...)\r
-                       */\r
-                       if (code >= slot && sp<(stack+MAX_CODES-1)) {\r
-                               if (code > slot)\r
-                                       ++bad_code_count;\r
-                               code = oc;\r
-                               *sp++ = (BYTE)fc;\r
-            }\r
-\r
-                       /* Here we scan back along the linked list of prefixes, pushing\r
-                       * helpless characters (ie. suffixes) onto the stack as we do so.\r
-                       */\r
-                       while (code >= newcodes && sp<(stack+MAX_CODES-1)) {\r
-                               *sp++ = suffix[code];\r
-                               code = prefix[code];\r
-            }\r
-\r
-                       /* Push the last character on the stack, and set up the new\r
-                       * prefix and suffix, and if the required slot number is greater\r
-                       * than that allowed by the current bit size, increase the bit\r
-                       * size.  (NOTE - If we are all full, we *don't* save the new\r
-                       * suffix and prefix...  I'm not certain if this is correct...\r
-                       * it might be more proper to overwrite the last code...\r
-                       */\r
-                       *sp++ = (BYTE)code;\r
-                       if (slot < top_slot){\r
-                               suffix[slot] = (BYTE)(fc = (BYTE)code);\r
-                               prefix[slot++] = oc;\r
-                               oc = c;\r
-            }\r
-                       if (slot >= top_slot){\r
-                               if (curr_size < 12) {\r
-                                       top_slot <<= 1;\r
-                                       ++curr_size;\r
-                               }\r
-                       }\r
-\r
-                       /* Now that we've pushed the decoded string (in reverse order)\r
-                       * onto the stack, lets pop it off and put it into our decode\r
-                       * buffer...  And when the decode buffer is full, write another\r
-                       * line...\r
-                       */\r
-                       while (sp > stack) {\r
-                               *bufptr++ = *(--sp);\r
-                               if (--bufcnt == 0) {\r
-                                       if (iter) {\r
-                                               if ((ret = (short)out_line(iter, buf, linewidth)) < 0) {\r
-                                                       delete [] buf;\r
-                                                       return(ret);\r
-                                               }\r
-                                       }\r
-                                       bufptr = buf;\r
-                                       bufcnt = linewidth;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       ret = 0;\r
-       if (bufcnt != linewidth && iter)\r
-               ret = (short)out_line(iter, buf, (linewidth - bufcnt));\r
-       delete [] buf;\r
-       return(ret);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-int CxImageGIF::get_num_frames(CxFile *fp,struct_TabCol* TabColSrc,struct_dscgif* dscgif)\r
-{\r
-       struct_image image;\r
-\r
-       long pos=fp->Tell();\r
-       int nframes=0;\r
-\r
-       struct_TabCol TempTabCol;\r
-       memcpy(&TempTabCol,TabColSrc,sizeof(struct_TabCol));\r
-\r
-       char ch;\r
-       bool bPreviousWasNull = true;\r
-\r
-       for (BOOL bContinue = TRUE; bContinue; )\r
-       {\r
-               if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;}\r
-\r
-               if (bPreviousWasNull || ch==0)\r
-               {\r
-                       switch (ch)\r
-                       {\r
-                       case '!': // extension\r
-                               {\r
-                               DecodeExtension(fp);\r
-                               break;\r
-                               }\r
-                       case ',': // image\r
-                               {\r
-\r
-                               assert(sizeof(image) == 9);\r
-                               //log << "Image header" << endl;\r
-                               fp->Read(&image,sizeof(image),1);\r
-\r
-                               //avoid byte order problems with Solaris <candan> <AMSN>\r
-                               image.l = ntohs(image.l);\r
-                               image.t = ntohs(image.t);\r
-                               image.w = ntohs(image.w);\r
-                               image.h = ntohs(image.h);\r
-\r
-                               // in case of images with empty screen descriptor, give a last chance\r
-                               if (dscgif->scrwidth==0 && dscgif->scrheight==0){\r
-                                       dscgif->scrwidth = image.w;\r
-                                       dscgif->scrheight = image.h;\r
-                               }\r
-\r
-                               if (((image.l + image.w) > dscgif->scrwidth)||((image.t + image.h) > dscgif->scrheight))\r
-                                       break;\r
-\r
-                               nframes++;\r
-\r
-                               // Local colour map?\r
-                               if (image.pf & 0x80) {\r
-                                       TempTabCol.sogct = (short)(1 << ((image.pf & 0x07) +1));\r
-                                       assert(3 == sizeof(struct rgb_color));\r
-                                       fp->Read(TempTabCol.paleta,sizeof(struct rgb_color)*TempTabCol.sogct,1);\r
-                                       //log << "Local colour map" << endl;\r
-                               }\r
-\r
-                               int badcode=0;\r
-                               ibf = GIFBUFTAM+1;\r
-\r
-                               interlaced = image.pf & 0x40;\r
-                               iheight = image.h;\r
-                               istep = 8;\r
-                               iypos = 0;\r
-                               ipass = 0;\r
-\r
-                               long pos_start = fp->Tell();\r
-\r
-                               //if (interlaced) log << "Interlaced" << endl;\r
-                               decoder(fp, 0, image.w, badcode);\r
-\r
-                               if (badcode){\r
-                                       seek_next_image(fp,pos_start);\r
-                               } else {\r
-                                       fp->Seek(-(ibfmax - ibf - 1), SEEK_CUR);\r
-                               }\r
-               \r
-                               break;\r
-                               }\r
-                       case ';': //terminator\r
-                               bContinue=false;\r
-                               break;\r
-                       default:\r
-                               bPreviousWasNull = (ch==0);\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-\r
-       fp->Seek(pos,SEEK_SET);\r
-       return nframes;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImageGIF::seek_next_image(CxFile* fp, long position)\r
-{\r
-       fp->Seek(position, SEEK_SET);\r
-       char ch1,ch2;\r
-       ch1=ch2=0;\r
-       while(fp->Read(&ch2,sizeof(char),1)>0){\r
-               if (ch1 == 0 && ch2 == ','){\r
-                       fp->Seek(-1,SEEK_CUR);\r
-                       return fp->Tell();\r
-               } else {\r
-                       ch1 = ch2;\r
-               }\r
-       }\r
-       return -1;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::SetLoops(int loops)\r
-{      m_loops=loops; }\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImageGIF::GetLoops()\r
-{      return m_loops; }\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::SetComment(const char* sz_comment_in)\r
-{      if (sz_comment_in) strncpy(m_comment,sz_comment_in,255); }\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::GetComment(char* sz_comment_out)\r
-{      if (sz_comment_out) strncpy(sz_comment_out,m_comment,255); }\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::GifMix(CxImage & imgsrc2, struct_image & imgdesc)\r
-{\r
-       long ymin = max(0,(long)(GetHeight()-imgdesc.t - imgdesc.h));\r
-       long ymax = GetHeight()-imgdesc.t;\r
-       long xmin = imgdesc.l;\r
-       long xmax = min(GetWidth(), (DWORD)(imgdesc.l + imgdesc.w));\r
-\r
-       long ibg2= imgsrc2.GetTransIndex();\r
-    BYTE i2;\r
-\r
-       for(long y = ymin; y < ymax; y++){\r
-               for(long x = xmin; x < xmax; x++){\r
-                       i2 = imgsrc2.GetPixelIndex(x-xmin,y-ymin);\r
-                       if(i2!=ibg2) SetPixelIndex(x,y,i2);\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/*-----------------------------------------------------------------------\r
- *\r
- * miGIF Compression - mouse and ivo's GIF-compatible compression\r
- *\r
- *          -run length encoding compression routines-\r
- *\r
- * Copyright (C) 1998 Hutchison Avenue Software Corporation\r
- *               http://www.hasc.com\r
- *               info@hasc.com\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose and without fee is hereby granted, provided\r
- * that the above copyright notice appear in all copies and that both that\r
- * copyright notice and this permission notice appear in supporting\r
- * documentation.  This software is provided "AS IS." The Hutchison Avenue \r
- * Software Corporation disclaims all warranties, either express or implied, \r
- * including but not limited to implied warranties of merchantability and \r
- * fitness for a particular purpose, with respect to this code and accompanying\r
- * documentation. \r
- * \r
- * The miGIF compression routines do not, strictly speaking, generate files \r
- * conforming to the GIF spec, since the image data is not LZW-compressed \r
- * (this is the point: in order to avoid transgression of the Unisys patent \r
- * on the LZW algorithm.)  However, miGIF generates data streams that any \r
- * reasonably sane LZW decompresser will decompress to what we want.\r
- *\r
- * miGIF compression uses run length encoding. It compresses horizontal runs \r
- * of pixels of the same color. This type of compression gives good results\r
- * on images with many runs, for example images with lines, text and solid \r
- * shapes on a solid-colored background. It gives little or no compression \r
- * on images with few runs, for example digital or scanned photos.\r
- *\r
- *                               der Mouse\r
- *                      mouse@rodents.montreal.qc.ca\r
- *            7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B\r
- *\r
- *                             ivo@hasc.com\r
- *\r
- * The Graphics Interchange Format(c) is the Copyright property of\r
- * CompuServe Incorporated.  GIF(sm) is a Service Mark property of\r
- * CompuServe Incorporated.\r
- *\r
- */\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_clear(struct_RLE* rle)\r
-{\r
-       rle->out_bits = rle->out_bits_init;\r
-       rle->out_bump = rle->out_bump_init;\r
-       rle->out_clear = rle->out_clear_init;\r
-       rle->out_count = 0;\r
-       rle->rl_table_max = 0;\r
-       rle->just_cleared = 1;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_flush(struct_RLE* rle)\r
-{\r
-       if (rle->rl_count == 1){\r
-               rle_output_plain(rle->rl_pixel,rle);\r
-               rle->rl_count = 0;\r
-               return;\r
-       }\r
-       if (rle->just_cleared){\r
-               rle_flush_fromclear(rle->rl_count,rle);\r
-       } else if ((rle->rl_table_max < 2) || (rle->rl_table_pixel != rle->rl_pixel)) {\r
-               rle_flush_clearorrep(rle->rl_count,rle);\r
-       } else {\r
-               rle_flush_withtable(rle->rl_count,rle);\r
-       }\r
-       rle->rl_count = 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_output_plain(int c,struct_RLE* rle)\r
-{\r
-       rle->just_cleared = 0;\r
-       rle_output(c,rle);\r
-       rle->out_count++;\r
-       if (rle->out_count >= rle->out_bump){\r
-               rle->out_bits ++;\r
-               rle->out_bump += 1 << (rle->out_bits - 1);\r
-       }\r
-       if (rle->out_count >= rle->out_clear){\r
-               rle_output(rle->code_clear,rle);\r
-               rle_clear(rle);\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_flush_fromclear(int count,struct_RLE* rle)\r
-{\r
-       int n;\r
-\r
-       rle->out_clear = rle->max_ocodes;\r
-       rle->rl_table_pixel = rle->rl_pixel;\r
-       n = 1;\r
-       while (count > 0){\r
-               if (n == 1){\r
-                       rle->rl_table_max = 1;\r
-                       rle_output_plain(rle->rl_pixel,rle);\r
-                       count --;\r
-               } else if (count >= n){\r
-                       rle->rl_table_max = n;\r
-                       rle_output_plain(rle->rl_basecode+n-2,rle);\r
-                       count -= n;\r
-               } else if (count == 1){\r
-                       rle->rl_table_max ++;\r
-                       rle_output_plain(rle->rl_pixel,rle);\r
-                       count = 0;\r
-               } else {\r
-                       rle->rl_table_max ++;\r
-                       rle_output_plain(rle->rl_basecode+count-2,rle);\r
-                       count = 0;\r
-               }\r
-               if (rle->out_count == 0) n = 1; else n ++;\r
-       }\r
-       rle_reset_out_clear(rle);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_reset_out_clear(struct_RLE* rle)\r
-{\r
-       rle->out_clear = rle->out_clear_init;\r
-       if (rle->out_count >= rle->out_clear){\r
-               rle_output(rle->code_clear,rle);\r
-               rle_clear(rle);\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_flush_withtable(int count, struct_RLE* rle)\r
-{\r
-       int repmax;\r
-       int repleft;\r
-       int leftover;\r
-\r
-       repmax = count / rle->rl_table_max;\r
-       leftover = count % rle->rl_table_max;\r
-       repleft = (leftover ? 1 : 0);\r
-       if (rle->out_count+repmax+repleft > rle->max_ocodes){\r
-               repmax = rle->max_ocodes - rle->out_count;\r
-               leftover = count - (repmax * rle->rl_table_max);\r
-               repleft = 1 + rle_compute_triangle_count(leftover,rle->max_ocodes);\r
-       }\r
-       if (1+rle_compute_triangle_count(count,rle->max_ocodes) < (unsigned int)(repmax+repleft)){\r
-               rle_output(rle->code_clear,rle);\r
-               rle_clear(rle);\r
-               rle_flush_fromclear(count,rle);\r
-               return;\r
-       }\r
-       rle->out_clear = rle->max_ocodes;\r
-       for (;repmax>0;repmax--) rle_output_plain(rle->rl_basecode+rle->rl_table_max-2,rle);\r
-       if (leftover){\r
-               if (rle->just_cleared){\r
-                       rle_flush_fromclear(leftover,rle);\r
-               } else if (leftover == 1){\r
-                       rle_output_plain(rle->rl_pixel,rle);\r
-               } else {\r
-                       rle_output_plain(rle->rl_basecode+leftover-2,rle);\r
-               }\r
-       }\r
-       rle_reset_out_clear(rle);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-unsigned int CxImageGIF::rle_compute_triangle_count(unsigned int count, unsigned int nrepcodes)\r
-{\r
-       unsigned int perrep;\r
-       unsigned int cost;\r
-\r
-       cost = 0;\r
-       perrep = (nrepcodes * (nrepcodes+1)) / 2;\r
-       while (count >= perrep){\r
-               cost += nrepcodes;\r
-               count -= perrep;\r
-       }\r
-       if (count > 0){\r
-               unsigned int n;\r
-               n = rle_isqrt(count);\r
-               while ((n*(n+1)) >= 2*count) n --;\r
-               while ((n*(n+1)) < 2*count) n ++;\r
-               cost += n;\r
-       }\r
-       return(cost);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-unsigned int CxImageGIF::rle_isqrt(unsigned int x)\r
-{\r
-       unsigned int r;\r
-       unsigned int v;\r
-\r
-       if (x < 2) return(x);\r
-       for (v=x,r=1;v;v>>=2,r<<=1) ;\r
-       for( ;; )\r
-       {\r
-               v = ((x / r) + r) / 2;\r
-               if ((v == r) || (v == r+1)) return(r);\r
-               r = v;\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_flush_clearorrep(int count, struct_RLE* rle)\r
-{\r
-       int withclr;\r
-       withclr = 1 + rle_compute_triangle_count(count,rle->max_ocodes);\r
-       if (withclr < count) {\r
-               rle_output(rle->code_clear,rle);\r
-               rle_clear(rle);\r
-               rle_flush_fromclear(count,rle);\r
-       } else {\r
-               for (;count>0;count--) rle_output_plain(rle->rl_pixel,rle);\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_write_block(struct_RLE* rle)\r
-{\r
-       g_outfile->PutC((BYTE)rle->oblen);\r
-       g_outfile->Write(rle->oblock,1,rle->oblen);\r
-       rle->oblen = 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_block_out(unsigned char c, struct_RLE* rle)\r
-{\r
-       rle->oblock[rle->oblen++] = c;\r
-       if (rle->oblen >= 255) rle_write_block(rle);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_block_flush(struct_RLE* rle)\r
-{\r
-       if (rle->oblen > 0) rle_write_block(rle);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_output(int val, struct_RLE* rle)\r
-{\r
-       rle->obuf |= val << rle->obits;\r
-       rle->obits += rle->out_bits;\r
-       while (rle->obits >= 8){\r
-               rle_block_out((unsigned char)(rle->obuf&0xff),rle);\r
-               rle->obuf >>= 8;\r
-               rle->obits -= 8;\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::rle_output_flush(struct_RLE* rle)\r
-{\r
-        if (rle->obits > 0) rle_block_out((unsigned char)(rle->obuf),rle);\r
-        rle_block_flush(rle);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageGIF::compressRLE( int init_bits, CxFile* outfile)\r
-{\r
-       g_init_bits = init_bits;\r
-       g_outfile = outfile;\r
-\r
-       struct_RLE rle;\r
-       rle.code_clear = 1 << (init_bits - 1);\r
-       rle.code_eof = rle.code_clear + 1;\r
-       rle.rl_basecode = rle.code_eof + 1;\r
-       rle.out_bump_init = (1 << (init_bits - 1)) - 1;\r
-       rle.out_clear_init = (init_bits <= 3) ? 9 : (rle.out_bump_init-1);\r
-       rle.out_bits_init = init_bits;\r
-       rle.max_ocodes = (1 << MAXBITSCODES) - ((1 << (rle.out_bits_init - 1)) + 3);\r
-       rle.rl_count = 0;\r
-       rle_clear(&rle);\r
-       rle.obuf = 0;\r
-       rle.obits = 0;\r
-       rle.oblen = 0;\r
-\r
-       rle_output(rle.code_clear,&rle);\r
-\r
-       int c;\r
-       for( ;; )\r
-       {\r
-               c = GifNextPixel();\r
-               if ((rle.rl_count > 0) && (c != rle.rl_pixel)) rle_flush(&rle);\r
-               if (c == EOF) break;\r
-               if (rle.rl_pixel == c){\r
-                       rle.rl_count++;\r
-               } else {\r
-                       rle.rl_pixel = c;\r
-                       rle.rl_count = 1;\r
-               }\r
-       }\r
-       rle_output(rle.code_eof,&rle);\r
-       rle_output_flush(&rle);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_GIF\r
+/*
+ * File:       ximagif.cpp
+ * Purpose:    Platform Independent GIF Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximagif.h"
+
+#if CXIMAGE_SUPPORT_GIF
+
+#include "ximaiter.h"
+
+#if defined (_WIN32_WCE)
+       #define assert(s)
+#else
+       #include <assert.h>
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+#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 = ntohs(dscgif.scrheight);
+       dscgif.scrwidth = 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 = (short)(1 << ((dscgif.pflds & 0x07)+1));
+       TabCol.colres = (short)(((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)
+       long 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
+
+       long first_transparent_index = 0;
+
+       int 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;
+       int  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 = ntohs(image.l);
+                               image.t = ntohs(image.t);
+                               image.w = ntohs(image.w);
+                               image.h = 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 
+                               short palcount = TabCol.sogct;          //Current Palette color count  
+
+                               // Local colour map?
+                               if (image.pf & 0x80) {
+                                       palcount = (short)(1 << ((image.pf & 0x07) +1));
+                                       assert(3 == sizeof(struct rgb_color));
+                                       fp->Read(locpal,sizeof(struct rgb_color)*palcount,1);
+                                       pcurpal = locpal;
+                               }
+
+                               int 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((BYTE)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((BYTE)first_transparent_index);
+                                       }*/
+                                       if (prevdispmeth==2){
+                                               backimage.Copy(*this,false,false,false);
+                                               backimage.Clear((BYTE)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)) {
+                                       unsigned char r[256], g[256], b[256];
+                                       int 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();
+                               int badcode=0;
+                               ibf = GIFBUFTAM+1;
+
+                               interlaced = image.pf & 0x40;
+                               iheight = image.h;
+                               istep = 8;
+                               iypos = 0;
+                               ipass = 0;
+
+                               long 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.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(long y=0;y<image.h;y++){
+                                               for (long 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(int 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) 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((BYTE)info.nBkgndIndex));
+                       imaRGB->SetTransIndex(0);
+               }
+               Transfer(*imaRGB);
+       }
+       delete imaRGB;
+
+       delete previousFrame;
+
+       return true;
+
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageGIF::DecodeExtension(CxFile *fp)
+{
+       bool bContinue;
+       unsigned char count;
+       unsigned char 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 = 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) {
+                                                       BYTE* dati = (BYTE*)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 BYTE from the GIF file, or a negative error number.
+int CxImageGIF::get_byte(CxFile* file)
+{
+       if (ibf>=GIFBUFTAM){
+               // FW 06/02/98 >>>
+               ibfmax = (int)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 BYTE 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...
+*/
+int CxImageGIF::out_line(CImageIterator* iter, unsigned char *pixels, int linelen)
+{
+       if (iter == NULL || pixels == NULL)
+               return -1;
+
+       //<DP> for 1 & 4 bpp images, the pixels are compressed
+       if (head.biBitCount < 8){
+               for(long x=0;x<head.biWidth;x++){
+                       BYTE pos;
+                       BYTE* iDst= pixels + (x*head.biBitCount >> 3);
+                       if (head.biBitCount==4){
+                               pos = (BYTE)(4*(1-x%2));
+                               *iDst &= ~(0x0F<<pos);
+                               *iDst |= ((pixels[x] & 0x0F)<<pos);
+                       } else if (head.biBitCount==1){
+                               pos = (BYTE)(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, int 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!");
+
+       int 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 {
+               BYTE 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 {
+                       BYTE 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);
+
+       BYTE 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(DWORD 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 = (WORD)info.dwFrameDelay;
+       gifgce.transpcolindex = (BYTE)info.nBkgndIndex;    
+
+       //Invert byte order in case we use a byte order arch, then set it back <AMSN>
+       gifgce.delaytime = ntohs(gifgce.delaytime);
+       fp->PutC(sizeof(gifgce));
+       fp->Write(&gifgce, sizeof(gifgce), 1);
+       gifgce.delaytime = 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 = (long)head.biWidth * (long)head.biHeight;
+
+       fp->PutC(',');
+
+       Putword(info.xOffset,fp);
+       Putword(info.yOffset,fp);
+       Putword(head.biWidth,fp);
+       Putword(head.biHeight,fp);
+
+       BYTE 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(DWORD i=0; i<head.biClrUsed; ++i) 
+               {
+                       fp->PutC(pPal[i].rgbRed);
+                       fp->PutC(pPal[i].rgbGreen);
+                       fp->PutC(pPal[i].rgbBlue);
+               }
+       }
+
+       int InitCodeSize = head.biBitCount <=1 ? 2 : head.biBitCount;
+        // Write out the initial code size
+       fp->PutC((BYTE)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)
+{
+       unsigned long n = (unsigned long) strlen(m_comment);
+       if (n>255) n=255;
+       if (n) {
+               fp->PutC('!');  //extension code:
+               fp->PutC(254);  //comment extension
+               fp->PutC((BYTE)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);
+
+       unsigned long w,h;
+       w=h=0;
+       const long cellw = 17;
+       const long cellh = 15;
+       CxImageGIF tmp;
+       for (long y=0;y<head.biHeight;y+=cellh){
+               for (long 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());
+                       }
+
+                       BYTE i;
+                       for (unsigned long j=0;j<h;j++){
+                               for (unsigned long k=0;k<w;k++){
+                                       i=(BYTE)(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
+int CxImageGIF::GifNextPixel( )
+{
+       if( CountDown == 0 ) return EOF;
+       --CountDown;
+       int 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(int w, CxFile *fp )
+{
+       fp->PutC((BYTE)(w & 0xff));
+       fp->PutC((BYTE)((w >> 8) & 0xff));
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::compressNONE( int init_bits, CxFile* outfile)
+{
+       register long c;
+       register long 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 = (short)MAXCODE(n_bits = g_init_bits);
+       code_int maxmaxcode = (code_int)1 << MAXBITSCODES;
+
+       ClearCode = (1 << (init_bits - 1));
+       EOFCode = ClearCode + 1;
+       free_ent = (short)(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=(short)(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( int init_bits, CxFile* outfile)
+{
+       register long fcode;
+       register long c;
+       register long ent;
+       register long hshift;
+       register long disp;
+       register long 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 = (short)MAXCODE(n_bits = g_init_bits);
+       code_int maxmaxcode = (code_int)1 << MAXBITSCODES;
+
+       ClearCode = (1 << (init_bits - 1));
+       EOFCode = ClearCode + 1;
+       free_ent = (short)(ClearCode + 2);
+
+       a_count=0;
+       ent = GifNextPixel( );
+
+       hshift = 0;
+       for ( fcode = (long) HSIZE;  fcode < 65536L; fcode *= 2L )      ++hshift;
+       hshift = 8 - hshift;                /* set hash code range bound */
+       cl_hash((long)HSIZE);        /* clear hash table */
+       output( (code_int)ClearCode );
+
+       while ( (c = GifNextPixel( )) != EOF ) {    
+
+               fcode = (long) (((long) c << MAXBITSCODES) + ent);
+               i = (((code_int)c << hshift) ^ ent);    /* xor hashing */
+
+               if ( HashTabOf (i) == fcode ) {
+                       ent = CodeTabOf (i);
+                       continue;
+               } else if ( (long)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 ( (long)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((long)HSIZE);
+                       free_ent=(short)(ClearCode+2);
+                       clear_flg=1;
+                       output((code_int)ClearCode);
+               }
+       }
+        // Put out the final code.
+       output( (code_int)ent );
+       output( (code_int) EOFCode );
+}
+////////////////////////////////////////////////////////////////////////////////
+
+static const unsigned long 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 |= ((long)code << cur_bits);
+       else
+               cur_accum = code;
+
+       cur_bits += n_bits;
+
+       while( cur_bits >= 8 ) {
+               char_out( (unsigned int)(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 = (short)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 = (short)MAXCODE(n_bits);
+               }
+       }
+       
+       if( code == EOFCode ) {
+                // At EOF, write the rest of the buffer.
+               while( cur_bits > 0 ) {
+                       char_out( (unsigned int)(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(long hsize)
+
+{
+       register long *htab_p = htab+hsize;
+
+       register long i;
+       register long 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(int c)
+{
+       accum[a_count++]=(char)c;
+       if (a_count >=254)
+               flush_char();
+}
+
+void CxImageGIF::flush_char()
+{
+       if (a_count > 0) {
+               g_outfile->PutC((BYTE)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 long 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.
+ *
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+
+short CxImageGIF::init_exp(short size)
+{
+       curr_size = (short)(size + 1);
+       top_slot = (short)(1 << curr_size);
+       clear = (short)(1 << size);
+       ending = (short)(clear + 1);
+       slot = newcodes = (short)(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...
+ */
+short CxImageGIF::get_next_code(CxFile* file)
+{
+       short i, x;
+       DWORD 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 = (short)get_byte(file)) < 0)
+                               return(navail_bytes);
+                       else if (navail_bytes) {
+                               for (i = 0; i < navail_bytes; ++i) {
+                                       if ((x = (short)get_byte(file)) < 0) return(x);
+                                       byte_buff[i] = (BYTE)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 = (short)get_byte(file)) < 0)
+                               return(navail_bytes);
+                       else if (navail_bytes){
+                               for (i = 0; i < navail_bytes; ++i){
+                                       if ((x = (short)get_byte(file)) < 0) return(x);
+                                       byte_buff[i] = (BYTE)x;
+                               }
+                       }
+               }
+               b1 = *pbytes++;
+               ret |= b1 << nbits_left;
+               nbits_left += 8;
+               --navail_bytes;
+       }
+       nbits_left = (short)(nbits_left-curr_size);
+       ret &= code_mask[curr_size];
+       return((short)(ret));
+}
+////////////////////////////////////////////////////////////////////////////////
+
+/* short decoder(linewidth)
+ *    short 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 BYTE 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...
+ */
+short CxImageGIF::decoder(CxFile* file, CImageIterator* iter, short linewidth, int &bad_code_count)
+{
+       register BYTE *sp, *bufptr;
+       BYTE *buf;
+       register short code, fc, oc, bufcnt;
+       short c, size, ret;
+
+       /* Initialize for decoding a new image... */
+       bad_code_count = 0;
+       if ((size = (short)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 BYTE[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 = (short)(size + 1);
+                       slot = newcodes;
+                       top_slot = (short)(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++ = (BYTE)c;
+                       if (--bufcnt == 0) {
+                               if (iter) {
+                                       if ((ret = (short)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++ = (BYTE)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++ = (BYTE)code;
+                       if (slot < top_slot){
+                               suffix[slot] = (BYTE)(fc = (BYTE)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 = (short)out_line(iter, buf, linewidth)) < 0) {
+                                                       delete [] buf;
+                                                       return(ret);
+                                               }
+                                       }
+                                       bufptr = buf;
+                                       bufcnt = linewidth;
+                               }
+                       }
+               }
+       }
+       ret = 0;
+       if (bufcnt != linewidth && iter)
+               ret = (short)out_line(iter, buf, (linewidth - bufcnt));
+       delete [] buf;
+       return(ret);
+}
+////////////////////////////////////////////////////////////////////////////////
+int CxImageGIF::get_num_frames(CxFile *fp,struct_TabCol* TabColSrc,struct_dscgif* dscgif)
+{
+       struct_image image;
+
+       long pos=fp->Tell();
+       int 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 = ntohs(image.l);
+                               image.t = ntohs(image.t);
+                               image.w = ntohs(image.w);
+                               image.h = 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 = (short)(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;
+                               }
+
+                               int badcode=0;
+                               ibf = GIFBUFTAM+1;
+
+                               interlaced = image.pf & 0x40;
+                               iheight = image.h;
+                               istep = 8;
+                               iypos = 0;
+                               ipass = 0;
+
+                               long 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;
+}
+////////////////////////////////////////////////////////////////////////////////
+long CxImageGIF::seek_next_image(CxFile* fp, long 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(int loops)
+{      m_loops=loops; }
+////////////////////////////////////////////////////////////////////////////////
+long 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)
+{
+       long ymin = max(0,(long)(GetHeight()-imgdesc.t - imgdesc.h));
+       long ymax = GetHeight()-imgdesc.t;
+       long xmin = imgdesc.l;
+       long xmax = min(GetWidth(), (DWORD)(imgdesc.l + imgdesc.w));
+
+       long ibg2= imgsrc2.GetTransIndex();
+    BYTE i2;
+
+       for(long y = ymin; y < ymax; y++){
+               for(long 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(int 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(int count,struct_RLE* rle)
+{
+       int 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(int count, struct_RLE* rle)
+{
+       int repmax;
+       int repleft;
+       int 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) < (unsigned int)(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);
+}
+////////////////////////////////////////////////////////////////////////////////
+unsigned int CxImageGIF::rle_compute_triangle_count(unsigned int count, unsigned int nrepcodes)
+{
+       unsigned int perrep;
+       unsigned int cost;
+
+       cost = 0;
+       perrep = (nrepcodes * (nrepcodes+1)) / 2;
+       while (count >= perrep){
+               cost += nrepcodes;
+               count -= perrep;
+       }
+       if (count > 0){
+               unsigned int n;
+               n = rle_isqrt(count);
+               while ((n*(n+1)) >= 2*count) n --;
+               while ((n*(n+1)) < 2*count) n ++;
+               cost += n;
+       }
+       return(cost);
+}
+////////////////////////////////////////////////////////////////////////////////
+unsigned int CxImageGIF::rle_isqrt(unsigned int x)
+{
+       unsigned int r;
+       unsigned int 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(int count, struct_RLE* rle)
+{
+       int 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((BYTE)rle->oblen);
+       g_outfile->Write(rle->oblock,1,rle->oblen);
+       rle->oblen = 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::rle_block_out(unsigned char 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(int val, struct_RLE* rle)
+{
+       rle->obuf |= val << rle->obits;
+       rle->obits += rle->out_bits;
+       while (rle->obits >= 8){
+               rle_block_out((unsigned char)(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((unsigned char)(rle->obuf),rle);
+        rle_block_flush(rle);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageGIF::compressRLE( int 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);
+
+       int 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
index 86a3e584297510ef2fdde003eee59e1c53ae6c7e..702e345d60c314813b6b34712b06768f1a30f2a5 100644 (file)
-/*\r
- * File:       ximagif.h\r
- * Purpose:    GIF Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageGIF (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes\r
- *\r
- * original CImageGIF  and CImageIterator implementation are:\r
- * Copyright:  (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>\r
- *\r
- * 6/15/97 Randy Spann: Added GIF87a writing support\r
- *         R.Spann@ConnRiver.net\r
- *\r
- * DECODE.C - An LZW decoder for GIF\r
- * Copyright (C) 1987, by Steven A. Bennett\r
- * Copyright (C) 1994, C++ version by Alejandro Aguilar Sierra\r
- *\r
- * In accordance with the above, I want to credit Steve Wilhite who wrote\r
- * the code which this is heavily inspired by...\r
- *\r
- * GIF and 'Graphics Interchange Format' are trademarks (tm) of\r
- * Compuserve, Incorporated, an H&R Block Company.\r
- *\r
- * Release Notes: This file contains a decoder routine for GIF images\r
- * which is similar, structurally, to the original routine by Steve Wilhite.\r
- * It is, however, somewhat noticably faster in most cases.\r
- *\r
- * ==========================================================\r
- */\r
-\r
-#if !defined(__ximaGIF_h)\r
-#define __ximaGIF_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_GIF\r
-\r
-typedef short int       code_int;   \r
-\r
-/* Various error codes used by decoder */\r
-#define OUT_OF_MEMORY -10\r
-#define BAD_CODE_SIZE -20\r
-#define READ_ERROR -1\r
-#define WRITE_ERROR -2\r
-#define OPEN_ERROR -3\r
-#define CREATE_ERROR -4\r
-#define MAX_CODES   4095\r
-#define GIFBUFTAM 16383\r
-#define TRANSPARENCY_CODE 0xF9\r
-\r
-//LZW GIF Image compression\r
-#define MAXBITSCODES    12\r
-#define HSIZE  5003     /* 80% occupancy */\r
-#define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)\r
-#define HashTabOf(i)    htab[i]\r
-#define CodeTabOf(i)    codetab[i]\r
-\r
-\r
-class CImageIterator;\r
-class DLL_EXP CxImageGIF: public CxImage\r
-{\r
-#pragma pack(1)\r
-\r
-typedef struct tag_gifgce{\r
-  BYTE flags; /*res:3|dispmeth:3|userinputflag:1|transpcolflag:1*/\r
-  WORD delaytime;\r
-  BYTE transpcolindex;\r
-} struct_gifgce;\r
-\r
-typedef struct tag_dscgif{             /* Logic Screen Descriptor  */\r
-  char header[6];                              /* Firma and version */\r
-  WORD scrwidth;\r
-  WORD scrheight;\r
-  char pflds;\r
-  char bcindx;\r
-  char pxasrat;\r
-} struct_dscgif;\r
-\r
-typedef struct tag_image{      /* Image Descriptor */\r
-  WORD l;\r
-  WORD t;\r
-  WORD w;\r
-  WORD h;\r
-  BYTE   pf;\r
-} struct_image;\r
-\r
-typedef struct tag_TabCol{             /* Tabla de colores */\r
-  short colres;                                        /* color resolution */\r
-  short sogct;                                 /* size of global color table */\r
-  rgb_color paleta[256];               /* paleta */\r
-} struct_TabCol;\r
-\r
-typedef struct tag_RLE{\r
-       int rl_pixel;\r
-       int rl_basecode;\r
-       int rl_count;\r
-       int rl_table_pixel;\r
-       int rl_table_max;\r
-       int just_cleared;\r
-       int out_bits;\r
-       int out_bits_init;\r
-       int out_count;\r
-       int out_bump;\r
-       int out_bump_init;\r
-       int out_clear;\r
-       int out_clear_init;\r
-       int max_ocodes;\r
-       int code_clear;\r
-       int code_eof;\r
-       unsigned int obuf;\r
-       int obits;\r
-       unsigned char oblock[256];\r
-       int oblen;\r
-} struct_RLE;\r
-#pragma pack()\r
-\r
-public:\r
-       CxImageGIF(): CxImage(CXIMAGE_FORMAT_GIF) {m_loops=0; info.dispmeth=0; m_comment[0]='\0';}\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_GIF);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_GIF);}\r
-       \r
-       bool Decode(CxFile * fp);\r
-       bool Decode(FILE *fp) { CxIOFile file(fp); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * fp);\r
-       bool Encode(CxFile * fp, CxImage ** pImages, int pagecount, bool bLocalColorMap = false, bool bLocalDispMeth = false);\r
-       bool Encode(FILE *fp) { CxIOFile file(fp); return Encode(&file); }\r
-       bool Encode(FILE *fp, CxImage ** pImages, int pagecount, bool bLocalColorMap = false)\r
-                               { CxIOFile file(fp); return Encode(&file, pImages, pagecount, bLocalColorMap); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-\r
-       void SetLoops(int loops);\r
-       long GetLoops();\r
-       void SetComment(const char* sz_comment_in);\r
-       void GetComment(char* sz_comment_out);\r
-\r
-protected:\r
-       bool DecodeExtension(CxFile *fp);\r
-       void EncodeHeader(CxFile *fp);\r
-       void EncodeLoopExtension(CxFile *fp);\r
-       void EncodeExtension(CxFile *fp);\r
-       void EncodeBody(CxFile *fp, bool bLocalColorMap = false);\r
-       void EncodeComment(CxFile *fp);\r
-       bool EncodeRGB(CxFile *fp);\r
-       void GifMix(CxImage & imgsrc2, struct_image & imgdesc);\r
-       \r
-       struct_gifgce gifgce;\r
-\r
-       int             curx, cury;\r
-       long             CountDown;\r
-       unsigned long    cur_accum;\r
-       int              cur_bits;\r
-       int interlaced, iypos, istep, iheight, ipass;\r
-       int ibf;\r
-       int ibfmax;\r
-       BYTE buf[GIFBUFTAM + 1];\r
-// Implementation\r
-       int GifNextPixel ();\r
-       void Putword (int w, CxFile* fp );\r
-       void compressNONE (int init_bits, CxFile* outfile);\r
-       void compressLZW (int init_bits, CxFile* outfile);\r
-       void output (code_int code );\r
-       void cl_hash (long hsize);\r
-       void char_out (int c);\r
-       void flush_char ();\r
-       short init_exp(short size);\r
-       short get_next_code(CxFile*);\r
-       short decoder(CxFile*, CImageIterator* iter, short linewidth, int &bad_code_count);\r
-       int get_byte(CxFile*);\r
-       int out_line(CImageIterator* iter, unsigned char *pixels, int linelen);\r
-       int get_num_frames(CxFile *f,struct_TabCol* TabColSrc,struct_dscgif* dscgif);\r
-       long seek_next_image(CxFile* fp, long position);\r
-\r
-       short curr_size;                     /* The current code size */\r
-       short clear;                         /* Value for a clear code */\r
-       short ending;                        /* Value for a ending code */\r
-       short newcodes;                      /* First available code */\r
-       short top_slot;                      /* Highest code for current size */\r
-       short slot;                          /* Last read code */\r
-\r
-       /* The following static variables are used\r
-       * for seperating out codes */\r
-       short navail_bytes;              /* # bytes left in block */\r
-       short nbits_left;                /* # bits left in current BYTE */\r
-       BYTE b1;                           /* Current BYTE */\r
-       BYTE byte_buff[257];               /* Current block */\r
-       BYTE *pbytes;                      /* Pointer to next BYTE in block */\r
-       /* The reason we have these seperated like this instead of using\r
-       * a structure like the original Wilhite code did, is because this\r
-       * stuff generally produces significantly faster code when compiled...\r
-       * This code is full of similar speedups...  (For a good book on writing\r
-       * C for speed or for space optomisation, see Efficient C by Tom Plum,\r
-       * published by Plum-Hall Associates...)\r
-       */\r
-       BYTE stack[MAX_CODES + 1];            /* Stack for storing pixels */\r
-       BYTE suffix[MAX_CODES + 1];           /* Suffix table */\r
-       WORD prefix[MAX_CODES + 1];           /* Prefix linked list */\r
-\r
-//LZW GIF Image compression routines\r
-       long htab [HSIZE];\r
-       unsigned short codetab [HSIZE];\r
-       int n_bits;                             /* number of bits/code */\r
-       code_int maxcode;               /* maximum code, given n_bits */\r
-       code_int free_ent;              /* first unused entry */\r
-       int clear_flg;\r
-       int g_init_bits;\r
-       CxFile* g_outfile;\r
-       int ClearCode;\r
-       int EOFCode;\r
-\r
-       int a_count;\r
-       char accum[256];\r
-\r
-       char m_comment[256];\r
-       int m_loops;\r
-\r
-//RLE compression routines\r
-       void compressRLE( int init_bits, CxFile* outfile);\r
-       void rle_clear(struct_RLE* rle);\r
-       void rle_flush(struct_RLE* rle);\r
-       void rle_flush_withtable(int count, struct_RLE* rle);\r
-       void rle_flush_clearorrep(int count, struct_RLE* rle);\r
-       void rle_flush_fromclear(int count,struct_RLE* rle);\r
-       void rle_output_plain(int c,struct_RLE* rle);\r
-       void rle_reset_out_clear(struct_RLE* rle);\r
-       unsigned int rle_compute_triangle_count(unsigned int count, unsigned int nrepcodes);\r
-       unsigned int rle_isqrt(unsigned int x);\r
-       void rle_write_block(struct_RLE* rle);\r
-       void rle_block_out(unsigned char c, struct_RLE* rle);\r
-       void rle_block_flush(struct_RLE* rle);\r
-       void rle_output(int val, struct_RLE* rle);\r
-       void rle_output_flush(struct_RLE* rle);\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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 short int       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 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{
+  BYTE flags; /*res:3|dispmeth:3|userinputflag:1|transpcolflag:1*/
+  WORD delaytime;
+  BYTE transpcolindex;
+} struct_gifgce;
+
+typedef struct tag_dscgif{             /* Logic Screen Descriptor  */
+  char header[6];                              /* Firma and version */
+  WORD scrwidth;
+  WORD scrheight;
+  char pflds;
+  char bcindx;
+  char pxasrat;
+} struct_dscgif;
+
+typedef struct tag_image{      /* Image Descriptor */
+  WORD l;
+  WORD t;
+  WORD w;
+  WORD h;
+  BYTE   pf;
+} struct_image;
+
+typedef struct tag_TabCol{             /* Tabla de colores */
+  short colres;                                        /* color resolution */
+  short sogct;                                 /* size of global color table */
+  rgb_color paleta[256];               /* paleta */
+} struct_TabCol;
+
+typedef struct tag_RLE{
+       int rl_pixel;
+       int rl_basecode;
+       int rl_count;
+       int rl_table_pixel;
+       int rl_table_max;
+       int just_cleared;
+       int out_bits;
+       int out_bits_init;
+       int out_count;
+       int out_bump;
+       int out_bump_init;
+       int out_clear;
+       int out_clear_init;
+       int max_ocodes;
+       int code_clear;
+       int code_eof;
+       unsigned int obuf;
+       int obits;
+       unsigned char oblock[256];
+       int oblen;
+} struct_RLE;
+#pragma pack()
+
+public:
+       CxImageGIF(): CxImage(CXIMAGE_FORMAT_GIF) {m_loops=0; info.dispmeth=0; m_comment[0]='\0';}
+
+//     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, int pagecount, bool bLocalColorMap = false, bool bLocalDispMeth = false);
+       bool Encode(FILE *fp) { CxIOFile file(fp); return Encode(&file); }
+       bool Encode(FILE *fp, CxImage ** pImages, int pagecount, bool bLocalColorMap = false)
+                               { CxIOFile file(fp); return Encode(&file, pImages, pagecount, bLocalColorMap); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+       void SetLoops(int loops);
+       long 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;
+
+       int             curx, cury;
+       long             CountDown;
+       unsigned long    cur_accum;
+       int              cur_bits;
+       int interlaced, iypos, istep, iheight, ipass;
+       int ibf;
+       int ibfmax;
+       BYTE buf[GIFBUFTAM + 1];
+// Implementation
+       int GifNextPixel ();
+       void Putword (int w, CxFile* fp );
+       void compressNONE (int init_bits, CxFile* outfile);
+       void compressLZW (int init_bits, CxFile* outfile);
+       void output (code_int code );
+       void cl_hash (long hsize);
+       void char_out (int c);
+       void flush_char ();
+       short init_exp(short size);
+       short get_next_code(CxFile*);
+       short decoder(CxFile*, CImageIterator* iter, short linewidth, int &bad_code_count);
+       int get_byte(CxFile*);
+       int out_line(CImageIterator* iter, unsigned char *pixels, int linelen);
+       int get_num_frames(CxFile *f,struct_TabCol* TabColSrc,struct_dscgif* dscgif);
+       long seek_next_image(CxFile* fp, long position);
+
+       short curr_size;                     /* The current code size */
+       short clear;                         /* Value for a clear code */
+       short ending;                        /* Value for a ending code */
+       short newcodes;                      /* First available code */
+       short top_slot;                      /* Highest code for current size */
+       short slot;                          /* Last read code */
+
+       /* The following static variables are used
+       * for seperating out codes */
+       short navail_bytes;              /* # bytes left in block */
+       short nbits_left;                /* # bits left in current BYTE */
+       BYTE b1;                           /* Current BYTE */
+       BYTE byte_buff[257];               /* Current block */
+       BYTE *pbytes;                      /* Pointer to next BYTE 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...)
+       */
+       BYTE stack[MAX_CODES + 1];            /* Stack for storing pixels */
+       BYTE suffix[MAX_CODES + 1];           /* Suffix table */
+       WORD prefix[MAX_CODES + 1];           /* Prefix linked list */
+
+//LZW GIF Image compression routines
+       long htab [HSIZE];
+       unsigned short codetab [HSIZE];
+       int n_bits;                             /* number of bits/code */
+       code_int maxcode;               /* maximum code, given n_bits */
+       code_int free_ent;              /* first unused entry */
+       int clear_flg;
+       int g_init_bits;
+       CxFile* g_outfile;
+       int ClearCode;
+       int EOFCode;
+
+       int a_count;
+       char accum[256];
+
+       char m_comment[256];
+       int m_loops;
+
+//RLE compression routines
+       void compressRLE( int init_bits, CxFile* outfile);
+       void rle_clear(struct_RLE* rle);
+       void rle_flush(struct_RLE* rle);
+       void rle_flush_withtable(int count, struct_RLE* rle);
+       void rle_flush_clearorrep(int count, struct_RLE* rle);
+       void rle_flush_fromclear(int count,struct_RLE* rle);
+       void rle_output_plain(int c,struct_RLE* rle);
+       void rle_reset_out_clear(struct_RLE* rle);
+       unsigned int rle_compute_triangle_count(unsigned int count, unsigned int nrepcodes);
+       unsigned int rle_isqrt(unsigned int x);
+       void rle_write_block(struct_RLE* rle);
+       void rle_block_out(unsigned char c, struct_RLE* rle);
+       void rle_block_flush(struct_RLE* rle);
+       void rle_output(int val, struct_RLE* rle);
+       void rle_output_flush(struct_RLE* rle);
+};
+
+#endif
+
+#endif
index 2b47d17d5e79eea1bb47610ac5ce84b156368a61..a2aed03e335614e818b15492fc871a96fa8e0b18 100644 (file)
-// xImaHist.cpp : histogram functions\r
-/* 28/01/2004 v1.00 - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_DSP\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImage::Histogram(long* red, long* green, long* blue, long* gray, long colorspace)\r
-{\r
-       if (!pDib) return 0;\r
-       RGBQUAD color;\r
-\r
-       if (red) memset(red,0,256*sizeof(long));\r
-       if (green) memset(green,0,256*sizeof(long));\r
-       if (blue) memset(blue,0,256*sizeof(long));\r
-       if (gray) memset(gray,0,256*sizeof(long));\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               switch (colorspace){\r
-                               case 1:\r
-                                       color = HSLtoRGB(BlindGetPixelColor(x,y));\r
-                                       break;\r
-                               case 2:\r
-                                       color = YUVtoRGB(BlindGetPixelColor(x,y));\r
-                                       break;\r
-                               case 3:\r
-                                       color = YIQtoRGB(BlindGetPixelColor(x,y));\r
-                                       break;\r
-                               case 4:\r
-                                       color = XYZtoRGB(BlindGetPixelColor(x,y));\r
-                                       break;\r
-                               default:\r
-                                       color = BlindGetPixelColor(x,y);\r
-                               }\r
-\r
-                               if (red) red[color.rgbRed]++;\r
-                               if (green) green[color.rgbGreen]++;\r
-                               if (blue) blue[color.rgbBlue]++;\r
-                               if (gray) gray[(BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)]++;\r
-                       }\r
-               }\r
-       }\r
-\r
-       long n=0;\r
-       for (int i=0; i<256; i++){\r
-               if (red && red[i]>n) n=red[i];\r
-               if (green && green[i]>n) n=green[i];\r
-               if (blue && blue[i]>n) n=blue[i];\r
-               if (gray && gray[i]>n) n=gray[i];\r
-       }\r
-\r
-       return n;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * HistogramStretch\r
- * \param method: 0 = luminance (default), 1 = linked channels , 2 = independent channels.\r
- * \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%);\r
- * \return true if everything is ok\r
- * \author [dave] and [nipper]; changes [DP]\r
- */\r
-bool CxImage::HistogramStretch(long method, double threshold)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       double dbScaler = 50.0/head.biHeight;\r
-       long x,y;\r
-\r
-  if ((head.biBitCount==8) && IsGrayScale()){\r
-\r
-       double p[256];\r
-       memset(p,  0, 256*sizeof(double));\r
-       for (y=0; y<head.biHeight; y++)\r
-       {\r
-               info.nProgress = (long)(y*dbScaler);\r
-               if (info.nEscape) break;\r
-               for (x=0; x<head.biWidth; x++)  {\r
-                       p[BlindGetPixelIndex(x, y)]++;\r
-               }\r
-       }\r
-\r
-       double maxh = 0;\r
-       for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y];\r
-       threshold *= maxh;\r
-       int minc = 0;\r
-       while (minc<255 && p[minc]<=threshold) minc++;\r
-       int maxc = 255;\r
-       while (maxc>0 && p[maxc]<=threshold) maxc--;\r
-\r
-       if (minc == 0 && maxc == 255) return true;\r
-       if (minc >= maxc) return true;\r
-\r
-       // calculate LUT\r
-       BYTE lut[256];\r
-       for (x = 0; x <256; x++){\r
-               lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc))));\r
-       }\r
-\r
-       for (y=0; y<head.biHeight; y++) {\r
-               if (info.nEscape) break;\r
-               info.nProgress = (long)(50.0+y*dbScaler);\r
-               for (x=0; x<head.biWidth; x++)\r
-               {\r
-                       BlindSetPixelIndex(x, y, lut[BlindGetPixelIndex(x, y)]);\r
-               }\r
-       }\r
-  } else {\r
-       switch(method){\r
-       case 1:\r
-         { // <nipper>\r
-               double p[256];\r
-               memset(p,  0, 256*sizeof(double));\r
-               for (y=0; y<head.biHeight; y++)\r
-               {\r
-                       info.nProgress = (long)(y*dbScaler);\r
-                       if (info.nEscape) break;\r
-                       for (x=0; x<head.biWidth; x++)  {\r
-                               RGBQUAD color = BlindGetPixelColor(x, y);\r
-                               p[color.rgbRed]++;\r
-                               p[color.rgbBlue]++;\r
-                               p[color.rgbGreen]++;\r
-                       }\r
-               }\r
-               double maxh = 0;\r
-               for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y];\r
-               threshold *= maxh;\r
-               int minc = 0;\r
-               while (minc<255 && p[minc]<=threshold) minc++;\r
-               int maxc = 255;\r
-               while (maxc>0 && p[maxc]<=threshold) maxc--;\r
-\r
-               if (minc == 0 && maxc == 255) return true;\r
-               if (minc >= maxc) return true;\r
-\r
-               // calculate LUT\r
-               BYTE lut[256];\r
-               for (x = 0; x <256; x++){\r
-                       lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc))));\r
-               }\r
-\r
-               // normalize image\r
-               for (y=0; y<head.biHeight; y++) {\r
-                       if (info.nEscape) break;\r
-                       info.nProgress = (long)(50.0+y*dbScaler);\r
-\r
-                       for (x=0; x<head.biWidth; x++)\r
-                       {\r
-                               RGBQUAD color = BlindGetPixelColor(x, y);\r
-\r
-                               color.rgbRed = lut[color.rgbRed];\r
-                               color.rgbBlue = lut[color.rgbBlue];\r
-                               color.rgbGreen = lut[color.rgbGreen];\r
-\r
-                               BlindSetPixelColor(x, y, color);\r
-                       }\r
-               }\r
-         }\r
-               break;\r
-       case 2:\r
-         { // <nipper>\r
-               double pR[256];\r
-               memset(pR,  0, 256*sizeof(double));\r
-               double pG[256];\r
-               memset(pG,  0, 256*sizeof(double));\r
-               double pB[256];\r
-               memset(pB,  0, 256*sizeof(double));\r
-               for (y=0; y<head.biHeight; y++)\r
-               {\r
-                       info.nProgress = (long)(y*dbScaler);\r
-                       if (info.nEscape) break;\r
-                       for (long x=0; x<head.biWidth; x++)     {\r
-                               RGBQUAD color = BlindGetPixelColor(x, y);\r
-                               pR[color.rgbRed]++;\r
-                               pB[color.rgbBlue]++;\r
-                               pG[color.rgbGreen]++;\r
-                       }\r
-               }\r
-\r
-               double maxh = 0;\r
-               for (y=0; y<255; y++) if (maxh < pR[y]) maxh = pR[y];\r
-               double threshold2 = threshold*maxh;\r
-               int minR = 0;\r
-               while (minR<255 && pR[minR]<=threshold2) minR++;\r
-               int maxR = 255;\r
-               while (maxR>0 && pR[maxR]<=threshold2) maxR--;\r
-\r
-               maxh = 0;\r
-               for (y=0; y<255; y++) if (maxh < pG[y]) maxh = pG[y];\r
-               threshold2 = threshold*maxh;\r
-               int minG = 0;\r
-               while (minG<255 && pG[minG]<=threshold2) minG++;\r
-               int maxG = 255;\r
-               while (maxG>0 && pG[maxG]<=threshold2) maxG--;\r
-\r
-               maxh = 0;\r
-               for (y=0; y<255; y++) if (maxh < pB[y]) maxh = pB[y];\r
-               threshold2 = threshold*maxh;\r
-               int minB = 0;\r
-               while (minB<255 && pB[minB]<=threshold2) minB++;\r
-               int maxB = 255;\r
-               while (maxB>0 && pB[maxB]<=threshold2) maxB--;\r
-\r
-               if (minR == 0 && maxR == 255 && minG == 0 && maxG == 255 && minB == 0 && maxB == 255)\r
-                       return true;\r
-\r
-               // calculate LUT\r
-               BYTE lutR[256];\r
-               BYTE range = maxR - minR;\r
-               if (range != 0) {\r
-                       for (x = 0; x <256; x++){\r
-                               lutR[x] = (BYTE)max(0,min(255,(255 * (x - minR) / range)));\r
-                       }\r
-               } else lutR[minR] = minR;\r
-\r
-               BYTE lutG[256];\r
-               range = maxG - minG;\r
-               if (range != 0) {\r
-                       for (x = 0; x <256; x++){\r
-                               lutG[x] = (BYTE)max(0,min(255,(255 * (x - minG) / range)));\r
-                       }\r
-               } else lutG[minG] = minG;\r
-                       \r
-               BYTE lutB[256];\r
-               range = maxB - minB;\r
-               if (range != 0) {\r
-                       for (x = 0; x <256; x++){\r
-                               lutB[x] = (BYTE)max(0,min(255,(255 * (x - minB) / range)));\r
-                       }\r
-               } else lutB[minB] = minB;\r
-\r
-               // normalize image\r
-               for (y=0; y<head.biHeight; y++)\r
-               {\r
-                       info.nProgress = (long)(50.0+y*dbScaler);\r
-                       if (info.nEscape) break;\r
-\r
-                       for (x=0; x<head.biWidth; x++)\r
-                       {\r
-                               RGBQUAD color = BlindGetPixelColor(x, y);\r
-\r
-                               color.rgbRed = lutR[color.rgbRed];\r
-                               color.rgbBlue = lutB[color.rgbBlue];\r
-                               color.rgbGreen = lutG[color.rgbGreen];\r
-\r
-                               BlindSetPixelColor(x, y, color);\r
-                       }\r
-               }\r
-         }\r
-               break;\r
-       default:\r
-         { // <dave>\r
-               double p[256];\r
-               memset(p,  0, 256*sizeof(double));\r
-               for (y=0; y<head.biHeight; y++)\r
-               {\r
-                       info.nProgress = (long)(y*dbScaler);\r
-                       if (info.nEscape) break;\r
-                       for (x=0; x<head.biWidth; x++)  {\r
-                               RGBQUAD color = BlindGetPixelColor(x, y);\r
-                               p[RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue)]++;\r
-                       }\r
-               }\r
-\r
-               double maxh = 0;\r
-               for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y];\r
-               threshold *= maxh;\r
-               int minc = 0;\r
-               while (minc<255 && p[minc]<=threshold) minc++;\r
-               int maxc = 255;\r
-               while (maxc>0 && p[maxc]<=threshold) maxc--;\r
-\r
-               if (minc == 0 && maxc == 255) return true;\r
-               if (minc >= maxc) return true;\r
-\r
-               // calculate LUT\r
-               BYTE lut[256];\r
-               for (x = 0; x <256; x++){\r
-                       lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc))));\r
-               }\r
-\r
-               for(y=0; y<head.biHeight; y++){\r
-                       info.nProgress = (long)(50.0+y*dbScaler);\r
-                       if (info.nEscape) break;\r
-                       for(x=0; x<head.biWidth; x++){\r
-\r
-                               RGBQUAD color = BlindGetPixelColor( x, y );\r
-                               RGBQUAD yuvClr = RGBtoYUV(color);\r
-                               yuvClr.rgbRed = lut[yuvClr.rgbRed];\r
-                               color = YUVtoRGB(yuvClr);\r
-                               BlindSetPixelColor( x, y, color );\r
-                       }\r
-               }\r
-         }\r
-       }\r
-  }\r
-  return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// HistogramEqualize function by <dave> : dave(at)posortho(dot)com\r
-bool CxImage::HistogramEqualize()\r
-{\r
-       if (!pDib) return false;\r
-\r
-    int histogram[256];\r
-       int map[256];\r
-       int equalize_map[256];\r
-    int x, y, i, j;\r
-       RGBQUAD color;\r
-       RGBQUAD yuvClr;\r
-       unsigned int YVal, high, low;\r
-\r
-       memset( &histogram, 0, sizeof(int) * 256 );\r
-       memset( &map, 0, sizeof(int) * 256 );\r
-       memset( &equalize_map, 0, sizeof(int) * 256 );\r
\r
-     // form histogram\r
-       for(y=0; y < head.biHeight; y++){\r
-               info.nProgress = (long)(50*y/head.biHeight);\r
-               if (info.nEscape) break;\r
-               for(x=0; x < head.biWidth; x++){\r
-                       color = BlindGetPixelColor( x, y );\r
-                       YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
-                       histogram[YVal]++;\r
-               }\r
-       }\r
-\r
-       // integrate the histogram to get the equalization map.\r
-       j = 0;\r
-       for(i=0; i <= 255; i++){\r
-               j += histogram[i];\r
-               map[i] = j; \r
-       }\r
-\r
-       // equalize\r
-       low = map[0];\r
-       high = map[255];\r
-       if (low == high) return false;\r
-       for( i = 0; i <= 255; i++ ){\r
-               equalize_map[i] = (unsigned int)((((double)( map[i] - low ) ) * 255) / ( high - low ) );\r
-       }\r
-\r
-       // stretch the histogram\r
-       if(head.biClrUsed == 0){ // No Palette\r
-               for( y = 0; y < head.biHeight; y++ ){\r
-                       info.nProgress = (long)(50+50*y/head.biHeight);\r
-                       if (info.nEscape) break;\r
-                       for( x = 0; x < head.biWidth; x++ ){\r
-\r
-                               color = BlindGetPixelColor( x, y );\r
-                               yuvClr = RGBtoYUV(color);\r
-\r
-                yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed];\r
-\r
-                               color = YUVtoRGB(yuvClr);\r
-                               BlindSetPixelColor( x, y, color );\r
-                       }\r
-               }\r
-       } else { // Palette\r
-               for( i = 0; i < (int)head.biClrUsed; i++ ){\r
-\r
-                       color = GetPaletteColor((BYTE)i);\r
-                       yuvClr = RGBtoYUV(color);\r
-\r
-            yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed];\r
-\r
-                       color = YUVtoRGB(yuvClr);\r
-                       SetPaletteColor( (BYTE)i, color );\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// HistogramNormalize function by <dave> : dave(at)posortho(dot)com\r
-bool CxImage::HistogramNormalize()\r
-{\r
-       if (!pDib) return false;\r
-\r
-       int histogram[256];\r
-       int threshold_intensity, intense;\r
-       int x, y, i;\r
-       unsigned int normalize_map[256];\r
-       unsigned int high, low, YVal;\r
-\r
-       RGBQUAD color;\r
-       RGBQUAD yuvClr;\r
-\r
-       memset( &histogram, 0, sizeof( int ) * 256 );\r
-       memset( &normalize_map, 0, sizeof( unsigned int ) * 256 );\r
\r
-     // form histogram\r
-       for(y=0; y < head.biHeight; y++){\r
-               info.nProgress = (long)(50*y/head.biHeight);\r
-               if (info.nEscape) break;\r
-               for(x=0; x < head.biWidth; x++){\r
-                       color = BlindGetPixelColor( x, y );\r
-                       YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
-                       histogram[YVal]++;\r
-               }\r
-       }\r
-\r
-       // find histogram boundaries by locating the 1 percent levels\r
-       threshold_intensity = ( head.biWidth * head.biHeight) / 100;\r
-\r
-       intense = 0;\r
-       for( low = 0; low < 255; low++ ){\r
-               intense += histogram[low];\r
-               if( intense > threshold_intensity )     break;\r
-       }\r
-\r
-       intense = 0;\r
-       for( high = 255; high != 0; high--){\r
-               intense += histogram[ high ];\r
-               if( intense > threshold_intensity ) break;\r
-       }\r
-\r
-       if ( low == high ){\r
-               // Unreasonable contrast;  use zero threshold to determine boundaries.\r
-               threshold_intensity = 0;\r
-               intense = 0;\r
-               for( low = 0; low < 255; low++){\r
-                       intense += histogram[low];\r
-                       if( intense > threshold_intensity )     break;\r
-               }\r
-               intense = 0;\r
-               for( high = 255; high != 0; high-- ){\r
-                       intense += histogram [high ];\r
-                       if( intense > threshold_intensity )     break;\r
-               }\r
-       }\r
-       if( low == high ) return false;  // zero span bound\r
-\r
-       // Stretch the histogram to create the normalized image mapping.\r
-       for(i = 0; i <= 255; i++){\r
-               if ( i < (int) low ){\r
-                       normalize_map[i] = 0;\r
-               } else {\r
-                       if(i > (int) high)\r
-                               normalize_map[i] = 255;\r
-                       else\r
-                               normalize_map[i] = ( 255 - 1) * ( i - low) / ( high - low );\r
-               }\r
-       }\r
-\r
-       // Normalize\r
-       if( head.biClrUsed == 0 ){\r
-               for( y = 0; y < head.biHeight; y++ ){\r
-                       info.nProgress = (long)(50+50*y/head.biHeight);\r
-                       if (info.nEscape) break;\r
-                       for( x = 0; x < head.biWidth; x++ ){\r
-\r
-                               color = BlindGetPixelColor( x, y );\r
-                               yuvClr = RGBtoYUV( color );\r
-\r
-                yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed];\r
-\r
-                               color = YUVtoRGB( yuvClr );\r
-                               BlindSetPixelColor( x, y, color );\r
-                       }\r
-               }\r
-       } else {\r
-               for(i = 0; i < (int)head.biClrUsed; i++){\r
-\r
-                       color = GetPaletteColor( (BYTE)i );\r
-                       yuvClr = RGBtoYUV( color );\r
-\r
-            yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed];\r
-\r
-                       color = YUVtoRGB( yuvClr );\r
-                       SetPaletteColor( (BYTE)i, color );\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// HistogramLog function by <dave> : dave(at)posortho(dot)com\r
-bool CxImage::HistogramLog()\r
-{\r
-       if (!pDib) return false;\r
-\r
-       //q(i,j) = 255/log(1 + |high|) * log(1 + |p(i,j)|);\r
-    int x, y, i;\r
-       RGBQUAD color;\r
-       RGBQUAD yuvClr;\r
-\r
-       unsigned int YVal, high = 1;\r
-\r
-    // Find Highest Luminance Value in the Image\r
-       if( head.biClrUsed == 0 ){ // No Palette\r
-               for(y=0; y < head.biHeight; y++){\r
-                       info.nProgress = (long)(50*y/head.biHeight);\r
-                       if (info.nEscape) break;\r
-                       for(x=0; x < head.biWidth; x++){\r
-                               color = BlindGetPixelColor( x, y );\r
-                               YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
-                               if (YVal > high ) high = YVal;\r
-                       }\r
-               }\r
-       } else { // Palette\r
-               for(i = 0; i < (int)head.biClrUsed; i++){\r
-                       color = GetPaletteColor((BYTE)i);\r
-                       YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
-                       if (YVal > high ) high = YVal;\r
-               }\r
-       }\r
-\r
-       // Logarithm Operator\r
-       double k = 255.0 / ::log( 1.0 + (double)high );\r
-       if( head.biClrUsed == 0 ){\r
-               for( y = 0; y < head.biHeight; y++ ){\r
-                       info.nProgress = (long)(50+50*y/head.biHeight);\r
-                       if (info.nEscape) break;\r
-                       for( x = 0; x < head.biWidth; x++ ){\r
-\r
-                               color = BlindGetPixelColor( x, y );\r
-                               yuvClr = RGBtoYUV( color );\r
-                \r
-                               yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) );\r
-\r
-                               color = YUVtoRGB( yuvClr );\r
-                               BlindSetPixelColor( x, y, color );\r
-                       }\r
-               }\r
-       } else {\r
-               for(i = 0; i < (int)head.biClrUsed; i++){\r
-\r
-                       color = GetPaletteColor( (BYTE)i );\r
-                       yuvClr = RGBtoYUV( color );\r
-\r
-            yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) );\r
-                       \r
-                       color = YUVtoRGB( yuvClr );\r
-                       SetPaletteColor( (BYTE)i, color );\r
-               }\r
-       }\r
\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// HistogramRoot function by <dave> : dave(at)posortho(dot)com\r
-bool CxImage::HistogramRoot()\r
-{\r
-       if (!pDib) return false;\r
-       //q(i,j) = sqrt(|p(i,j)|);\r
-\r
-    int x, y, i;\r
-       RGBQUAD color;\r
-       RGBQUAD  yuvClr;\r
-       double  dtmp;\r
-       unsigned int YVal, high = 1;\r
-\r
-     // Find Highest Luminance Value in the Image\r
-       if( head.biClrUsed == 0 ){ // No Palette\r
-               for(y=0; y < head.biHeight; y++){\r
-                       info.nProgress = (long)(50*y/head.biHeight);\r
-                       if (info.nEscape) break;\r
-                       for(x=0; x < head.biWidth; x++){\r
-                               color = BlindGetPixelColor( x, y );\r
-                               YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
-                               if (YVal > high ) high = YVal;\r
-                       }\r
-               }\r
-       } else { // Palette\r
-               for(i = 0; i < (int)head.biClrUsed; i++){\r
-                       color = GetPaletteColor((BYTE)i);\r
-                       YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
-                       if (YVal > high ) high = YVal;\r
-               }\r
-       }\r
-\r
-       // Root Operator\r
-       double k = 128.0 / ::log( 1.0 + (double)high );\r
-       if( head.biClrUsed == 0 ){\r
-               for( y = 0; y < head.biHeight; y++ ){\r
-                       info.nProgress = (long)(50+50*y/head.biHeight);\r
-                       if (info.nEscape) break;\r
-                       for( x = 0; x < head.biWidth; x++ ){\r
-\r
-                               color = BlindGetPixelColor( x, y );\r
-                               yuvClr = RGBtoYUV( color );\r
-\r
-                               dtmp = k * ::sqrt( (double)yuvClr.rgbRed );\r
-                               if ( dtmp > 255.0 )     dtmp = 255.0;\r
-                               if ( dtmp < 0 ) dtmp = 0;\r
-                yuvClr.rgbRed = (BYTE)dtmp;\r
-\r
-                               color = YUVtoRGB( yuvClr );\r
-                               BlindSetPixelColor( x, y, color );\r
-                       }\r
-               }\r
-       } else {\r
-               for(i = 0; i < (int)head.biClrUsed; i++){\r
-\r
-                       color = GetPaletteColor( (BYTE)i );\r
-                       yuvClr = RGBtoYUV( color );\r
-\r
-                       dtmp = k * ::sqrt( (double)yuvClr.rgbRed );\r
-                       if ( dtmp > 255.0 )     dtmp = 255.0;\r
-                       if ( dtmp < 0 ) dtmp = 0;\r
-            yuvClr.rgbRed = (BYTE)dtmp;\r
-\r
-                       color = YUVtoRGB( yuvClr );\r
-                       SetPaletteColor( (BYTE)i, color );\r
-               }\r
-       }\r
\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif\r
+// xImaHist.cpp : histogram functions
+/* 28/01/2004 v1.00 - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_DSP
+
+////////////////////////////////////////////////////////////////////////////////
+long CxImage::Histogram(long* red, long* green, long* blue, long* gray, long colorspace)
+{
+       if (!pDib) return 0;
+       RGBQUAD color;
+
+       if (red) memset(red,0,256*sizeof(long));
+       if (green) memset(green,0,256*sizeof(long));
+       if (blue) memset(blue,0,256*sizeof(long));
+       if (gray) memset(gray,0,256*sizeof(long));
+
+       long 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(long y=ymin; y<ymax; y++){
+               for(long 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[(BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)]++;
+                       }
+               }
+       }
+
+       long n=0;
+       for (int 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(long method, double threshold)
+{
+       if (!pDib) return false;
+
+       double dbScaler = 50.0/head.biHeight;
+       long 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 = (long)(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;
+       int minc = 0;
+       while (minc<255 && p[minc]<=threshold) minc++;
+       int maxc = 255;
+       while (maxc>0 && p[maxc]<=threshold) maxc--;
+
+       if (minc == 0 && maxc == 255) return true;
+       if (minc >= maxc) return true;
+
+       // calculate LUT
+       BYTE lut[256];
+       for (x = 0; x <256; x++){
+               lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc))));
+       }
+
+       for (y=0; y<head.biHeight; y++) {
+               if (info.nEscape) break;
+               info.nProgress = (long)(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 = (long)(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;
+               int minc = 0;
+               while (minc<255 && p[minc]<=threshold) minc++;
+               int maxc = 255;
+               while (maxc>0 && p[maxc]<=threshold) maxc--;
+
+               if (minc == 0 && maxc == 255) return true;
+               if (minc >= maxc) return true;
+
+               // calculate LUT
+               BYTE lut[256];
+               for (x = 0; x <256; x++){
+                       lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc))));
+               }
+
+               // normalize image
+               for (y=0; y<head.biHeight; y++) {
+                       if (info.nEscape) break;
+                       info.nProgress = (long)(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 = (long)(y*dbScaler);
+                       if (info.nEscape) break;
+                       for (long 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;
+               int minR = 0;
+               while (minR<255 && pR[minR]<=threshold2) minR++;
+               int 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;
+               int minG = 0;
+               while (minG<255 && pG[minG]<=threshold2) minG++;
+               int 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;
+               int minB = 0;
+               while (minB<255 && pB[minB]<=threshold2) minB++;
+               int 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
+               BYTE lutR[256];
+               BYTE range = maxR - minR;
+               if (range != 0) {
+                       for (x = 0; x <256; x++){
+                               lutR[x] = (BYTE)max(0,min(255,(255 * (x - minR) / range)));
+                       }
+               } else lutR[minR] = minR;
+
+               BYTE lutG[256];
+               range = maxG - minG;
+               if (range != 0) {
+                       for (x = 0; x <256; x++){
+                               lutG[x] = (BYTE)max(0,min(255,(255 * (x - minG) / range)));
+                       }
+               } else lutG[minG] = minG;
+                       
+               BYTE lutB[256];
+               range = maxB - minB;
+               if (range != 0) {
+                       for (x = 0; x <256; x++){
+                               lutB[x] = (BYTE)max(0,min(255,(255 * (x - minB) / range)));
+                       }
+               } else lutB[minB] = minB;
+
+               // normalize image
+               for (y=0; y<head.biHeight; y++)
+               {
+                       info.nProgress = (long)(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 = (long)(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;
+               int minc = 0;
+               while (minc<255 && p[minc]<=threshold) minc++;
+               int maxc = 255;
+               while (maxc>0 && p[maxc]<=threshold) maxc--;
+
+               if (minc == 0 && maxc == 255) return true;
+               if (minc >= maxc) return true;
+
+               // calculate LUT
+               BYTE lut[256];
+               for (x = 0; x <256; x++){
+                       lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc))));
+               }
+
+               for(y=0; y<head.biHeight; y++){
+                       info.nProgress = (long)(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;
+
+    int histogram[256];
+       int map[256];
+       int equalize_map[256];
+    int x, y, i, j;
+       RGBQUAD color;
+       RGBQUAD yuvClr;
+       unsigned int YVal, high, low;
+
+       memset( &histogram, 0, sizeof(int) * 256 );
+       memset( &map, 0, sizeof(int) * 256 );
+       memset( &equalize_map, 0, sizeof(int) * 256 );
+     // form histogram
+       for(y=0; y < head.biHeight; y++){
+               info.nProgress = (long)(50*y/head.biHeight);
+               if (info.nEscape) break;
+               for(x=0; x < head.biWidth; x++){
+                       color = BlindGetPixelColor( x, y );
+                       YVal = (unsigned int)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] = (unsigned int)((((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 = (long)(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 = (BYTE)equalize_map[yuvClr.rgbRed];
+
+                               color = YUVtoRGB(yuvClr);
+                               BlindSetPixelColor( x, y, color );
+                       }
+               }
+       } else { // Palette
+               for( i = 0; i < (int)head.biClrUsed; i++ ){
+
+                       color = GetPaletteColor((BYTE)i);
+                       yuvClr = RGBtoYUV(color);
+
+            yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed];
+
+                       color = YUVtoRGB(yuvClr);
+                       SetPaletteColor( (BYTE)i, color );
+               }
+       }
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+// HistogramNormalize function by <dave> : dave(at)posortho(dot)com
+bool CxImage::HistogramNormalize()
+{
+       if (!pDib) return false;
+
+       int histogram[256];
+       int threshold_intensity, intense;
+       int x, y, i;
+       unsigned int normalize_map[256];
+       unsigned int high, low, YVal;
+
+       RGBQUAD color;
+       RGBQUAD yuvClr;
+
+       memset( &histogram, 0, sizeof( int ) * 256 );
+       memset( &normalize_map, 0, sizeof( unsigned int ) * 256 );
+     // form histogram
+       for(y=0; y < head.biHeight; y++){
+               info.nProgress = (long)(50*y/head.biHeight);
+               if (info.nEscape) break;
+               for(x=0; x < head.biWidth; x++){
+                       color = BlindGetPixelColor( x, y );
+                       YVal = (unsigned int)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 < (int) low ){
+                       normalize_map[i] = 0;
+               } else {
+                       if(i > (int) 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 = (long)(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 = (BYTE)normalize_map[yuvClr.rgbRed];
+
+                               color = YUVtoRGB( yuvClr );
+                               BlindSetPixelColor( x, y, color );
+                       }
+               }
+       } else {
+               for(i = 0; i < (int)head.biClrUsed; i++){
+
+                       color = GetPaletteColor( (BYTE)i );
+                       yuvClr = RGBtoYUV( color );
+
+            yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed];
+
+                       color = YUVtoRGB( yuvClr );
+                       SetPaletteColor( (BYTE)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)|);
+    int x, y, i;
+       RGBQUAD color;
+       RGBQUAD yuvClr;
+
+       unsigned int 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 = (long)(50*y/head.biHeight);
+                       if (info.nEscape) break;
+                       for(x=0; x < head.biWidth; x++){
+                               color = BlindGetPixelColor( x, y );
+                               YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+                               if (YVal > high ) high = YVal;
+                       }
+               }
+       } else { // Palette
+               for(i = 0; i < (int)head.biClrUsed; i++){
+                       color = GetPaletteColor((BYTE)i);
+                       YVal = (unsigned int)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 = (long)(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 = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) );
+
+                               color = YUVtoRGB( yuvClr );
+                               BlindSetPixelColor( x, y, color );
+                       }
+               }
+       } else {
+               for(i = 0; i < (int)head.biClrUsed; i++){
+
+                       color = GetPaletteColor( (BYTE)i );
+                       yuvClr = RGBtoYUV( color );
+
+            yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) );
+                       
+                       color = YUVtoRGB( yuvClr );
+                       SetPaletteColor( (BYTE)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)|);
+
+    int x, y, i;
+       RGBQUAD color;
+       RGBQUAD  yuvClr;
+       double  dtmp;
+       unsigned int 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 = (long)(50*y/head.biHeight);
+                       if (info.nEscape) break;
+                       for(x=0; x < head.biWidth; x++){
+                               color = BlindGetPixelColor( x, y );
+                               YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+                               if (YVal > high ) high = YVal;
+                       }
+               }
+       } else { // Palette
+               for(i = 0; i < (int)head.biClrUsed; i++){
+                       color = GetPaletteColor((BYTE)i);
+                       YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+                       if (YVal > high ) high = YVal;
+               }
+       }
+
+       // Root Operator
+       double k = 128.0 / ::log( 1.0 + (double)high );
+       if( head.biClrUsed == 0 ){
+               for( y = 0; y < head.biHeight; y++ ){
+                       info.nProgress = (long)(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 = (BYTE)dtmp;
+
+                               color = YUVtoRGB( yuvClr );
+                               BlindSetPixelColor( x, y, color );
+                       }
+               }
+       } else {
+               for(i = 0; i < (int)head.biClrUsed; i++){
+
+                       color = GetPaletteColor( (BYTE)i );
+                       yuvClr = RGBtoYUV( color );
+
+                       dtmp = k * ::sqrt( (double)yuvClr.rgbRed );
+                       if ( dtmp > 255.0 )     dtmp = 255.0;
+                       if ( dtmp < 0 ) dtmp = 0;
+            yuvClr.rgbRed = (BYTE)dtmp;
+
+                       color = YUVtoRGB( yuvClr );
+                       SetPaletteColor( (BYTE)i, color );
+               }
+       }
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif
index 0cb3b060f2895fb7420fedcb6b2bbb1568540b70..8ae5047d20c4d241eefbcd3a2180cf4548e88306 100644 (file)
-/*\r
- * File:       ximaico.cpp\r
- * Purpose:    Platform Independent ICON Image Class Loader and Writer (MS version)\r
- * 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximaico.h"\r
-\r
-#if CXIMAGE_SUPPORT_ICO\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageICO::Decode(CxFile *hFile)\r
-{\r
-       if (hFile==NULL) return false;\r
-\r
-       DWORD off = hFile->Tell(); //<yuandi>\r
-       int     page=info.nFrame;       //internal icon structure indexes\r
-\r
-       // read the first part of the header\r
-       ICONHEADER icon_header;\r
-       hFile->Read(&icon_header,sizeof(ICONHEADER),1);\r
-\r
-       icon_header.idType = ntohs(icon_header.idType);\r
-       icon_header.idCount = ntohs(icon_header.idCount);\r
-\r
-       // check if it's an icon or a cursor\r
-       if ((icon_header.idReserved == 0) && ((icon_header.idType == 1)||(icon_header.idType == 2))) {\r
-\r
-               info.nNumFrames = icon_header.idCount;\r
-\r
-               // load the icon descriptions\r
-               ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header.idCount * sizeof(ICONDIRENTRY));\r
-               int c;\r
-               for (c = 0; c < icon_header.idCount; c++) {\r
-                       hFile->Read(icon_list + c, sizeof(ICONDIRENTRY), 1);\r
-\r
-                       icon_list[c].wPlanes = ntohs(icon_list[c].wPlanes);\r
-                       icon_list[c].wBitCount = ntohs(icon_list[c].wBitCount);\r
-                       icon_list[c].dwBytesInRes = ntohl(icon_list[c].dwBytesInRes);\r
-                       icon_list[c].dwImageOffset = ntohl(icon_list[c].dwImageOffset);\r
-               }\r
-               \r
-               if ((page>=0)&&(page<icon_header.idCount)){\r
-\r
-                       if (info.nEscape == -1) {\r
-                               // Return output dimensions only\r
-                               head.biWidth = icon_list[page].bWidth;\r
-                               head.biHeight = icon_list[page].bHeight;\r
-#if CXIMAGE_SUPPORT_PNG\r
-                               if (head.biWidth==0 && head.biHeight==0)\r
-                               {       // Vista icon support\r
-                                       hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET);\r
-                                       CxImage png;\r
-                                       png.SetEscape(-1);\r
-                                       if (png.Decode(hFile,CXIMAGE_FORMAT_PNG)){\r
-                                               Transfer(png);\r
-                                               info.nNumFrames = icon_header.idCount;\r
-                                       }\r
-                               }\r
-#endif //CXIMAGE_SUPPORT_PNG\r
-                               free(icon_list);\r
-                               info.dwType = CXIMAGE_FORMAT_ICO;\r
-                               return true;\r
-                       }\r
-\r
-                       // get the bit count for the colors in the icon <CoreyRLucier>\r
-                       BITMAPINFOHEADER bih;\r
-                       hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET);\r
-\r
-                       if (icon_list[page].bWidth==0 && icon_list[page].bHeight==0)\r
-                       {       // Vista icon support\r
-#if CXIMAGE_SUPPORT_PNG\r
-                               CxImage png;\r
-                               if (png.Decode(hFile,CXIMAGE_FORMAT_PNG)){\r
-                                       Transfer(png);\r
-                                       info.nNumFrames = icon_header.idCount;\r
-                               }\r
-                               SetType(CXIMAGE_FORMAT_ICO);\r
-#endif //CXIMAGE_SUPPORT_PNG\r
-                       }\r
-                       else\r
-                       {       // standard icon\r
-                               hFile->Read(&bih,sizeof(BITMAPINFOHEADER),1);\r
-\r
-                               bihtoh(&bih);\r
-\r
-                               c = bih.biBitCount;\r
-\r
-                               // allocate memory for one icon\r
-                               Create(icon_list[page].bWidth,icon_list[page].bHeight, c, CXIMAGE_FORMAT_ICO);  //image creation\r
-\r
-                               // read the palette\r
-                               RGBQUAD pal[256];\r
-                               if (bih.biClrUsed)\r
-                                       hFile->Read(pal,bih.biClrUsed*sizeof(RGBQUAD), 1);\r
-                               else\r
-                                       hFile->Read(pal,head.biClrUsed*sizeof(RGBQUAD), 1);\r
-\r
-                               SetPalette(pal,head.biClrUsed); //palette assign\r
-\r
-                               //read the icon\r
-                               if (c<=24){\r
-                                       hFile->Read(info.pImage, head.biSizeImage, 1);\r
-                               } else { // 32 bit icon\r
-                                       BYTE* buf=(BYTE*)malloc(4*head.biHeight*head.biWidth);\r
-                                       BYTE* src = buf;\r
-                                       hFile->Read(buf, 4*head.biHeight*head.biWidth, 1);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       if (!AlphaIsValid()) AlphaCreate();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                                       for (long y = 0; y < head.biHeight; y++) {\r
-                                               BYTE* dst = GetBits(y);\r
-                                               for(long x=0;x<head.biWidth;x++){\r
-                                                       *dst++=src[0];\r
-                                                       *dst++=src[1];\r
-                                                       *dst++=src[2];\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                                       AlphaSet(x,y,src[3]);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                                                       src+=4;\r
-                                               }\r
-                                       }\r
-                                       free(buf);\r
-                               }\r
-                               // apply the AND and XOR masks\r
-                               int maskwdt = ((head.biWidth+31) / 32) * 4;     //line width of AND mask (always 1 Bpp)\r
-                               int masksize = head.biHeight * maskwdt;                         //size of mask\r
-                               BYTE *mask = (BYTE *)malloc(masksize);\r
-                               if (hFile->Read(mask, masksize, 1)){\r
-\r
-                                       bool bGoodMask=false;\r
-                                       for (int im=0;im<masksize;im++){\r
-                                               if (mask[im]!=255){\r
-                                                       bGoodMask=true;\r
-                                                       break;\r
-                                               }\r
-                                       }\r
-\r
-                                       if (bGoodMask){\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                               bool bNeedAlpha = false;\r
-                                               if (!AlphaIsValid()){\r
-                                                       AlphaCreate();\r
-                                               } else { \r
-                                                       bNeedAlpha=true; //32bit icon\r
-                                               }\r
-                                               int x,y;\r
-                                               for (y = 0; y < head.biHeight; y++) {\r
-                                                       for (x = 0; x < head.biWidth; x++) {\r
-                                                               if (((mask[y*maskwdt+(x>>3)]>>(7-x%8))&0x01)){\r
-                                                                       AlphaSet(x,y,0);\r
-                                                                       bNeedAlpha=true;\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                               if (!bNeedAlpha) AlphaDelete();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-                                               //check if there is only one transparent color\r
-                                               RGBQUAD cc,ct;\r
-                                               long* pcc = (long*)&cc;\r
-                                               long* pct = (long*)&ct;\r
-                                               int nTransColors=0;\r
-                                               int nTransIndex=0;\r
-                                               for (y = 0; y < head.biHeight; y++){\r
-                                                       for (x = 0; x < head.biWidth; x++){\r
-                                                               if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){\r
-                                                                       cc = GetPixelColor(x,y,false);\r
-                                                                       if (nTransColors==0){\r
-                                                                               nTransIndex = GetPixelIndex(x,y);\r
-                                                                               nTransColors++;\r
-                                                                               ct = cc;\r
-                                                                       } else {\r
-                                                                               if (*pct!=*pcc){\r
-                                                                                       nTransColors++;\r
-                                                                               }\r
-                                                                       }\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                               if (nTransColors==1){\r
-                                                       SetTransColor(ct);\r
-                                                       SetTransIndex(nTransIndex);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                                       AlphaDelete(); //because we have a unique transparent color in the image\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                                               }\r
-\r
-                                               // <vho> - Transparency support w/o Alpha support\r
-                                               if (c <= 8){ // only for icons with less than 256 colors (XP icons need alpha).\r
-                                                         \r
-                                                       // find a color index, which is not used in the image\r
-                                                       // it is almost sure to find one, bcs. nobody uses all possible colors for an icon\r
-\r
-                                                       BYTE colorsUsed[256];\r
-                                                       memset(colorsUsed, 0, sizeof(colorsUsed));\r
-\r
-                                                       for (y = 0; y < head.biHeight; y++){\r
-                                                               for (x = 0; x < head.biWidth; x++){\r
-                                                                       colorsUsed[BlindGetPixelIndex(x,y)] = 1;\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       int iTransIdx = -1;\r
-                                                       for (x = (int)(head.biClrUsed-1); x>=0 ; x--){\r
-                                                               if (colorsUsed[x] == 0){\r
-                                                                       iTransIdx = x; // this one is not in use. we may use it as transparent color\r
-                                                                       break;\r
-                                                               }\r
-                                                       }\r
-\r
-                                                       // Go thru image and set unused color as transparent index if needed\r
-                                                       if (iTransIdx >= 0){\r
-                                                               bool bNeedTrans = false;\r
-                                                               for (y = 0; y < head.biHeight; y++){\r
-                                                                       for (x = 0; x < head.biWidth; x++){\r
-                                                                               // AND mask (Each Byte represents 8 Pixels)\r
-                                                                               if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){\r
-                                                                                       // AND mask is set (!=0). This is a transparent part\r
-                                                                                       SetPixelIndex(x, y, (BYTE)iTransIdx);\r
-                                                                                       bNeedTrans = true;\r
-                                                                               }\r
-                                                                       }\r
-                                                               }\r
-                                                               // set transparent index if needed\r
-                                                               if (bNeedTrans) SetTransIndex(iTransIdx);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                                               AlphaDelete(); //because we have a transparent color in the palette\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                                                       }\r
-                                               }\r
-                                       } else {\r
-                                               SetTransIndex(0); //empty mask, set black as transparent color\r
-                                               Negative();\r
-                                       }\r
-                               } \r
-                               free(mask);\r
-                       }\r
-                       free(icon_list);\r
-                       // icon has been loaded successfully!\r
-                       return true;\r
-               }\r
-               free(icon_list);\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Thanks to <Alas>\r
-bool CxImageICO::Encode(CxFile * hFile, CxImage ** pImages, int nPageCount)\r
-{\r
-  cx_try\r
-  {\r
-       if (hFile==NULL) cx_throw("invalid file pointer");\r
-       if (pImages==NULL || nPageCount<=0) cx_throw("multipage ICO, no images!");\r
-\r
-       int i;\r
-       for (i=0; i<nPageCount; i++){\r
-               if (pImages[i]==NULL)\r
-                       cx_throw("Bad image pointer");\r
-               if (!(pImages[i]->IsValid()))\r
-                       cx_throw("Empty image");\r
-       }\r
-\r
-       CxImageICO ghost;\r
-       for (i=0; i<nPageCount; i++){   //write headers\r
-               ghost.Ghost(pImages[i]);\r
-               ghost.info.nNumFrames = nPageCount;\r
-               if (i==0) {\r
-                       if (!ghost.Encode(hFile,false,nPageCount))\r
-                               cx_throw("Error writing ICO file header");\r
-               }\r
-               if (!ghost.Encode(hFile,true,nPageCount)) \r
-                       cx_throw("Error saving ICO image header");\r
-       }\r
-       for (i=0; i<nPageCount; i++){   //write bodies\r
-               ghost.Ghost(pImages[i]);\r
-               ghost.info.nNumFrames = nPageCount;\r
-               if (!ghost.Encode(hFile,true,i)) \r
-                       cx_throw("Error saving ICO body");\r
-       }\r
-\r
-  } cx_catch {\r
-         if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-         return false;\r
-  }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageICO::Encode(CxFile * hFile, bool bAppend, int nPageCount)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-#if CXIMAGE_SUPPORT_PNG == 0\r
-       //check format limits\r
-       if ((head.biWidth>255)||(head.biHeight>255)){\r
-               strcpy(info.szLastError,"Can't save this image as icon");\r
-               return false;\r
-       }\r
-#endif\r
-\r
-       //prepare the palette struct\r
-       RGBQUAD* pal=GetPalette();\r
-       if (head.biBitCount<=8 && pal==NULL) return false;\r
-\r
-       int maskwdt=((head.biWidth+31)/32)*4; //mask line width\r
-       int masksize=head.biHeight * maskwdt; //size of mask\r
-       int bitcount=head.biBitCount;\r
-       int imagesize=head.biSizeImage;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid() && head.biClrUsed==0){\r
-               bitcount=32;\r
-               imagesize=4*head.biHeight*head.biWidth;\r
-       }\r
-#endif\r
-\r
-       //fill the icon headers\r
-       int nPages = nPageCount;\r
-       if (nPages<1) nPages = 1;\r
-\r
-       ICONHEADER icon_header={0,1,nPages};\r
-\r
-       if (!bAppend)\r
-               m_dwImageOffset = sizeof(ICONHEADER) + nPages * sizeof(ICONDIRENTRY);\r
-\r
-       DWORD dwBytesInRes = sizeof(BITMAPINFOHEADER)+head.biClrUsed*sizeof(RGBQUAD)+imagesize+masksize;\r
-\r
-       ICONDIRENTRY icon_list={\r
-               (BYTE)head.biWidth,\r
-               (BYTE)head.biHeight,\r
-               (BYTE)head.biClrUsed,\r
-               0, 0,\r
-               (WORD)bitcount,\r
-               dwBytesInRes,\r
-               m_dwImageOffset\r
-       };\r
-\r
-       BITMAPINFOHEADER bi={\r
-               sizeof(BITMAPINFOHEADER),\r
-               head.biWidth,\r
-               2*head.biHeight,\r
-               1,\r
-               (WORD)bitcount,\r
-               0, imagesize,\r
-               0, 0, 0, 0\r
-       };\r
-\r
-#if CXIMAGE_SUPPORT_PNG // Vista icon support\r
-       CxImage png(*this);\r
-       CxMemFile memfile;\r
-       if (head.biWidth>255 || head.biHeight>255){\r
-               icon_list.bWidth = icon_list.bHeight = 0;\r
-               memfile.Open();\r
-               png.Encode(&memfile,CXIMAGE_FORMAT_PNG);\r
-               icon_list.dwBytesInRes = dwBytesInRes = memfile.Size();\r
-       }\r
-#endif //CXIMAGE_SUPPORT_PNG\r
-\r
-       if (!bAppend){\r
-               icon_header.idType = ntohs(icon_header.idType);\r
-               icon_header.idCount = ntohs(icon_header.idCount);\r
-               hFile->Write(&icon_header,sizeof(ICONHEADER),1);        //write the file header\r
-               icon_header.idType = ntohs(icon_header.idType);\r
-               icon_header.idCount = ntohs(icon_header.idCount);\r
-       }\r
-\r
-\r
-       if ((bAppend && nPageCount==info.nNumFrames) || (!bAppend && nPageCount==0)){\r
-               icon_list.wPlanes = ntohs(icon_list.wPlanes);\r
-               icon_list.wBitCount = ntohs(icon_list.wBitCount);\r
-               icon_list.dwBytesInRes = ntohl(icon_list.dwBytesInRes);\r
-               icon_list.dwImageOffset = ntohl(icon_list.dwImageOffset);\r
-               hFile->Write(&icon_list,sizeof(ICONDIRENTRY),1);        //write the image entry\r
-               icon_list.wPlanes = ntohs(icon_list.wPlanes);\r
-               icon_list.wBitCount = ntohs(icon_list.wBitCount);\r
-               icon_list.dwBytesInRes = ntohl(icon_list.dwBytesInRes);\r
-               icon_list.dwImageOffset = ntohl(icon_list.dwImageOffset);\r
-\r
-               m_dwImageOffset += dwBytesInRes;                        //update offset for next header\r
-       }\r
-\r
-       if ((bAppend && nPageCount<info.nNumFrames) || (!bAppend && nPageCount==0))\r
-       {\r
-#if CXIMAGE_SUPPORT_PNG\r
-               if (icon_list.bWidth==0 && icon_list.bHeight==0) {      // Vista icon support\r
-                       hFile->Write(memfile.GetBuffer(false),dwBytesInRes,1);\r
-               } else\r
-#endif //CXIMAGE_SUPPORT_PNG\r
-               {       // standard icon\r
-                       bihtoh(&bi);\r
-                       hFile->Write(&bi,sizeof(BITMAPINFOHEADER),1);                   //write the image header\r
-                       bihtoh(&bi);\r
-\r
-                       bool bTransparent = info.nBkgndIndex >= 0;\r
-                       RGBQUAD ct = GetTransColor();\r
-                       if (pal){\r
-                               if (bTransparent) SetPaletteColor((BYTE)info.nBkgndIndex,0,0,0,0);\r
-                               hFile->Write(pal,head.biClrUsed*sizeof(RGBQUAD),1); //write palette\r
-                               if (bTransparent) SetPaletteColor((BYTE)info.nBkgndIndex,ct);\r
-                       }\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       if (AlphaIsValid() && head.biClrUsed==0){\r
-                               BYTE* buf=(BYTE*)malloc(imagesize);\r
-                               BYTE* dst = buf;\r
-                               for (long y = 0; y < head.biHeight; y++) {\r
-                                       BYTE* src = GetBits(y);\r
-                                       for(long x=0;x<head.biWidth;x++){\r
-                                               *dst++=*src++;\r
-                                               *dst++=*src++;\r
-                                               *dst++=*src++;\r
-                                               *dst++=AlphaGet(x,y);\r
-                                       }\r
-                               }\r
-                               hFile->Write(buf,imagesize, 1);\r
-                               free(buf);\r
-                       } else {\r
-                               hFile->Write(info.pImage,imagesize,1);  //write image\r
-                       }\r
-#else\r
-                       hFile->Write(info.pImage,imagesize,1);  //write image\r
-#endif\r
-\r
-                       //save transparency mask\r
-                       BYTE* mask=(BYTE*)calloc(masksize,1);   //create empty AND/XOR masks\r
-                       if (!mask) return false;\r
-\r
-                       //prepare the variables to build the mask\r
-                       BYTE* iDst;\r
-                       int pos,i;\r
-                       RGBQUAD c={0,0,0,0};\r
-                       long* pc = (long*)&c;\r
-                       long* pct= (long*)&ct;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       bool bAlphaPaletteIsValid = AlphaPaletteIsValid();\r
-                       bool bAlphaIsValid = AlphaIsValid();\r
-#endif\r
-                       //build the mask\r
-                       for (int y = 0; y < head.biHeight; y++) {\r
-                               for (int x = 0; x < head.biWidth; x++) {\r
-                                       i=0;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       if (bAlphaIsValid && AlphaGet(x,y)==0) i=1;\r
-                                       if (bAlphaPaletteIsValid && BlindGetPixelColor(x,y).rgbReserved==0) i=1;\r
-#endif\r
-                                       c=GetPixelColor(x,y,false);\r
-                                       if (bTransparent && *pc==*pct) i=1;\r
-                                       iDst = mask + y*maskwdt + (x>>3);\r
-                                       pos = 7-x%8;\r
-                                       *iDst &= ~(0x01<<pos);\r
-                                       *iDst |= ((i & 0x01)<<pos);\r
-                               }\r
-                       }\r
-                       //write AND/XOR masks\r
-                       hFile->Write(mask,masksize,1);\r
-                       free(mask);\r
-               }\r
-       }\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ICO\r
-\r
+/*
+ * File:       ximaico.cpp
+ * Purpose:    Platform Independent ICON Image Class Loader and Writer (MS version)
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximaico.h"
+
+#if CXIMAGE_SUPPORT_ICO
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageICO::Decode(CxFile *hFile)
+{
+       if (hFile==NULL) return false;
+
+       DWORD off = hFile->Tell(); //<yuandi>
+       int     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 = ntohs(icon_header.idType);
+       icon_header.idCount = 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));
+               int c;
+               for (c = 0; c < icon_header.idCount; c++) {
+                       hFile->Read(icon_list + c, sizeof(ICONDIRENTRY), 1);
+
+                       icon_list[c].wPlanes = ntohs(icon_list[c].wPlanes);
+                       icon_list[c].wBitCount = ntohs(icon_list[c].wBitCount);
+                       icon_list[c].dwBytesInRes = ntohl(icon_list[c].dwBytesInRes);
+                       icon_list[c].dwImageOffset = 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
+                                       BYTE* buf=(BYTE*)malloc(4*head.biHeight*head.biWidth);
+                                       BYTE* src = buf;
+                                       hFile->Read(buf, 4*head.biHeight*head.biWidth, 1);
+#if CXIMAGE_SUPPORT_ALPHA
+                                       if (!AlphaIsValid()) AlphaCreate();
+#endif //CXIMAGE_SUPPORT_ALPHA
+                                       for (long y = 0; y < head.biHeight; y++) {
+                                               BYTE* dst = GetBits(y);
+                                               for(long 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
+                               int maskwdt = ((head.biWidth+31) / 32) * 4;     //line width of AND mask (always 1 Bpp)
+                               int masksize = head.biHeight * maskwdt;                         //size of mask
+                               BYTE *mask = (BYTE *)malloc(masksize);
+                               if (hFile->Read(mask, masksize, 1)){
+
+                                       bool bGoodMask=false;
+                                       for (int 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
+                                               }
+                                               int 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;
+                                               long* pcc = (long*)&cc;
+                                               long* pct = (long*)&ct;
+                                               int nTransColors=0;
+                                               int 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 (*pct!=*pcc){
+                                                                                       nTransColors++;
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                               if (nTransColors==1){
+                                                       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
+
+                                                       BYTE 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;
+                                                               }
+                                                       }
+
+                                                       int iTransIdx = -1;
+                                                       for (x = (int)(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, (BYTE)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, int nPageCount)
+{
+  cx_try
+  {
+       if (hFile==NULL) cx_throw("invalid file pointer");
+       if (pImages==NULL || nPageCount<=0) cx_throw("multipage ICO, no images!");
+
+       int 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, int 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;
+
+       int maskwdt=((head.biWidth+31)/32)*4; //mask line width
+       int masksize=head.biHeight * maskwdt; //size of mask
+       int bitcount=head.biBitCount;
+       int 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
+       int nPages = nPageCount;
+       if (nPages<1) nPages = 1;
+
+       ICONHEADER icon_header={0,1,nPages};
+
+       if (!bAppend)
+               m_dwImageOffset = sizeof(ICONHEADER) + nPages * sizeof(ICONDIRENTRY);
+
+       DWORD dwBytesInRes = sizeof(BITMAPINFOHEADER)+head.biClrUsed*sizeof(RGBQUAD)+imagesize+masksize;
+
+       ICONDIRENTRY icon_list={
+               (BYTE)head.biWidth,
+               (BYTE)head.biHeight,
+               (BYTE)head.biClrUsed,
+               0, 0,
+               (WORD)bitcount,
+               dwBytesInRes,
+               m_dwImageOffset
+       };
+
+       BITMAPINFOHEADER bi={
+               sizeof(BITMAPINFOHEADER),
+               head.biWidth,
+               2*head.biHeight,
+               1,
+               (WORD)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 = ntohs(icon_header.idType);
+               icon_header.idCount = ntohs(icon_header.idCount);
+               hFile->Write(&icon_header,sizeof(ICONHEADER),1);        //write the file header
+               icon_header.idType = ntohs(icon_header.idType);
+               icon_header.idCount = ntohs(icon_header.idCount);
+       }
+
+
+       if ((bAppend && nPageCount==info.nNumFrames) || (!bAppend && nPageCount==0)){
+               icon_list.wPlanes = ntohs(icon_list.wPlanes);
+               icon_list.wBitCount = ntohs(icon_list.wBitCount);
+               icon_list.dwBytesInRes = ntohl(icon_list.dwBytesInRes);
+               icon_list.dwImageOffset = ntohl(icon_list.dwImageOffset);
+               hFile->Write(&icon_list,sizeof(ICONDIRENTRY),1);        //write the image entry
+               icon_list.wPlanes = ntohs(icon_list.wPlanes);
+               icon_list.wBitCount = ntohs(icon_list.wBitCount);
+               icon_list.dwBytesInRes = ntohl(icon_list.dwBytesInRes);
+               icon_list.dwImageOffset = 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((BYTE)info.nBkgndIndex,0,0,0,0);
+                               hFile->Write(pal,head.biClrUsed*sizeof(RGBQUAD),1); //write palette
+                               if (bTransparent) SetPaletteColor((BYTE)info.nBkgndIndex,ct);
+                       }
+
+#if CXIMAGE_SUPPORT_ALPHA
+                       if (AlphaIsValid() && head.biClrUsed==0){
+                               BYTE* buf=(BYTE*)malloc(imagesize);
+                               BYTE* dst = buf;
+                               for (long y = 0; y < head.biHeight; y++) {
+                                       BYTE* src = GetBits(y);
+                                       for(long 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
+                       BYTE* mask=(BYTE*)calloc(masksize,1);   //create empty AND/XOR masks
+                       if (!mask) return false;
+
+                       //prepare the variables to build the mask
+                       BYTE* iDst;
+                       int pos,i;
+                       RGBQUAD c={0,0,0,0};
+                       long* pc = (long*)&c;
+                       long* pct= (long*)&ct;
+#if CXIMAGE_SUPPORT_ALPHA
+                       bool bAlphaPaletteIsValid = AlphaPaletteIsValid();
+                       bool bAlphaIsValid = AlphaIsValid();
+#endif
+                       //build the mask
+                       for (int y = 0; y < head.biHeight; y++) {
+                               for (int 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
+
index 837939a7dcccca87c637dc7e58c23a41bb4e615d..86ef4eafcefe9fd86e080f8dc3d13f24e2f0128e 100644 (file)
@@ -1,58 +1,58 @@
-/*\r
- * File:       ximaico.h\r
- * Purpose:    ICON Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageICO (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaICO_h)\r
-#define __ximaICO_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_ICO\r
-\r
-class CxImageICO: public CxImage\r
-{\r
-typedef struct tagIconDirectoryEntry {\r
-    BYTE  bWidth;\r
-    BYTE  bHeight;\r
-    BYTE  bColorCount;\r
-    BYTE  bReserved;\r
-    WORD  wPlanes;\r
-    WORD  wBitCount;\r
-    DWORD dwBytesInRes;\r
-    DWORD dwImageOffset;\r
-} ICONDIRENTRY;\r
-\r
-typedef struct tagIconDir {\r
-    WORD          idReserved;\r
-    WORD          idType;\r
-    WORD          idCount;\r
-} ICONHEADER;\r
-\r
-public:\r
-       CxImageICO(): CxImage(CXIMAGE_FORMAT_ICO) {m_dwImageOffset=0;}\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_ICO);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_ICO);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile, bool bAppend=false, int nPageCount=0);\r
-       bool Encode(CxFile * hFile, CxImage ** pImages, int nPageCount);\r
-       bool Encode(FILE *hFile, bool bAppend=false, int nPageCount=0)\r
-                               { CxIOFile file(hFile); return Encode(&file,bAppend,nPageCount); }\r
-       bool Encode(FILE *hFile, CxImage ** pImages, int nPageCount)\r
-                               { CxIOFile file(hFile); return Encode(&file, pImages, nPageCount); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-protected:\r
-       DWORD m_dwImageOffset;\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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 {
+    BYTE  bWidth;
+    BYTE  bHeight;
+    BYTE  bColorCount;
+    BYTE  bReserved;
+    WORD  wPlanes;
+    WORD  wBitCount;
+    DWORD dwBytesInRes;
+    DWORD dwImageOffset;
+} ICONDIRENTRY;
+
+typedef struct tagIconDir {
+    WORD          idReserved;
+    WORD          idType;
+    WORD          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, int nPageCount=0);
+       bool Encode(CxFile * hFile, CxImage ** pImages, int nPageCount);
+       bool Encode(FILE *hFile, bool bAppend=false, int nPageCount=0)
+                               { CxIOFile file(hFile); return Encode(&file,bAppend,nPageCount); }
+       bool Encode(FILE *hFile, CxImage ** pImages, int nPageCount)
+                               { CxIOFile file(hFile); return Encode(&file, pImages, nPageCount); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+protected:
+       DWORD m_dwImageOffset;
+};
+
+#endif
+
+#endif
index fd453f2f778e22b485d8b9ea68d654f377237fbc..28cbad40cc42b11e9f9b7585af9fecd88bdf3314 100644 (file)
-// ximainfo.cpp : main attributes\r
-/* 03/10/2004 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return the color used for transparency, and/or for background color\r
- */\r
-RGBQUAD        CxImage::GetTransColor()\r
-{\r
-       if (head.biBitCount<24 && info.nBkgndIndex>=0) return GetPaletteColor((BYTE)info.nBkgndIndex);\r
-       return info.nBkgndColor;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Gets the index used for transparency. Returns -1 for no transparancy.\r
- */\r
-long CxImage::GetTransIndex() const\r
-{\r
-       return info.nBkgndIndex;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the index used for transparency with 1, 4 and 8 bpp images. Set to -1 to remove the effect.\r
- */\r
-void CxImage::SetTransIndex(long idx)\r
-{\r
-       if (idx<(long)head.biClrUsed)\r
-               info.nBkgndIndex = idx;\r
-       else \r
-               info.nBkgndIndex = 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the color used for transparency with 24 bpp images.\r
- * You must call SetTransIndex(0) to enable the effect, SetTransIndex(-1) to disable it.\r
- */\r
-void CxImage::SetTransColor(RGBQUAD rgb)\r
-{\r
-       rgb.rgbReserved=0;\r
-       info.nBkgndColor = rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::IsTransparent() const\r
-{\r
-       return info.nBkgndIndex>=0; // <vho>\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns true if the image has 256 colors or less.\r
- */\r
-bool CxImage::IsIndexed() const\r
-{\r
-       return head.biClrUsed!=0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return 1 = indexed, 2 = RGB, 4 = RGBA\r
- */\r
-BYTE CxImage::GetColorType()\r
-{\r
-       BYTE b = (BYTE)((head.biBitCount>8) ? 2 /*COLORTYPE_COLOR*/ : 1 /*COLORTYPE_PALETTE*/);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()) b = 4 /*COLORTYPE_ALPHA*/;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       return b;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return Resolution for TIFF, JPEG, PNG and BMP formats.\r
- */\r
-long CxImage::GetXDPI() const\r
-{\r
-       return info.xDPI;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return Resolution for TIFF, JPEG, PNG and BMP formats.\r
- */\r
-long CxImage::GetYDPI() const\r
-{\r
-       return info.yDPI;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Set resolution for TIFF, JPEG, PNG and BMP formats.\r
- */\r
-void CxImage::SetXDPI(long dpi)\r
-{\r
-       if (dpi<=0) dpi = CXIMAGE_DEFAULT_DPI;\r
-       info.xDPI = dpi;\r
-       head.biXPelsPerMeter = (long) floor(dpi * 10000.0 / 254.0 + 0.5);\r
-       if (pDib) ((BITMAPINFOHEADER*)pDib)->biXPelsPerMeter = head.biXPelsPerMeter;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Set resolution for TIFF, JPEG, PNG and BMP formats.\r
- */\r
-void CxImage::SetYDPI(long dpi)\r
-{\r
-       if (dpi<=0) dpi = CXIMAGE_DEFAULT_DPI;\r
-       info.yDPI = dpi;\r
-       head.biYPelsPerMeter = (long) floor(dpi * 10000.0 / 254.0 + 0.5);\r
-       if (pDib) ((BITMAPINFOHEADER*)pDib)->biYPelsPerMeter = head.biYPelsPerMeter;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa SetFlags\r
- */\r
-DWORD CxImage::GetFlags() const\r
-{\r
-       return info.dwFlags;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Image flags, for future use\r
- * \param flags\r
- *  - 0x??00000 = reserved for 16 bit, CMYK, multilayer\r
- *  - 0x00??0000 = blend modes\r
- *  - 0x0000???? = layer id or user flags\r
- *\r
- * \param bLockReservedFlags protects the "reserved" and "blend modes" flags \r
- */\r
-void CxImage::SetFlags(DWORD flags, bool bLockReservedFlags)\r
-{\r
-       if (bLockReservedFlags) info.dwFlags = flags & 0x0000ffff;\r
-       else info.dwFlags = flags;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa SetCodecOption\r
- */\r
-DWORD CxImage::GetCodecOption(DWORD imagetype)\r
-{\r
-       imagetype = GetTypeIndexFromId(imagetype);\r
-       if (imagetype==0){\r
-               imagetype = GetTypeIndexFromId(GetType());\r
-       }\r
-       return info.dwCodecOpt[imagetype];\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Encode option for GIF, TIF and JPG.\r
- * - GIF : 0 = LZW (default), 1 = none, 2 = RLE.\r
- * - TIF : 0 = automatic (default), or a valid compression code as defined in "tiff.h" (COMPRESSION_NONE = 1, COMPRESSION_CCITTRLE = 2, ...)\r
- * - JPG : valid values stored in enum CODEC_OPTION ( ENCODE_BASELINE = 0x01, ENCODE_PROGRESSIVE = 0x10, ...)\r
- * - RAW : valid values stored in enum CODEC_OPTION ( DECODE_QUALITY_LIN = 0x00, DECODE_QUALITY_VNG = 0x01, ...)\r
- *\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::SetCodecOption(DWORD opt, DWORD imagetype)\r
-{\r
-       imagetype = GetTypeIndexFromId(imagetype);\r
-       if (imagetype==0){\r
-               imagetype = GetTypeIndexFromId(GetType());\r
-       }\r
-       info.dwCodecOpt[imagetype] = opt;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return internal hDib object..\r
- */\r
-void* CxImage::GetDIB() const\r
-{\r
-       return pDib;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-DWORD CxImage::GetHeight() const\r
-{\r
-       return head.biHeight;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-DWORD CxImage::GetWidth() const\r
-{\r
-       return head.biWidth;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return DWORD aligned width of the image.\r
- */\r
-DWORD CxImage::GetEffWidth() const\r
-{\r
-       return info.dwEffWidth;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return 2, 16, 256; 0 for RGB images.\r
- */\r
-DWORD CxImage::GetNumColors() const\r
-{\r
-       return head.biClrUsed;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return: 1, 4, 8, 24.\r
- */\r
-WORD CxImage::GetBpp() const\r
-{\r
-       return head.biBitCount;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return original image format\r
- * \sa ENUM_CXIMAGE_FORMATS.\r
- */\r
-DWORD CxImage::GetType() const\r
-{\r
-       return info.dwType;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * change image format identifier\r
- * \sa ENUM_CXIMAGE_FORMATS.\r
- */\r
-bool CxImage::SetType(DWORD type)\r
-{\r
-       switch (type){\r
-#if CXIMAGE_SUPPORT_BMP\r
-       case CXIMAGE_FORMAT_BMP:\r
-#endif\r
-#if CXIMAGE_SUPPORT_GIF\r
-       case CXIMAGE_FORMAT_GIF:\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPG\r
-       case CXIMAGE_FORMAT_JPG:\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNG\r
-       case CXIMAGE_FORMAT_PNG:\r
-#endif\r
-#if CXIMAGE_SUPPORT_MNG\r
-       case CXIMAGE_FORMAT_MNG:\r
-#endif\r
-#if CXIMAGE_SUPPORT_ICO\r
-       case CXIMAGE_FORMAT_ICO:\r
-#endif\r
-#if CXIMAGE_SUPPORT_TIF\r
-       case CXIMAGE_FORMAT_TIF:\r
-#endif\r
-#if CXIMAGE_SUPPORT_TGA\r
-       case CXIMAGE_FORMAT_TGA:\r
-#endif\r
-#if CXIMAGE_SUPPORT_PCX\r
-       case CXIMAGE_FORMAT_PCX:\r
-#endif\r
-#if CXIMAGE_SUPPORT_WBMP\r
-       case CXIMAGE_FORMAT_WBMP:\r
-#endif\r
-#if CXIMAGE_SUPPORT_WMF\r
-       case CXIMAGE_FORMAT_WMF:\r
-#endif\r
-#if CXIMAGE_SUPPORT_JBG\r
-       case CXIMAGE_FORMAT_JBG:\r
-#endif\r
-#if CXIMAGE_SUPPORT_JP2\r
-       case CXIMAGE_FORMAT_JP2:\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPC\r
-       case CXIMAGE_FORMAT_JPC:\r
-#endif\r
-#if CXIMAGE_SUPPORT_PGX\r
-       case CXIMAGE_FORMAT_PGX:\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNM\r
-       case CXIMAGE_FORMAT_PNM:\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAS\r
-       case CXIMAGE_FORMAT_RAS:\r
-#endif\r
-#if CXIMAGE_SUPPORT_SKA\r
-       case CXIMAGE_FORMAT_SKA:\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAW\r
-       case CXIMAGE_FORMAT_RAW:\r
-#endif\r
-               info.dwType = type;\r
-               return true;\r
-       }\r
-       info.dwType = CXIMAGE_FORMAT_UNKNOWN;\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-DWORD CxImage::GetNumTypes()\r
-{\r
-       return CMAX_IMAGE_FORMATS-1;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-DWORD CxImage::GetTypeIdFromName(const TCHAR* ext)\r
-{\r
-#if CXIMAGE_SUPPORT_BMP\r
-       if (_tcsnicmp(ext,_T("bmp"),3)==0 )             return CXIMAGE_FORMAT_BMP;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPG\r
-       if (_tcsnicmp(ext,_T("jpg"),3)==0 ||\r
-               _tcsnicmp(ext,_T("jpe"),3)==0 ||\r
-               _tcsnicmp(ext,_T("jfi"),3)==0 )         return CXIMAGE_FORMAT_JPG;\r
-#endif\r
-#if CXIMAGE_SUPPORT_GIF\r
-       if (_tcsnicmp(ext,_T("gif"),3)==0 )             return CXIMAGE_FORMAT_GIF;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNG\r
-       if (_tcsnicmp(ext,_T("png"),3)==0 )             return CXIMAGE_FORMAT_PNG;\r
-#endif\r
-#if CXIMAGE_SUPPORT_ICO\r
-       if (_tcsnicmp(ext,_T("ico"),3)==0 ||\r
-               _tcsnicmp(ext,_T("cur"),3)==0 )         return CXIMAGE_FORMAT_ICO;\r
-#endif\r
-#if CXIMAGE_SUPPORT_TIF\r
-       if (_tcsnicmp(ext,_T("tif"),3)==0 )             return CXIMAGE_FORMAT_TIF;\r
-#endif\r
-#if CXIMAGE_SUPPORT_TGA\r
-       if (_tcsnicmp(ext,_T("tga"),3)==0 )             return CXIMAGE_FORMAT_TGA;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PCX\r
-       if (_tcsnicmp(ext,_T("pcx"),3)==0 )             return CXIMAGE_FORMAT_PCX;\r
-#endif\r
-#if CXIMAGE_SUPPORT_WBMP\r
-       if (_tcsnicmp(ext,_T("wbm"),3)==0 )             return CXIMAGE_FORMAT_WBMP;\r
-#endif\r
-#if CXIMAGE_SUPPORT_WMF\r
-       if (_tcsnicmp(ext,_T("wmf"),3)==0 ||\r
-               _tcsnicmp(ext,_T("emf"),3)==0 )         return CXIMAGE_FORMAT_WMF;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JP2\r
-       if (_tcsnicmp(ext,_T("jp2"),3)==0 ||\r
-               _tcsnicmp(ext,_T("j2k"),3)==0 )         return CXIMAGE_FORMAT_JP2;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPC\r
-       if (_tcsnicmp(ext,_T("jpc"),3)==0 ||\r
-               _tcsnicmp(ext,_T("j2c"),3)==0 )         return CXIMAGE_FORMAT_JPC;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PGX\r
-       if (_tcsnicmp(ext,_T("pgx"),3)==0 )             return CXIMAGE_FORMAT_PGX;\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAS\r
-       if (_tcsnicmp(ext,_T("ras"),3)==0 )             return CXIMAGE_FORMAT_RAS;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNM\r
-       if (_tcsnicmp(ext,_T("pnm"),3)==0 ||\r
-               _tcsnicmp(ext,_T("pgm"),3)==0 ||\r
-               _tcsnicmp(ext,_T("ppm"),3)==0 )         return CXIMAGE_FORMAT_PNM;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JBG\r
-       if (_tcsnicmp(ext,_T("jbg"),3)==0 )             return CXIMAGE_FORMAT_JBG;\r
-#endif\r
-#if CXIMAGE_SUPPORT_MNG\r
-       if (_tcsnicmp(ext,_T("mng"),3)==0 ||\r
-               _tcsnicmp(ext,_T("jng"),3)==0 )         return CXIMAGE_FORMAT_MNG;\r
-#endif\r
-#if CXIMAGE_SUPPORT_SKA\r
-       if (_tcsnicmp(ext,_T("ska"),3)==0 )             return CXIMAGE_FORMAT_SKA;\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAW\r
-       if (_tcsnicmp(ext,_T("nef"),3)==0 ||\r
-               _tcsnicmp(ext,_T("crw"),3)==0 ||\r
-               _tcsnicmp(ext,_T("cr2"),3)==0 ||\r
-               _tcsnicmp(ext,_T("dng"),3)==0 ||\r
-               _tcsnicmp(ext,_T("arw"),3)==0 ||\r
-               _tcsnicmp(ext,_T("erf"),3)==0 ||\r
-               _tcsnicmp(ext,_T("3fr"),3)==0 ||\r
-               _tcsnicmp(ext,_T("dcr"),3)==0 ||\r
-               _tcsnicmp(ext,_T("raw"),3)==0 ||\r
-               _tcsnicmp(ext,_T("x3f"),3)==0 ||\r
-               _tcsnicmp(ext,_T("mef"),3)==0 ||\r
-               _tcsnicmp(ext,_T("raf"),3)==0 ||\r
-               _tcsnicmp(ext,_T("mrw"),3)==0 ||\r
-               _tcsnicmp(ext,_T("pef"),3)==0 ||\r
-               _tcsnicmp(ext,_T("sr2"),3)==0 ||\r
-               _tcsnicmp(ext,_T("orf"),3)==0 )         return CXIMAGE_FORMAT_RAW;\r
-#endif\r
-\r
-       return CXIMAGE_FORMAT_UNKNOWN;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-DWORD CxImage::GetTypeIdFromIndex(const DWORD index)\r
-{\r
-       DWORD n;\r
-\r
-       n=0; if (index == n) return CXIMAGE_FORMAT_UNKNOWN;\r
-#if CXIMAGE_SUPPORT_BMP\r
-       n++; if (index == n) return CXIMAGE_FORMAT_BMP;\r
-#endif\r
-#if CXIMAGE_SUPPORT_GIF\r
-       n++; if (index == n) return CXIMAGE_FORMAT_GIF;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPG\r
-       n++; if (index == n) return CXIMAGE_FORMAT_JPG;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNG\r
-       n++; if (index == n) return CXIMAGE_FORMAT_PNG;\r
-#endif\r
-#if CXIMAGE_SUPPORT_ICO\r
-       n++; if (index == n) return CXIMAGE_FORMAT_ICO;\r
-#endif\r
-#if CXIMAGE_SUPPORT_TIF\r
-       n++; if (index == n) return CXIMAGE_FORMAT_TIF;\r
-#endif\r
-#if CXIMAGE_SUPPORT_TGA\r
-       n++; if (index == n) return CXIMAGE_FORMAT_TGA;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PCX\r
-       n++; if (index == n) return CXIMAGE_FORMAT_PCX;\r
-#endif\r
-#if CXIMAGE_SUPPORT_WBMP\r
-       n++; if (index == n) return CXIMAGE_FORMAT_WBMP;\r
-#endif\r
-#if CXIMAGE_SUPPORT_WMF\r
-       n++; if (index == n) return CXIMAGE_FORMAT_WMF;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JP2\r
-       n++; if (index == n) return CXIMAGE_FORMAT_JP2;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPC\r
-       n++; if (index == n) return CXIMAGE_FORMAT_JPC;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PGX\r
-       n++; if (index == n) return CXIMAGE_FORMAT_PGX;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNM\r
-       n++; if (index == n) return CXIMAGE_FORMAT_PNM;\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAS\r
-       n++; if (index == n) return CXIMAGE_FORMAT_RAS;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JBG\r
-       n++; if (index == n) return CXIMAGE_FORMAT_JBG;\r
-#endif\r
-#if CXIMAGE_SUPPORT_MNG\r
-       n++; if (index == n) return CXIMAGE_FORMAT_MNG;\r
-#endif\r
-#if CXIMAGE_SUPPORT_SKA\r
-       n++; if (index == n) return CXIMAGE_FORMAT_SKA;\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAW\r
-       n++; if (index == n) return CXIMAGE_FORMAT_RAW;\r
-#endif\r
-\r
-       return CXIMAGE_FORMAT_UNKNOWN;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-DWORD CxImage::GetTypeIndexFromId(const DWORD id)\r
-{\r
-       DWORD n;\r
-\r
-       n=0; if (id == CXIMAGE_FORMAT_UNKNOWN) return n;\r
-#if CXIMAGE_SUPPORT_BMP\r
-       n++; if (id == CXIMAGE_FORMAT_BMP) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_GIF\r
-       n++; if (id == CXIMAGE_FORMAT_GIF) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPG\r
-       n++; if (id == CXIMAGE_FORMAT_JPG) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNG\r
-       n++; if (id == CXIMAGE_FORMAT_PNG) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_ICO\r
-       n++; if (id == CXIMAGE_FORMAT_ICO) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_TIF\r
-       n++; if (id == CXIMAGE_FORMAT_TIF) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_TGA\r
-       n++; if (id == CXIMAGE_FORMAT_TGA) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PCX\r
-       n++; if (id == CXIMAGE_FORMAT_PCX) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_WBMP\r
-       n++; if (id == CXIMAGE_FORMAT_WBMP) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_WMF\r
-       n++; if (id == CXIMAGE_FORMAT_WMF) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JP2\r
-       n++; if (id == CXIMAGE_FORMAT_JP2) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPC\r
-       n++; if (id == CXIMAGE_FORMAT_JPC) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PGX\r
-       n++; if (id == CXIMAGE_FORMAT_PGX) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNM\r
-       n++; if (id == CXIMAGE_FORMAT_PNM) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAS\r
-       n++; if (id == CXIMAGE_FORMAT_RAS) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JBG\r
-       n++; if (id == CXIMAGE_FORMAT_JBG) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_MNG\r
-       n++; if (id == CXIMAGE_FORMAT_MNG) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_SKA\r
-       n++; if (id == CXIMAGE_FORMAT_SKA) return n;\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAW\r
-       n++; if (id == CXIMAGE_FORMAT_RAW) return n;\r
-#endif\r
-\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return current frame delay in milliseconds. Only for GIF and MNG formats.\r
- */\r
-DWORD CxImage::GetFrameDelay() const\r
-{\r
-       return info.dwFrameDelay;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets current frame delay. Only for GIF format.\r
- * \param d = delay in milliseconds\r
- */\r
-void CxImage::SetFrameDelay(DWORD d)\r
-{\r
-       info.dwFrameDelay=d;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::GetOffset(long *x,long *y)\r
-{\r
-       *x=info.xOffset;\r
-       *y=info.yOffset;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetOffset(long x,long y)\r
-{\r
-       info.xOffset=x;\r
-       info.yOffset=y;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa SetJpegQuality, GetJpegQualityF\r
- * \author [DP]; changes [Stefan Schürmans]\r
- */\r
-BYTE CxImage::GetJpegQuality() const\r
-{\r
-       return (BYTE)(info.fQuality + 0.5f);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa SetJpegQuality, GetJpegQuality\r
- * \author [Stefan Schürmans]\r
- */\r
-float CxImage::GetJpegQualityF() const\r
-{\r
-       return info.fQuality;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * quality level for JPEG and JPEG2000\r
- * \param q: can be from 0 to 100\r
- * \author [DP]; changes [Stefan Schürmans]\r
- */\r
-void CxImage::SetJpegQuality(BYTE q){\r
-       info.fQuality = (float)q;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * quality level for JPEG and JPEG2000\r
- * necessary for JPEG2000 when quality is between 0.0 and 1.0\r
- * \param q: can be from 0.0 to 100.0\r
- * \author [Stefan Schürmans]\r
- */\r
-void CxImage::SetJpegQualityF(float q){\r
-       if (q>0) info.fQuality = q;\r
-       else  info.fQuality = 0.0f;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa SetJpegScale\r
- */\r
-BYTE CxImage::GetJpegScale() const\r
-{\r
-       return info.nJpegScale;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * scaling down during JPEG decoding valid numbers are 1, 2, 4, 8\r
- * \author [ignacio]\r
- */\r
-void CxImage::SetJpegScale(BYTE q){\r
-       info.nJpegScale = q;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Used to monitor the slow loops.\r
- * \return value is from 0 to 100.\r
- * \sa SetProgress\r
- */\r
-long CxImage::GetProgress() const\r
-{\r
-       return info.nProgress;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return the escape code.\r
- * \sa SetEscape\r
- */\r
-long CxImage::GetEscape() const\r
-{\r
-       return info.nEscape;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Forces the value of the internal progress variable.\r
- * \param p should be from 0 to 100.\r
- * \sa GetProgress\r
- */\r
-void CxImage::SetProgress(long p)\r
-{\r
-       info.nProgress = p;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Used to quit the slow loops or the codecs.\r
- * - SetEscape(-1) before Decode forces the function to exit, right after  \r
- *   the image width and height are available ( for bmp, jpg, gif, tif )\r
- */\r
-void CxImage::SetEscape(long i)\r
-{\r
-       info.nEscape = i;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if the image is correctly initializated.\r
- */\r
-bool CxImage::IsValid() const\r
-{\r
-       return pDib!=0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * True if the image is enabled for painting.\r
- */\r
-bool CxImage::IsEnabled() const\r
-{\r
-       return info.bEnabled;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Enables/disables the image.\r
- */\r
-void CxImage::Enable(bool enable)\r
-{\r
-       info.bEnabled=enable;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * This function must be used after a Decode() / Load() call.\r
- * Use the sequence SetFrame(-1); Load(...); GetNumFrames();\r
- * to get the number of images without loading the first image.\r
- * \return the number of images in the file.\r
- */\r
-long CxImage::GetNumFrames() const\r
-{\r
-       return info.nNumFrames;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return the current selected image (zero-based index).\r
- */\r
-long CxImage::GetFrame() const\r
-{\r
-       return info.nFrame;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the image number that the next Decode() / Load() call will load\r
- */\r
-void CxImage::SetFrame(long nFrame){\r
-       info.nFrame=nFrame;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the method for drawing the frame related to others\r
- * \sa GetDisposalMethod\r
- */\r
-void CxImage::SetDisposalMethod(BYTE dm)\r
-{      info.dispmeth=dm; }\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Gets the method for drawing the frame related to others\r
- * Values :    0 -   No disposal specified. The decoder is\r
- *                   not required to take any action.\r
- *             1 -   Do not dispose. The graphic is to be left\r
- *                   in place.\r
- *             2 -   Restore to background color. The area used by the\r
- *                   graphic must be restored to the background color.\r
- *             3 -   Restore to previous. The decoder is required to\r
- *                   restore the area overwritten by the graphic with\r
- *                   what was there prior to rendering the graphic.\r
- *             4-7 -    To be defined.\r
- */\r
-BYTE CxImage::GetDisposalMethod() const\r
-{      return info.dispmeth; }\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::GetRetreiveAllFrames() const\r
-{      return info.bGetAllFrames; }\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetRetreiveAllFrames(bool flag)\r
-{      info.bGetAllFrames = flag; }\r
-////////////////////////////////////////////////////////////////////////////////\r
-CxImage * CxImage::GetFrame(long nFrame) const\r
-{\r
-       if ( ppFrames == NULL) return NULL;\r
-       if ( info.nNumFrames == 0) return NULL;\r
-       if ( nFrame >= info.nNumFrames ) return NULL;\r
-       if ( nFrame < 0) nFrame = info.nNumFrames - 1;\r
-       return ppFrames[nFrame];\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-short CxImage::ntohs(const short word)\r
-{\r
-       if (info.bLittleEndianHost) return word;\r
-       return ( (word & 0xff) << 8 ) | ( (word >> 8) & 0xff );\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImage::ntohl(const long dword)\r
-{\r
-       if (info.bLittleEndianHost) return dword;\r
-       return  ((dword & 0xff) << 24 ) | ((dword & 0xff00) << 8 ) |\r
-                       ((dword >> 8) & 0xff00) | ((dword >> 24) & 0xff);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::bihtoh(BITMAPINFOHEADER* bih)\r
-{\r
-       bih->biSize = ntohl(bih->biSize);\r
-       bih->biWidth = ntohl(bih->biWidth);\r
-       bih->biHeight = ntohl(bih->biHeight);\r
-       bih->biPlanes = ntohs(bih->biPlanes);\r
-       bih->biBitCount = ntohs(bih->biBitCount);\r
-       bih->biCompression = ntohl(bih->biCompression);\r
-       bih->biSizeImage = ntohl(bih->biSizeImage);\r
-       bih->biXPelsPerMeter = ntohl(bih->biXPelsPerMeter);\r
-       bih->biYPelsPerMeter = ntohl(bih->biYPelsPerMeter);\r
-       bih->biClrUsed = ntohl(bih->biClrUsed);\r
-       bih->biClrImportant = ntohl(bih->biClrImportant);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns the last reported error.\r
- */\r
-const char* CxImage::GetLastError()\r
-{\r
-       return info.szLastError;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-DWORD CxImage::DumpSize()\r
-{\r
-       DWORD n;\r
-       n = sizeof(BITMAPINFOHEADER) + sizeof(CXIMAGEINFO) + GetSize();\r
-\r
-       if (pAlpha){\r
-               n += 1 + head.biWidth * head.biHeight;\r
-       } else n++;\r
-\r
-       if (pSelection){\r
-               n += 1 + head.biWidth * head.biHeight;\r
-       } else n++;\r
-\r
-       if (ppLayers){\r
-               for (long m=0; m<GetNumLayers(); m++){\r
-                       if (GetLayer(m)){\r
-                               n += 1 + GetLayer(m)->DumpSize();\r
-                       }\r
-               }\r
-       } else n++;\r
-\r
-       if (ppFrames){\r
-               for (long m=0; m<GetNumFrames(); m++){\r
-                       if (GetFrame(m)){\r
-                               n += 1 + GetFrame(m)->DumpSize();\r
-                       }\r
-               }\r
-       } else n++;\r
-\r
-       return n;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-DWORD CxImage::Dump(BYTE * dst)\r
-{\r
-       if (!dst) return 0;\r
-\r
-       memcpy(dst,&head,sizeof(BITMAPINFOHEADER));\r
-       dst += sizeof(BITMAPINFOHEADER);\r
-\r
-       memcpy(dst,&info,sizeof(CXIMAGEINFO));\r
-       dst += sizeof(CXIMAGEINFO);\r
-\r
-       memcpy(dst,pDib,GetSize());\r
-       dst += GetSize();\r
-\r
-       if (pAlpha){\r
-               memset(dst++, 1, 1);\r
-               memcpy(dst,pAlpha,head.biWidth * head.biHeight);\r
-               dst += head.biWidth * head.biHeight;\r
-       } else {\r
-               memset(dst++, 0, 1);\r
-       }\r
-\r
-       if (pSelection){\r
-               memset(dst++, 1, 1);\r
-               memcpy(dst,pSelection,head.biWidth * head.biHeight);\r
-               dst += head.biWidth * head.biHeight;\r
-       } else {\r
-               memset(dst++, 0, 1);\r
-       }\r
-\r
-       if (ppLayers){\r
-               memset(dst++, 1, 1);\r
-               for (long m=0; m<GetNumLayers(); m++){\r
-                       if (GetLayer(m)){\r
-                               dst += GetLayer(m)->Dump(dst);\r
-                       }\r
-               }\r
-       } else {\r
-               memset(dst++, 0, 1);\r
-       }\r
-\r
-       if (ppFrames){\r
-               memset(dst++, 1, 1);\r
-               for (long m=0; m<GetNumFrames(); m++){\r
-                       if (GetFrame(m)){\r
-                               dst += GetFrame(m)->Dump(dst);\r
-                       }\r
-               }\r
-       } else {\r
-               memset(dst++, 0, 1);\r
-       }\r
-\r
-       return DumpSize();\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-DWORD CxImage::UnDump(const BYTE * src)\r
-{\r
-       if (!src)\r
-               return 0;\r
-       if (!Destroy())\r
-               return 0;\r
-       if (!DestroyFrames())\r
-               return 0;\r
-\r
-       DWORD n = 0;\r
-\r
-       memcpy(&head,src,sizeof(BITMAPINFOHEADER));\r
-       n += sizeof(BITMAPINFOHEADER);\r
-\r
-       memcpy(&info,&src[n],sizeof(CXIMAGEINFO));\r
-       n += sizeof(CXIMAGEINFO);\r
-\r
-       if (!Create(head.biWidth, head.biHeight, head.biBitCount, info.dwType))\r
-               return 0;\r
-\r
-       memcpy(pDib,&src[n],GetSize());\r
-       n += GetSize();\r
-\r
-       if (src[n++]){\r
-               if (AlphaCreate()){\r
-                       memcpy(pAlpha, &src[n], head.biWidth * head.biHeight);\r
-               }\r
-               n += head.biWidth * head.biHeight;\r
-       }\r
-\r
-       if (src[n++]){\r
-               RECT box = info.rSelectionBox;\r
-               if (SelectionCreate()){\r
-                       info.rSelectionBox = box;\r
-                       memcpy(pSelection, &src[n], head.biWidth * head.biHeight);\r
-               }\r
-               n += head.biWidth * head.biHeight;\r
-       }\r
-\r
-       if (src[n++]){\r
-               ppLayers = new CxImage*[info.nNumLayers];\r
-               for (long m=0; m<GetNumLayers(); m++){\r
-                       ppLayers[m] = new CxImage();\r
-                       n += ppLayers[m]->UnDump(&src[n]);\r
-               }\r
-       }\r
-\r
-       if (src[n++]){\r
-               ppFrames = new CxImage*[info.nNumFrames];\r
-               for (long m=0; m<GetNumFrames(); m++){\r
-                       ppFrames[m] = new CxImage();\r
-                       n += ppFrames[m]->UnDump(&src[n]);\r
-               }\r
-       }\r
-\r
-       return n;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \return A.BBCCCDDDD\r
- *  - A = main version\r
- *  - BB = main revision\r
- *  - CCC = minor revision (letter)\r
- *  - DDDD = experimental revision\r
- */\r
-const float CxImage::GetVersionNumber()\r
-{\r
-       return 6.000000015f;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-const TCHAR* CxImage::GetVersion()\r
-{\r
-       static const TCHAR CxImageVersion[] = _T("CxImage 6.0.0");\r
-       return (CxImageVersion);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
+// ximainfo.cpp : main attributes
+/* 03/10/2004 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximage.h"
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return the color used for transparency, and/or for background color
+ */
+RGBQUAD        CxImage::GetTransColor()
+{
+       if (head.biBitCount<24 && info.nBkgndIndex>=0) return GetPaletteColor((BYTE)info.nBkgndIndex);
+       return info.nBkgndColor;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the index used for transparency. Returns -1 for no transparancy.
+ */
+long 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(long idx)
+{
+       if (idx<(long)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
+ */
+BYTE CxImage::GetColorType()
+{
+       BYTE b = (BYTE)((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.
+ */
+long CxImage::GetXDPI() const
+{
+       return info.xDPI;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return Resolution for TIFF, JPEG, PNG and BMP formats.
+ */
+long CxImage::GetYDPI() const
+{
+       return info.yDPI;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Set resolution for TIFF, JPEG, PNG and BMP formats.
+ */
+void CxImage::SetXDPI(long dpi)
+{
+       if (dpi<=0) dpi = CXIMAGE_DEFAULT_DPI;
+       info.xDPI = dpi;
+       head.biXPelsPerMeter = (long) 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(long dpi)
+{
+       if (dpi<=0) dpi = CXIMAGE_DEFAULT_DPI;
+       info.yDPI = dpi;
+       head.biYPelsPerMeter = (long) floor(dpi * 10000.0 / 254.0 + 0.5);
+       if (pDib) ((BITMAPINFOHEADER*)pDib)->biYPelsPerMeter = head.biYPelsPerMeter;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetFlags
+ */
+DWORD 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(DWORD flags, bool bLockReservedFlags)
+{
+       if (bLockReservedFlags) info.dwFlags = flags & 0x0000ffff;
+       else info.dwFlags = flags;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetCodecOption
+ */
+DWORD CxImage::GetCodecOption(DWORD imagetype)
+{
+       imagetype = GetTypeIndexFromId(imagetype);
+       if (imagetype==0){
+               imagetype = GetTypeIndexFromId(GetType());
+       }
+       return info.dwCodecOpt[imagetype];
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Encode option for GIF, TIF and JPG.
+ * - 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, ...)
+ * - 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(DWORD opt, DWORD 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;
+}
+////////////////////////////////////////////////////////////////////////////////
+DWORD CxImage::GetHeight() const
+{
+       return head.biHeight;
+}
+////////////////////////////////////////////////////////////////////////////////
+DWORD CxImage::GetWidth() const
+{
+       return head.biWidth;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return DWORD aligned width of the image.
+ */
+DWORD CxImage::GetEffWidth() const
+{
+       return info.dwEffWidth;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return 2, 16, 256; 0 for RGB images.
+ */
+DWORD CxImage::GetNumColors() const
+{
+       return head.biClrUsed;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return: 1, 4, 8, 24.
+ */
+WORD CxImage::GetBpp() const
+{
+       return head.biBitCount;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return original image format
+ * \sa ENUM_CXIMAGE_FORMATS.
+ */
+DWORD CxImage::GetType() const
+{
+       return info.dwType;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * change image format identifier
+ * \sa ENUM_CXIMAGE_FORMATS.
+ */
+bool CxImage::SetType(DWORD 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
+               info.dwType = type;
+               return true;
+       }
+       info.dwType = CXIMAGE_FORMAT_UNKNOWN;
+       return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+DWORD CxImage::GetNumTypes()
+{
+       return CMAX_IMAGE_FORMATS-1;
+}
+////////////////////////////////////////////////////////////////////////////////
+DWORD 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_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;
+}
+////////////////////////////////////////////////////////////////////////////////
+DWORD CxImage::GetTypeIdFromIndex(const DWORD index)
+{
+       DWORD 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
+
+       return CXIMAGE_FORMAT_UNKNOWN;
+}
+////////////////////////////////////////////////////////////////////////////////
+DWORD CxImage::GetTypeIndexFromId(const DWORD id)
+{
+       DWORD 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
+
+       return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return current frame delay in milliseconds. Only for GIF and MNG formats.
+ */
+DWORD CxImage::GetFrameDelay() const
+{
+       return info.dwFrameDelay;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets current frame delay. Only for GIF format.
+ * \param d = delay in milliseconds
+ */
+void CxImage::SetFrameDelay(DWORD d)
+{
+       info.dwFrameDelay=d;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::GetOffset(long *x,long *y)
+{
+       *x=info.xOffset;
+       *y=info.yOffset;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetOffset(long x,long y)
+{
+       info.xOffset=x;
+       info.yOffset=y;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa SetJpegQuality, GetJpegQualityF
+ * \author [DP]; changes [Stefan Schürmans]
+ */
+BYTE CxImage::GetJpegQuality() const
+{
+       return (BYTE)(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(BYTE 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
+ */
+BYTE CxImage::GetJpegScale() const
+{
+       return info.nJpegScale;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * scaling down during JPEG decoding valid numbers are 1, 2, 4, 8
+ * \author [ignacio]
+ */
+void CxImage::SetJpegScale(BYTE q){
+       info.nJpegScale = q;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Used to monitor the slow loops.
+ * \return value is from 0 to 100.
+ * \sa SetProgress
+ */
+long CxImage::GetProgress() const
+{
+       return info.nProgress;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return the escape code.
+ * \sa SetEscape
+ */
+long 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(long 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(long 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.
+ */
+long CxImage::GetNumFrames() const
+{
+       return info.nNumFrames;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return the current selected image (zero-based index).
+ */
+long CxImage::GetFrame() const
+{
+       return info.nFrame;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the image number that the next Decode() / Load() call will load
+ */
+void CxImage::SetFrame(long nFrame){
+       info.nFrame=nFrame;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Sets the method for drawing the frame related to others
+ * \sa GetDisposalMethod
+ */
+void CxImage::SetDisposalMethod(BYTE 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.
+ */
+BYTE CxImage::GetDisposalMethod() const
+{      return info.dispmeth; }
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::GetRetreiveAllFrames() const
+{      return info.bGetAllFrames; }
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetRetreiveAllFrames(bool flag)
+{      info.bGetAllFrames = flag; }
+////////////////////////////////////////////////////////////////////////////////
+CxImage * CxImage::GetFrame(long 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];
+}
+////////////////////////////////////////////////////////////////////////////////
+short CxImage::ntohs(const short word)
+{
+       if (info.bLittleEndianHost) return word;
+       return ( (word & 0xff) << 8 ) | ( (word >> 8) & 0xff );
+}
+////////////////////////////////////////////////////////////////////////////////
+long CxImage::ntohl(const long 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 = ntohl(bih->biSize);
+       bih->biWidth = ntohl(bih->biWidth);
+       bih->biHeight = ntohl(bih->biHeight);
+       bih->biPlanes = ntohs(bih->biPlanes);
+       bih->biBitCount = ntohs(bih->biBitCount);
+       bih->biCompression = ntohl(bih->biCompression);
+       bih->biSizeImage = ntohl(bih->biSizeImage);
+       bih->biXPelsPerMeter = ntohl(bih->biXPelsPerMeter);
+       bih->biYPelsPerMeter = ntohl(bih->biYPelsPerMeter);
+       bih->biClrUsed = ntohl(bih->biClrUsed);
+       bih->biClrImportant = ntohl(bih->biClrImportant);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the last reported error.
+ */
+const char* CxImage::GetLastError()
+{
+       return info.szLastError;
+}
+////////////////////////////////////////////////////////////////////////////////
+DWORD CxImage::DumpSize()
+{
+       DWORD n;
+       n = sizeof(BITMAPINFOHEADER) + sizeof(CXIMAGEINFO) + GetSize();
+
+       if (pAlpha){
+               n += 1 + head.biWidth * head.biHeight;
+       } else n++;
+
+       if (pSelection){
+               n += 1 + head.biWidth * head.biHeight;
+       } else n++;
+
+       if (ppLayers){
+               for (long m=0; m<GetNumLayers(); m++){
+                       if (GetLayer(m)){
+                               n += 1 + GetLayer(m)->DumpSize();
+                       }
+               }
+       } else n++;
+
+       if (ppFrames){
+               for (long m=0; m<GetNumFrames(); m++){
+                       if (GetFrame(m)){
+                               n += 1 + GetFrame(m)->DumpSize();
+                       }
+               }
+       } else n++;
+
+       return n;
+}
+////////////////////////////////////////////////////////////////////////////////
+DWORD CxImage::Dump(BYTE * 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 (pAlpha){
+               memset(dst++, 1, 1);
+               memcpy(dst,pAlpha,head.biWidth * head.biHeight);
+               dst += head.biWidth * head.biHeight;
+       } else {
+               memset(dst++, 0, 1);
+       }
+
+       if (pSelection){
+               memset(dst++, 1, 1);
+               memcpy(dst,pSelection,head.biWidth * head.biHeight);
+               dst += head.biWidth * head.biHeight;
+       } else {
+               memset(dst++, 0, 1);
+       }
+
+       if (ppLayers){
+               memset(dst++, 1, 1);
+               for (long m=0; m<GetNumLayers(); m++){
+                       if (GetLayer(m)){
+                               dst += GetLayer(m)->Dump(dst);
+                       }
+               }
+       } else {
+               memset(dst++, 0, 1);
+       }
+
+       if (ppFrames){
+               memset(dst++, 1, 1);
+               for (long m=0; m<GetNumFrames(); m++){
+                       if (GetFrame(m)){
+                               dst += GetFrame(m)->Dump(dst);
+                       }
+               }
+       } else {
+               memset(dst++, 0, 1);
+       }
+
+       return DumpSize();
+}
+////////////////////////////////////////////////////////////////////////////////
+DWORD CxImage::UnDump(const BYTE * src)
+{
+       if (!src)
+               return 0;
+       if (!Destroy())
+               return 0;
+       if (!DestroyFrames())
+               return 0;
+
+       DWORD 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 (src[n++]){
+               if (AlphaCreate()){
+                       memcpy(pAlpha, &src[n], head.biWidth * head.biHeight);
+               }
+               n += head.biWidth * head.biHeight;
+       }
+
+       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;
+       }
+
+       if (src[n++]){
+               ppLayers = new CxImage*[info.nNumLayers];
+               for (long m=0; m<GetNumLayers(); m++){
+                       ppLayers[m] = new CxImage();
+                       n += ppLayers[m]->UnDump(&src[n]);
+               }
+       }
+
+       if (src[n++]){
+               ppFrames = new CxImage*[info.nNumFrames];
+               for (long 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 6.000000015f;
+}
+////////////////////////////////////////////////////////////////////////////////
+const TCHAR* CxImage::GetVersion()
+{
+       static const TCHAR CxImageVersion[] = _T("CxImage 6.0.0");
+       return (CxImageVersion);
+}
+////////////////////////////////////////////////////////////////////////////////
index 89e1bacc9e9a2740ea7b65071c4a5cb657db2717..989d76cf71e3d1014cb7b95d2e46706a2995c0dd 100644 (file)
-// xImaInt.cpp : interpolation functions\r
-/* 02/2004 - Branko Brevensek \r
- * CxImage version 6.0.0 02/Feb/2008 - Davide Pizzolato - www.xdp.it\r
- */\r
-\r
-#include "ximage.h"\r
-#include "ximath.h"\r
-\r
-#if CXIMAGE_SUPPORT_INTERPOLATION\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Recalculates coordinates according to specified overflow method.\r
- * If pixel (x,y) lies within image, nothing changes.\r
- *\r
- *  \param x, y - coordinates of pixel\r
- *  \param ofMethod - overflow method\r
- * \r
- *  \return x, y - new coordinates (pixel (x,y) now lies inside image)\r
- *\r
- *  \author ***bd*** 2.2004\r
- */\r
-void CxImage::OverflowCoordinates(long &x, long &y, OverflowMethod const ofMethod)\r
-{\r
-  if (IsInside(x,y)) return;  //if pixel is within bounds, no change\r
-  switch (ofMethod) {\r
-    case OM_REPEAT:\r
-      //clip coordinates\r
-      x=max(x,0); x=min(x, head.biWidth-1);\r
-      y=max(y,0); y=min(y, head.biHeight-1);\r
-      break;\r
-    case OM_WRAP:\r
-      //wrap coordinates\r
-      x = x % head.biWidth;\r
-      y = y % head.biHeight;\r
-      if (x<0) x = head.biWidth + x;\r
-      if (y<0) y = head.biHeight + y;\r
-      break;\r
-    case OM_MIRROR:\r
-      //mirror pixels near border\r
-      if (x<0) x=((-x) % head.biWidth);\r
-      else if (x>=head.biWidth) x=head.biWidth-(x % head.biWidth + 1);\r
-      if (y<0) y=((-y) % head.biHeight);\r
-      else if (y>=head.biHeight) y=head.biHeight-(y % head.biHeight + 1);\r
-      break;\r
-    default:\r
-      return;\r
-  }//switch\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * See OverflowCoordinates for integer version \r
- * \author ***bd*** 2.2004\r
- */\r
-void CxImage::OverflowCoordinates(float &x, float &y, OverflowMethod const ofMethod)\r
-{\r
-  if (x>=0 && x<head.biWidth && y>=0 && y<head.biHeight) return;  //if pixel is within bounds, no change\r
-  switch (ofMethod) {\r
-    case OM_REPEAT:\r
-      //clip coordinates\r
-      x=max(x,0); x=min(x, head.biWidth-1);\r
-      y=max(y,0); y=min(y, head.biHeight-1);\r
-      break;\r
-    case OM_WRAP:\r
-      //wrap coordinates\r
-      x = (float)fmod(x, (float) head.biWidth);\r
-      y = (float)fmod(y, (float) head.biHeight);\r
-      if (x<0) x = head.biWidth + x;\r
-      if (y<0) y = head.biHeight + y;\r
-      break;\r
-    case OM_MIRROR:\r
-      //mirror pixels near border\r
-      if (x<0) x=(float)fmod(-x, (float) head.biWidth);\r
-      else if (x>=head.biWidth) x=head.biWidth-((float)fmod(x, (float) head.biWidth) + 1);\r
-      if (y<0) y=(float)fmod(-y, (float) head.biHeight);\r
-      else if (y>=head.biHeight) y=head.biHeight-((float)fmod(y, (float) head.biHeight) + 1);\r
-      break;\r
-    default:\r
-      return;\r
-  }//switch\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Method return pixel color. Different methods are implemented for out of bounds pixels.\r
- * If an image has alpha channel, alpha value is returned in .RGBReserved.\r
- *\r
- *  \param x,y : pixel coordinates\r
- *  \param ofMethod : out-of-bounds method:\r
- *    - OF_WRAP - wrap over to pixels on other side of the image\r
- *    - OF_REPEAT - repeat last pixel on the edge\r
- *    - OF_COLOR - return input value of color\r
- *    - OF_BACKGROUND - return background color (if not set, return input color)\r
- *    - OF_TRANSPARENT - return transparent pixel\r
- *\r
- *  \param rplColor : input color (returned for out-of-bound coordinates in OF_COLOR mode and if other mode is not applicable)\r
- *\r
- * \return color : color of pixel\r
- * \author ***bd*** 2.2004\r
- */\r
-RGBQUAD CxImage::GetPixelColorWithOverflow(long x, long y, OverflowMethod const ofMethod, RGBQUAD* const rplColor)\r
-{\r
-  RGBQUAD color;          //color to return\r
-  if ((!IsInside(x,y)) || pDib==NULL) {     //is pixel within bouns?:\r
-    //pixel is out of bounds or no DIB\r
-    if (rplColor!=NULL)\r
-      color=*rplColor;\r
-    else {\r
-      color.rgbRed=color.rgbGreen=color.rgbBlue=255; color.rgbReserved=0; //default replacement colour: white transparent\r
-    }//if\r
-    if (pDib==NULL) return color;\r
-    //pixel is out of bounds:\r
-    switch (ofMethod) {\r
-      case OM_TRANSPARENT:\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-        if (AlphaIsValid()) {\r
-          //alpha transparency is supported and image has alpha layer\r
-          color.rgbReserved=0;\r
-        } else {\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-          //no alpha transparency\r
-          if (GetTransIndex()>=0) {\r
-            color=GetTransColor();    //single color transparency enabled (return transparent color)\r
-          }//if\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-        }//if\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-        return color;\r
-      case OM_BACKGROUND:\r
-                 //return background color (if it exists, otherwise input value)\r
-                 if (info.nBkgndIndex >= 0) {\r
-                         if (head.biBitCount<24) color = GetPaletteColor((BYTE)info.nBkgndIndex);\r
-                         else color = info.nBkgndColor;\r
-                 }//if\r
-                 return color;\r
-      case OM_REPEAT:\r
-      case OM_WRAP:\r
-      case OM_MIRROR:\r
-        OverflowCoordinates(x,y,ofMethod);\r
-        break;\r
-      default:\r
-        //simply return replacement color (OM_COLOR and others)\r
-        return color;\r
-    }//switch\r
-  }//if\r
-  //just return specified pixel (it's within bounds)\r
-  return BlindGetPixelColor(x,y);\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * This method reconstructs image according to chosen interpolation method and then returns pixel (x,y).\r
- * (x,y) can lie between actual image pixels. If (x,y) lies outside of image, method returns value\r
- * according to overflow method.\r
- * This method is very useful for geometrical image transformations, where destination pixel\r
- * can often assume color value lying between source pixels.\r
- *\r
- *  \param (x,y) - coordinates of pixel to return\r
- *           GPCI method recreates "analogue" image back from digital data, so x and y\r
- *           are float values and color value of point (1.1,1) will generally not be same\r
- *           as (1,1). Center of first pixel is at (0,0) and center of pixel right to it is (1,0).\r
- *           (0.5,0) is half way between these two pixels.\r
- *  \param inMethod - interpolation (reconstruction) method (kernel) to use:\r
- *    - IM_NEAREST_NEIGHBOUR - returns colour of nearest lying pixel (causes stairy look of \r
- *                            processed images)\r
- *    - IM_BILINEAR - interpolates colour from four neighbouring pixels (softens image a bit)\r
- *    - IM_BICUBIC - interpolates from 16 neighbouring pixels (can produce "halo" artifacts)\r
- *    - IM_BICUBIC2 - interpolates from 16 neighbouring pixels (perhaps a bit less halo artifacts \r
-                     than IM_BICUBIC)\r
- *    - IM_BSPLINE - interpolates from 16 neighbouring pixels (softens image, washes colours)\r
- *                  (As far as I know, image should be prefiltered for this method to give \r
- *                   good results... some other time :) )\r
- *                  This method uses bicubic interpolation kernel from CXImage 5.99a and older\r
- *                  versions.\r
- *    - IM_LANCZOS - interpolates from 12*12 pixels (slow, ringing artifacts)\r
- *\r
- *  \param ofMethod - overflow method (see comments at GetPixelColorWithOverflow)\r
- *  \param rplColor - pointer to color used for out of borders pixels in OM_COLOR mode\r
- *              (and other modes if colour can't calculated in a specified way)\r
- *\r
- *  \return interpolated color value (including interpolated alpha value, if image has alpha layer)\r
- * \r
- *  \author ***bd*** 2.2004\r
- */\r
-RGBQUAD CxImage::GetPixelColorInterpolated(\r
-  float x,float y, \r
-  InterpolationMethod const inMethod, \r
-  OverflowMethod const ofMethod, \r
-  RGBQUAD* const rplColor)\r
-{\r
-  //calculate nearest pixel\r
-  int xi=(int)(x); if (x<0) xi--;   //these replace (incredibly slow) floor (Visual c++ 2003, AMD Athlon)\r
-  int yi=(int)(y); if (y<0) yi--;\r
-  RGBQUAD color;                    //calculated colour\r
-\r
-  switch (inMethod) {\r
-    case IM_NEAREST_NEIGHBOUR:\r
-      return GetPixelColorWithOverflow((long)(x+0.5f), (long)(y+0.5f), ofMethod, rplColor);\r
-    default: {\r
-      //IM_BILINEAR: bilinear interpolation\r
-      if (xi<-1 || xi>=head.biWidth || yi<-1 || yi>=head.biHeight) {  //all 4 points are outside bounds?:\r
-        switch (ofMethod) {\r
-          case OM_COLOR: case OM_TRANSPARENT: case OM_BACKGROUND:\r
-            //we don't need to interpolate anything with all points outside in this case\r
-            return GetPixelColorWithOverflow(-999, -999, ofMethod, rplColor);\r
-          default:\r
-            //recalculate coordinates and use faster method later on\r
-            OverflowCoordinates(x,y,ofMethod);\r
-            xi=(int)(x); if (x<0) xi--;   //x and/or y have changed ... recalculate xi and yi\r
-            yi=(int)(y); if (y<0) yi--;\r
-        }//switch\r
-      }//if\r
-      //get four neighbouring pixels\r
-      if ((xi+1)<head.biWidth && xi>=0 && (yi+1)<head.biHeight && yi>=0 && head.biClrUsed==0) {\r
-        //all pixels are inside RGB24 image... optimize reading (and use fixed point arithmetic)\r
-        WORD wt1=(WORD)((x-xi)*256.0f), wt2=(WORD)((y-yi)*256.0f);\r
-        WORD wd=wt1*wt2>>8;\r
-        WORD wb=wt1-wd;\r
-        WORD wc=wt2-wd;\r
-        WORD wa=256-wt1-wc;\r
-        WORD wrr,wgg,wbb;\r
-        BYTE *pxptr=(BYTE*)info.pImage+yi*info.dwEffWidth+xi*3;\r
-        wbb=wa*(*pxptr++); wgg=wa*(*pxptr++); wrr=wa*(*pxptr++);\r
-        wbb+=wb*(*pxptr++); wgg+=wb*(*pxptr++); wrr+=wb*(*pxptr);\r
-        pxptr+=(info.dwEffWidth-5); //move to next row\r
-        wbb+=wc*(*pxptr++); wgg+=wc*(*pxptr++); wrr+=wc*(*pxptr++); \r
-        wbb+=wd*(*pxptr++); wgg+=wd*(*pxptr++); wrr+=wd*(*pxptr); \r
-        color.rgbRed=(BYTE) (wrr>>8); color.rgbGreen=(BYTE) (wgg>>8); color.rgbBlue=(BYTE) (wbb>>8);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-        if (pAlpha) {\r
-          WORD waa;\r
-          //image has alpha layer... we have to do the same for alpha data\r
-          pxptr=AlphaGetPointer(xi,yi);                           //pointer to first byte\r
-          waa=wa*(*pxptr++); waa+=wb*(*pxptr);   //first two pixels\r
-          pxptr+=(head.biWidth-1);                                //move to next row\r
-          waa+=wc*(*pxptr++); waa+=wd*(*pxptr);   //and second row pixels\r
-          color.rgbReserved=(BYTE) (waa>>8);\r
-        } else\r
-#endif\r
-               { //Alpha not supported or no alpha at all\r
-                       color.rgbReserved = 0;\r
-               }\r
-        return color;\r
-      } else {\r
-        //default (slower) way to get pixels (not RGB24 or some pixels out of borders)\r
-        float t1=x-xi, t2=y-yi;\r
-        float d=t1*t2;\r
-        float b=t1-d;\r
-        float c=t2-d;\r
-        float a=1-t1-c;\r
-        RGBQUAD rgb11,rgb21,rgb12,rgb22;\r
-        rgb11=GetPixelColorWithOverflow(xi, yi, ofMethod, rplColor);\r
-        rgb21=GetPixelColorWithOverflow(xi+1, yi, ofMethod, rplColor);\r
-        rgb12=GetPixelColorWithOverflow(xi, yi+1, ofMethod, rplColor);\r
-        rgb22=GetPixelColorWithOverflow(xi+1, yi+1, ofMethod, rplColor);\r
-        //calculate linear interpolation\r
-        color.rgbRed=(BYTE) (a*rgb11.rgbRed+b*rgb21.rgbRed+c*rgb12.rgbRed+d*rgb22.rgbRed);\r
-        color.rgbGreen=(BYTE) (a*rgb11.rgbGreen+b*rgb21.rgbGreen+c*rgb12.rgbGreen+d*rgb22.rgbGreen);\r
-        color.rgbBlue=(BYTE) (a*rgb11.rgbBlue+b*rgb21.rgbBlue+c*rgb12.rgbBlue+d*rgb22.rgbBlue);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-        if (AlphaIsValid())\r
-                       color.rgbReserved=(BYTE) (a*rgb11.rgbReserved+b*rgb21.rgbReserved+c*rgb12.rgbReserved+d*rgb22.rgbReserved);\r
-               else\r
-#endif\r
-               { //Alpha not supported or no alpha at all\r
-                       color.rgbReserved = 0;\r
-               }\r
-        return color;\r
-      }//if\r
-    }//default\r
-    case IM_BICUBIC: \r
-    case IM_BICUBIC2:\r
-    case IM_BSPLINE:\r
-       case IM_BOX:\r
-       case IM_HERMITE:\r
-       case IM_HAMMING:\r
-       case IM_SINC:\r
-       case IM_BLACKMAN:\r
-       case IM_BESSEL:\r
-       case IM_GAUSSIAN:\r
-       case IM_QUADRATIC:\r
-       case IM_MITCHELL:\r
-       case IM_CATROM:\r
-       case IM_HANNING:\r
-       case IM_POWER:\r
-      //bicubic interpolation(s)\r
-      if (((xi+2)<0) || ((xi-1)>=head.biWidth) || ((yi+2)<0) || ((yi-1)>=head.biHeight)) { //all points are outside bounds?:\r
-        switch (ofMethod) {\r
-          case OM_COLOR: case OM_TRANSPARENT: case OM_BACKGROUND:\r
-            //we don't need to interpolate anything with all points outside in this case\r
-            return GetPixelColorWithOverflow(-999, -999, ofMethod, rplColor);\r
-            break;\r
-          default:\r
-            //recalculate coordinates and use faster method later on\r
-            OverflowCoordinates(x,y,ofMethod);\r
-            xi=(int)(x); if (x<0) xi--;   //x and/or y have changed ... recalculate xi and yi\r
-            yi=(int)(y); if (y<0) yi--;\r
-        }//switch\r
-      }//if\r
-\r
-      //some variables needed from here on\r
-      int xii,yii;                      //x any y integer indexes for loops\r
-      float kernel, kernelyc;           //kernel cache\r
-      float kernelx[12], kernely[4];    //precalculated kernel values\r
-      float rr,gg,bb,aa;                //accumulated color values\r
-      //calculate multiplication factors for all pixels\r
-         int i;\r
-      switch (inMethod) {\r
-        case IM_BICUBIC:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelCubic((float)(xi+i-1-x));\r
-            kernely[i]=KernelCubic((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_BICUBIC2:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelGeneralizedCubic((float)(xi+i-1-x), -0.5);\r
-            kernely[i]=KernelGeneralizedCubic((float)(yi+i-1-y), -0.5);\r
-          }//for i\r
-          break;\r
-        case IM_BSPLINE:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelBSpline((float)(xi+i-1-x));\r
-            kernely[i]=KernelBSpline((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_BOX:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelBox((float)(xi+i-1-x));\r
-            kernely[i]=KernelBox((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_HERMITE:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelHermite((float)(xi+i-1-x));\r
-            kernely[i]=KernelHermite((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_HAMMING:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelHamming((float)(xi+i-1-x));\r
-            kernely[i]=KernelHamming((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_SINC:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelSinc((float)(xi+i-1-x));\r
-            kernely[i]=KernelSinc((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_BLACKMAN:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelBlackman((float)(xi+i-1-x));\r
-            kernely[i]=KernelBlackman((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_BESSEL:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelBessel((float)(xi+i-1-x));\r
-            kernely[i]=KernelBessel((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_GAUSSIAN:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelGaussian((float)(xi+i-1-x));\r
-            kernely[i]=KernelGaussian((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_QUADRATIC:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelQuadratic((float)(xi+i-1-x));\r
-            kernely[i]=KernelQuadratic((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_MITCHELL:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelMitchell((float)(xi+i-1-x));\r
-            kernely[i]=KernelMitchell((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_CATROM:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelCatrom((float)(xi+i-1-x));\r
-            kernely[i]=KernelCatrom((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_HANNING:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelHanning((float)(xi+i-1-x));\r
-            kernely[i]=KernelHanning((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-        case IM_POWER:\r
-          for (i=0; i<4; i++) {\r
-            kernelx[i]=KernelPower((float)(xi+i-1-x));\r
-            kernely[i]=KernelPower((float)(yi+i-1-y));\r
-          }//for i\r
-          break;\r
-      }//switch\r
-      rr=gg=bb=aa=0;\r
-      if (((xi+2)<head.biWidth) && xi>=1 && ((yi+2)<head.biHeight) && (yi>=1) && !IsIndexed()) {\r
-        //optimized interpolation (faster pixel reads) for RGB24 images with all pixels inside bounds\r
-        BYTE *pxptr, *pxptra;\r
-        for (yii=yi-1; yii<yi+3; yii++) {\r
-          pxptr=(BYTE *)BlindGetPixelPointer(xi-1, yii);    //calculate pointer to first byte in row\r
-          kernelyc=kernely[yii-(yi-1)];\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-          if (AlphaIsValid()) {\r
-            //alpha is supported and valid (optimized bicubic int. for image with alpha)\r
-            pxptra=AlphaGetPointer(xi-1, yii);\r
-            kernel=kernelyc*kernelx[0];\r
-            bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++); aa+=kernel*(*pxptra++);\r
-            kernel=kernelyc*kernelx[1];\r
-            bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++); aa+=kernel*(*pxptra++);\r
-            kernel=kernelyc*kernelx[2];\r
-            bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++); aa+=kernel*(*pxptra++);\r
-            kernel=kernelyc*kernelx[3];\r
-            bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr); aa+=kernel*(*pxptra);\r
-          } else\r
-#endif\r
-          //alpha not supported or valid (optimized bicubic int. for no alpha channel)\r
-          {\r
-            kernel=kernelyc*kernelx[0];\r
-            bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++);\r
-            kernel=kernelyc*kernelx[1];\r
-            bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++);\r
-            kernel=kernelyc*kernelx[2];\r
-            bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++);\r
-            kernel=kernelyc*kernelx[3];\r
-            bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr);\r
-          }\r
-        }//yii\r
-      } else {\r
-        //slower more flexible interpolation for border pixels and paletted images\r
-        RGBQUAD rgbs;\r
-        for (yii=yi-1; yii<yi+3; yii++) {\r
-          kernelyc=kernely[yii-(yi-1)];\r
-          for (xii=xi-1; xii<xi+3; xii++) {\r
-            kernel=kernelyc*kernelx[xii-(xi-1)];\r
-            rgbs=GetPixelColorWithOverflow(xii, yii, ofMethod, rplColor);\r
-            rr+=kernel*rgbs.rgbRed;\r
-            gg+=kernel*rgbs.rgbGreen;\r
-            bb+=kernel*rgbs.rgbBlue;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-            aa+=kernel*rgbs.rgbReserved;\r
-#endif\r
-          }//xii\r
-        }//yii\r
-      }//if\r
-      //for all colors, clip to 0..255 and assign to RGBQUAD\r
-      if (rr>255) rr=255; if (rr<0) rr=0; color.rgbRed=(BYTE) rr;\r
-      if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(BYTE) gg;\r
-      if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(BYTE) bb;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-      if (AlphaIsValid()) {\r
-        if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(BYTE) aa;\r
-      } else\r
-#endif\r
-               { //Alpha not supported or no alpha at all\r
-                       color.rgbReserved = 0;\r
-               }\r
-      return color;\r
-    case IM_LANCZOS:\r
-      //lanczos window (16*16) sinc interpolation\r
-      if (((xi+6)<0) || ((xi-5)>=head.biWidth) || ((yi+6)<0) || ((yi-5)>=head.biHeight)) {\r
-        //all points are outside bounds\r
-        switch (ofMethod) {\r
-          case OM_COLOR: case OM_TRANSPARENT: case OM_BACKGROUND:\r
-            //we don't need to interpolate anything with all points outside in this case\r
-            return GetPixelColorWithOverflow(-999, -999, ofMethod, rplColor);\r
-            break;\r
-          default:\r
-            //recalculate coordinates and use faster method later on\r
-            OverflowCoordinates(x,y,ofMethod);\r
-            xi=(int)(x); if (x<0) xi--;   //x and/or y have changed ... recalculate xi and yi\r
-            yi=(int)(y); if (y<0) yi--;\r
-        }//switch\r
-      }//if\r
-\r
-      for (xii=xi-5; xii<xi+7; xii++) kernelx[xii-(xi-5)]=KernelLanczosSinc((float)(xii-x), 6.0f);\r
-      rr=gg=bb=aa=0;\r
-\r
-      if (((xi+6)<head.biWidth) && ((xi-5)>=0) && ((yi+6)<head.biHeight) && ((yi-5)>=0) && !IsIndexed()) {\r
-        //optimized interpolation (faster pixel reads) for RGB24 images with all pixels inside bounds\r
-        BYTE *pxptr, *pxptra;\r
-        for (yii=yi-5; yii<yi+7; yii++) {\r
-          pxptr=(BYTE *)BlindGetPixelPointer(xi-5, yii);    //calculate pointer to first byte in row\r
-          kernelyc=KernelLanczosSinc((float)(yii-y),6.0f);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-          if (AlphaIsValid()) {\r
-            //alpha is supported and valid\r
-            pxptra=AlphaGetPointer(xi-1, yii);\r
-            for (xii=0; xii<12; xii++) {\r
-              kernel=kernelyc*kernelx[xii];\r
-              bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++); aa+=kernel*(*pxptra++);\r
-            }//for xii\r
-          } else\r
-#endif\r
-          //alpha not supported or valid\r
-          {\r
-            for (xii=0; xii<12; xii++) {\r
-              kernel=kernelyc*kernelx[xii];\r
-              bb+=kernel*(*pxptr++); gg+=kernel*(*pxptr++); rr+=kernel*(*pxptr++);\r
-            }//for xii\r
-          }\r
-        }//yii\r
-      } else {\r
-        //slower more flexible interpolation for border pixels and paletted images\r
-        RGBQUAD rgbs;\r
-        for (yii=yi-5; yii<yi+7; yii++) {\r
-          kernelyc=KernelLanczosSinc((float)(yii-y),6.0f);\r
-          for (xii=xi-5; xii<xi+7; xii++) {\r
-            kernel=kernelyc*kernelx[xii-(xi-5)];\r
-            rgbs=GetPixelColorWithOverflow(xii, yii, ofMethod, rplColor);\r
-            rr+=kernel*rgbs.rgbRed;\r
-            gg+=kernel*rgbs.rgbGreen;\r
-            bb+=kernel*rgbs.rgbBlue;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-            aa+=kernel*rgbs.rgbReserved;\r
-#endif\r
-          }//xii\r
-        }//yii\r
-      }//if\r
-      //for all colors, clip to 0..255 and assign to RGBQUAD\r
-      if (rr>255) rr=255; if (rr<0) rr=0; color.rgbRed=(BYTE) rr;\r
-      if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(BYTE) gg;\r
-      if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(BYTE) bb;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-      if (AlphaIsValid()) {\r
-        if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(BYTE) aa;   \r
-      } else\r
-#endif\r
-               { //Alpha not supported or no alpha at all\r
-                       color.rgbReserved = 0;\r
-               }\r
-      return color;\r
-  }//switch\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Helper function for GetAreaColorInterpolated.\r
- * Adds 'surf' portion of image pixel with color 'color' to (rr,gg,bb,aa).\r
- */\r
-void CxImage::AddAveragingCont(RGBQUAD const &color, float const surf, float &rr, float &gg, float &bb, float &aa)\r
-{\r
-  rr+=color.rgbRed*surf;\r
-  gg+=color.rgbGreen*surf;\r
-  bb+=color.rgbBlue*surf;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-  aa+=color.rgbReserved*surf;\r
-#endif\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * This method is similar to GetPixelColorInterpolated, but this method also properly handles \r
- * subsampling.\r
- * If you need to sample original image with interval of more than 1 pixel (as when shrinking an image), \r
- * you should use this method instead of GetPixelColorInterpolated or aliasing will occur.\r
- * When area width and height are both less than pixel, this method gets pixel color by interpolating\r
- * color of frame center with selected (inMethod) interpolation by calling GetPixelColorInterpolated. \r
- * If width and height are more than 1, method calculates color by averaging color of pixels within area.\r
- * Interpolation method is not used in this case. Pixel color is interpolated by averaging instead.\r
- * If only one of both is more than 1, method uses combination of interpolation and averaging.\r
- * Chosen interpolation method is used, but since it is averaged later on, there is little difference\r
- * between IM_BILINEAR (perhaps best for this case) and better methods. IM_NEAREST_NEIGHBOUR again\r
- * leads to aliasing artifacts.\r
- * This method is a bit slower than GetPixelColorInterpolated and when aliasing is not a problem, you should\r
- * simply use the later. \r
- *\r
- * \param  xc, yc - center of (rectangular) area\r
- * \param  w, h - width and height of area\r
- * \param  inMethod - interpolation method that is used, when interpolation is used (see above)\r
- * \param  ofMethod - overflow method used when retrieving individual pixel colors\r
- * \param  rplColor - replacement colour to use, in OM_COLOR\r
- *\r
- * \author ***bd*** 2.2004\r
- */\r
-RGBQUAD CxImage::GetAreaColorInterpolated(\r
-  float const xc, float const yc, float const w, float const h, \r
-  InterpolationMethod const inMethod, \r
-  OverflowMethod const ofMethod, \r
-  RGBQUAD* const rplColor)\r
-{\r
-       RGBQUAD color;      //calculated colour\r
-       \r
-       if (h<=1 && w<=1) {\r
-               //both width and height are less than one... we will use interpolation of center point\r
-               return GetPixelColorInterpolated(xc, yc, inMethod, ofMethod, rplColor);\r
-       } else {\r
-               //area is wider and/or taller than one pixel:\r
-               CxRect2 area(xc-w/2.0f, yc-h/2.0f, xc+w/2.0f, yc+h/2.0f);   //area\r
-               int xi1=(int)(area.botLeft.x+0.49999999f);                //low x\r
-               int yi1=(int)(area.botLeft.y+0.49999999f);                //low y\r
-               \r
-               \r
-               int xi2=(int)(area.topRight.x+0.5f);                      //top x\r
-               int yi2=(int)(area.topRight.y+0.5f);                      //top y (for loops)\r
-               \r
-               float rr,gg,bb,aa;                                        //red, green, blue and alpha components\r
-               rr=gg=bb=aa=0;\r
-               int x,y;                                                  //loop counters\r
-               float s=0;                                                //surface of all pixels\r
-               float cps;                                                //surface of current crosssection\r
-               if (h>1 && w>1) {\r
-                       //width and height of area are greater than one pixel, so we can employ "ordinary" averaging\r
-                       CxRect2 intBL, intTR;     //bottom left and top right intersection\r
-                       intBL=area.CrossSection(CxRect2(((float)xi1)-0.5f, ((float)yi1)-0.5f, ((float)xi1)+0.5f, ((float)yi1)+0.5f));\r
-                       intTR=area.CrossSection(CxRect2(((float)xi2)-0.5f, ((float)yi2)-0.5f, ((float)xi2)+0.5f, ((float)yi2)+0.5f));\r
-                       float wBL, wTR, hBL, hTR;\r
-                       wBL=intBL.Width();            //width of bottom left pixel-area intersection\r
-                       hBL=intBL.Height();           //height of bottom left...\r
-                       wTR=intTR.Width();            //width of top right...\r
-                       hTR=intTR.Height();           //height of top right...\r
-                       \r
-                       AddAveragingCont(GetPixelColorWithOverflow(xi1,yi1,ofMethod,rplColor), wBL*hBL, rr, gg, bb, aa);    //bottom left pixel\r
-                       AddAveragingCont(GetPixelColorWithOverflow(xi2,yi1,ofMethod,rplColor), wTR*hBL, rr, gg, bb, aa);    //bottom right pixel\r
-                       AddAveragingCont(GetPixelColorWithOverflow(xi1,yi2,ofMethod,rplColor), wBL*hTR, rr, gg, bb, aa);    //top left pixel\r
-                       AddAveragingCont(GetPixelColorWithOverflow(xi2,yi2,ofMethod,rplColor), wTR*hTR, rr, gg, bb, aa);    //top right pixel\r
-                       //bottom and top row\r
-                       for (x=xi1+1; x<xi2; x++) {\r
-                               AddAveragingCont(GetPixelColorWithOverflow(x,yi1,ofMethod,rplColor), hBL, rr, gg, bb, aa);    //bottom row\r
-                               AddAveragingCont(GetPixelColorWithOverflow(x,yi2,ofMethod,rplColor), hTR, rr, gg, bb, aa);    //top row\r
-                       }\r
-                       //leftmost and rightmost column\r
-                       for (y=yi1+1; y<yi2; y++) {\r
-                               AddAveragingCont(GetPixelColorWithOverflow(xi1,y,ofMethod,rplColor), wBL, rr, gg, bb, aa);    //left column\r
-                               AddAveragingCont(GetPixelColorWithOverflow(xi2,y,ofMethod,rplColor), wTR, rr, gg, bb, aa);    //right column\r
-                       }\r
-                       for (y=yi1+1; y<yi2; y++) {\r
-                               for (x=xi1+1; x<xi2; x++) { \r
-                                       color=GetPixelColorWithOverflow(x,y,ofMethod,rplColor);\r
-                                       rr+=color.rgbRed;\r
-                                       gg+=color.rgbGreen;\r
-                                       bb+=color.rgbBlue;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       aa+=color.rgbReserved;\r
-#endif\r
-                               }//for x\r
-                       }//for y\r
-               } else {\r
-                       //width or height greater than one:\r
-                       CxRect2 intersect;                                          //intersection with current pixel\r
-                       CxPoint2 center;\r
-                       for (y=yi1; y<=yi2; y++) {\r
-                               for (x=xi1; x<=xi2; x++) {\r
-                                       intersect=area.CrossSection(CxRect2(((float)x)-0.5f, ((float)y)-0.5f, ((float)x)+0.5f, ((float)y)+0.5f));\r
-                                       center=intersect.Center();\r
-                                       color=GetPixelColorInterpolated(center.x, center.y, inMethod, ofMethod, rplColor);\r
-                                       cps=intersect.Surface();\r
-                                       rr+=color.rgbRed*cps;\r
-                                       gg+=color.rgbGreen*cps;\r
-                                       bb+=color.rgbBlue*cps;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       aa+=color.rgbReserved*cps;\r
-#endif\r
-                               }//for x\r
-                       }//for y      \r
-               }//if\r
-               \r
-               s=area.Surface();\r
-               rr/=s; gg/=s; bb/=s; aa/=s;\r
-               if (rr>255) rr=255; if (rr<0) rr=0; color.rgbRed=(BYTE) rr;\r
-               if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(BYTE) gg;\r
-               if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(BYTE) bb;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               if (AlphaIsValid()) {\r
-                       if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(BYTE) aa;\r
-               }//if\r
-#endif\r
-       }//if\r
-       return color;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelBSpline(const float x)\r
-{\r
-       if (x>2.0f) return 0.0f;\r
-       // thanks to Kristian Kratzenstein\r
-       float a, b, c, d;\r
-       float xm1 = x - 1.0f; // Was calculatet anyway cause the "if((x-1.0f) < 0)"\r
-       float xp1 = x + 1.0f;\r
-       float xp2 = x + 2.0f;\r
-\r
-       if ((xp2) <= 0.0f) a = 0.0f; else a = xp2*xp2*xp2; // Only float, not float -> double -> float\r
-       if ((xp1) <= 0.0f) b = 0.0f; else b = xp1*xp1*xp1;\r
-       if (x <= 0) c = 0.0f; else c = x*x*x;  \r
-       if ((xm1) <= 0.0f) d = 0.0f; else d = xm1*xm1*xm1;\r
-\r
-       return (0.16666666666666666667f * (a - (4.0f * b) + (6.0f * c) - (4.0f * d)));\r
-\r
-       /* equivalent <Vladimír Kloucek>\r
-       if (x < -2.0)\r
-               return(0.0f);\r
-       if (x < -1.0)\r
-               return((2.0f+x)*(2.0f+x)*(2.0f+x)*0.16666666666666666667f);\r
-       if (x < 0.0)\r
-               return((4.0f+x*x*(-6.0f-3.0f*x))*0.16666666666666666667f);\r
-       if (x < 1.0)\r
-               return((4.0f+x*x*(-6.0f+3.0f*x))*0.16666666666666666667f);\r
-       if (x < 2.0)\r
-               return((2.0f-x)*(2.0f-x)*(2.0f-x)*0.16666666666666666667f);\r
-       return(0.0f);\r
-       */\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Bilinear interpolation kernel:\r
-  \verbatim\r
-          /\r
-         | 1-t           , if  0 <= t <= 1\r
-  h(t) = | t+1           , if -1 <= t <  0\r
-         | 0             , otherwise\r
-          \\r
-  \endverbatim\r
- * ***bd*** 2.2004\r
- */\r
-float CxImage::KernelLinear(const float t)\r
-{\r
-//  if (0<=t && t<=1) return 1-t;\r
-//  if (-1<=t && t<0) return 1+t;\r
-//  return 0;\r
-       \r
-       //<Vladimír Kloucek>\r
-       if (t < -1.0f)\r
-               return 0.0f;\r
-       if (t < 0.0f)\r
-               return 1.0f+t;\r
-       if (t < 1.0f)\r
-               return 1.0f-t;\r
-       return 0.0f;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Bicubic interpolation kernel (a=-1):\r
-  \verbatim\r
-          /\r
-         | 1-2|t|**2+|t|**3          , if |t| < 1\r
-  h(t) = | 4-8|t|+5|t|**2-|t|**3     , if 1<=|t|<2\r
-         | 0                         , otherwise\r
-          \\r
-  \endverbatim\r
- * ***bd*** 2.2004\r
- */\r
-float CxImage::KernelCubic(const float t)\r
-{\r
-  float abs_t = (float)fabs(t);\r
-  float abs_t_sq = abs_t * abs_t;\r
-  if (abs_t<1) return 1-2*abs_t_sq+abs_t_sq*abs_t;\r
-  if (abs_t<2) return 4 - 8*abs_t +5*abs_t_sq - abs_t_sq*abs_t;\r
-  return 0;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Bicubic kernel (for a=-1 it is the same as BicubicKernel):\r
-  \verbatim\r
-          /\r
-         | (a+2)|t|**3 - (a+3)|t|**2 + 1     , |t| <= 1\r
-  h(t) = | a|t|**3 - 5a|t|**2 + 8a|t| - 4a   , 1 < |t| <= 2\r
-         | 0                                 , otherwise\r
-          \\r
-  \endverbatim\r
- * Often used values for a are -1 and -1/2.\r
- */\r
-float CxImage::KernelGeneralizedCubic(const float t, const float a)\r
-{\r
-  float abs_t = (float)fabs(t);\r
-  float abs_t_sq = abs_t * abs_t;\r
-  if (abs_t<1) return (a+2)*abs_t_sq*abs_t - (a+3)*abs_t_sq + 1;\r
-  if (abs_t<2) return a*abs_t_sq*abs_t - 5*a*abs_t_sq + 8*a*abs_t - 4*a;\r
-  return 0;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Lanczos windowed sinc interpolation kernel with radius r.\r
-  \verbatim\r
-          /\r
-  h(t) = | sinc(t)*sinc(t/r)       , if |t|<r\r
-         | 0                       , otherwise\r
-          \\r
-  \endverbatim\r
- * ***bd*** 2.2004\r
- */\r
-float CxImage::KernelLanczosSinc(const float t, const float r)\r
-{\r
-  if (fabs(t) > r) return 0;\r
-  if (t==0) return 1;\r
-  float pit=PI*t;\r
-  float pitd=pit/r;\r
-  return (float)((sin(pit)/pit) * (sin(pitd)/pitd));\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelBox(const float x)\r
-{\r
-       if (x < -0.5f)\r
-               return 0.0f;\r
-       if (x < 0.5f)\r
-               return 1.0f;\r
-       return 0.0f;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelHermite(const float x)\r
-{\r
-       if (x < -1.0f)\r
-               return 0.0f;\r
-       if (x < 0.0f)\r
-               return (-2.0f*x-3.0f)*x*x+1.0f;\r
-       if (x < 1.0f)\r
-               return (2.0f*x-3.0f)*x*x+1.0f;\r
-       return 0.0f;\r
-//     if (fabs(x)>1) return 0.0f;\r
-//     return(0.5f+0.5f*(float)cos(PI*x));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelHanning(const float x)\r
-{\r
-       if (fabs(x)>1) return 0.0f;\r
-       return (0.5f+0.5f*(float)cos(PI*x))*((float)sin(PI*x)/(PI*x));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelHamming(const float x)\r
-{\r
-       if (x < -1.0f)\r
-               return 0.0f;\r
-       if (x < 0.0f)\r
-               return 0.92f*(-2.0f*x-3.0f)*x*x+1.0f;\r
-       if (x < 1.0f)\r
-               return 0.92f*(2.0f*x-3.0f)*x*x+1.0f;\r
-       return 0.0f;\r
-//     if (fabs(x)>1) return 0.0f;\r
-//     return(0.54f+0.46f*(float)cos(PI*x));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelSinc(const float x)\r
-{\r
-       if (x == 0.0)\r
-               return(1.0);\r
-       return((float)sin(PI*x)/(PI*x));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelBlackman(const float x)\r
-{\r
-       //if (fabs(x)>1) return 0.0f;\r
-       return (0.42f+0.5f*(float)cos(PI*x)+0.08f*(float)cos(2.0f*PI*x));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelBessel_J1(const float x)\r
-{\r
-       double p, q;\r
-       \r
-       register long i;\r
-       \r
-       static const double\r
-       Pone[] =\r
-       {\r
-               0.581199354001606143928050809e+21,\r
-               -0.6672106568924916298020941484e+20,\r
-               0.2316433580634002297931815435e+19,\r
-               -0.3588817569910106050743641413e+17,\r
-               0.2908795263834775409737601689e+15,\r
-               -0.1322983480332126453125473247e+13,\r
-               0.3413234182301700539091292655e+10,\r
-               -0.4695753530642995859767162166e+7,\r
-               0.270112271089232341485679099e+4\r
-       },\r
-       Qone[] =\r
-       {\r
-               0.11623987080032122878585294e+22,\r
-               0.1185770712190320999837113348e+20,\r
-               0.6092061398917521746105196863e+17,\r
-               0.2081661221307607351240184229e+15,\r
-               0.5243710262167649715406728642e+12,\r
-               0.1013863514358673989967045588e+10,\r
-               0.1501793594998585505921097578e+7,\r
-               0.1606931573481487801970916749e+4,\r
-               0.1e+1\r
-       };\r
-               \r
-       p = Pone[8];\r
-       q = Qone[8];\r
-       for (i=7; i >= 0; i--)\r
-       {\r
-               p = p*x*x+Pone[i];\r
-               q = q*x*x+Qone[i];\r
-       }\r
-       return (float)(p/q);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelBessel_P1(const float x)\r
-{\r
-       double p, q;\r
-       \r
-       register long i;\r
-       \r
-       static const double\r
-       Pone[] =\r
-       {\r
-               0.352246649133679798341724373e+5,\r
-               0.62758845247161281269005675e+5,\r
-               0.313539631109159574238669888e+5,\r
-               0.49854832060594338434500455e+4,\r
-               0.2111529182853962382105718e+3,\r
-               0.12571716929145341558495e+1\r
-       },\r
-       Qone[] =\r
-       {\r
-               0.352246649133679798068390431e+5,\r
-               0.626943469593560511888833731e+5,\r
-               0.312404063819041039923015703e+5,\r
-               0.4930396490181088979386097e+4,\r
-               0.2030775189134759322293574e+3,\r
-               0.1e+1\r
-       };\r
-               \r
-       p = Pone[5];\r
-       q = Qone[5];\r
-       for (i=4; i >= 0; i--)\r
-       {\r
-               p = p*(8.0/x)*(8.0/x)+Pone[i];\r
-               q = q*(8.0/x)*(8.0/x)+Qone[i];\r
-       }\r
-       return (float)(p/q);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelBessel_Q1(const float x)\r
-{\r
-       double p, q;\r
-       \r
-       register long i;\r
-       \r
-       static const double\r
-       Pone[] =\r
-       {\r
-               0.3511751914303552822533318e+3,\r
-               0.7210391804904475039280863e+3,\r
-               0.4259873011654442389886993e+3,\r
-               0.831898957673850827325226e+2,\r
-               0.45681716295512267064405e+1,\r
-               0.3532840052740123642735e-1\r
-       },\r
-       Qone[] =\r
-       {\r
-               0.74917374171809127714519505e+4,\r
-               0.154141773392650970499848051e+5,\r
-               0.91522317015169922705904727e+4,\r
-               0.18111867005523513506724158e+4,\r
-               0.1038187585462133728776636e+3,\r
-               0.1e+1\r
-       };\r
-               \r
-       p = Pone[5];\r
-       q = Qone[5];\r
-       for (i=4; i >= 0; i--)\r
-       {\r
-               p = p*(8.0/x)*(8.0/x)+Pone[i];\r
-               q = q*(8.0/x)*(8.0/x)+Qone[i];\r
-       }\r
-       return (float)(p/q);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelBessel_Order1(float x)\r
-{\r
-       float p, q;\r
-       \r
-       if (x == 0.0)\r
-               return (0.0f);\r
-       p = x;\r
-       if (x < 0.0)\r
-               x=(-x);\r
-       if (x < 8.0)\r
-               return(p*KernelBessel_J1(x));\r
-       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)*\r
-               (-1.0f/sqrt(2.0f)*(sin(x)+cos(x))));\r
-       if (p < 0.0f)\r
-               q = (-q);\r
-       return (q);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelBessel(const float x)\r
-{\r
-       if (x == 0.0f)\r
-               return(PI/4.0f);\r
-       return(KernelBessel_Order1(PI*x)/(2.0f*x));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelGaussian(const float x)\r
-{\r
-       return (float)(exp(-2.0f*x*x)*0.79788456080287f/*sqrt(2.0f/PI)*/);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelQuadratic(const float x)\r
-{\r
-       if (x < -1.5f)\r
-               return(0.0f);\r
-       if (x < -0.5f)\r
-               return(0.5f*(x+1.5f)*(x+1.5f));\r
-       if (x < 0.5f)\r
-               return(0.75f-x*x);\r
-       if (x < 1.5f)\r
-               return(0.5f*(x-1.5f)*(x-1.5f));\r
-       return(0.0f);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelMitchell(const float x)\r
-{\r
-#define KM_B (1.0f/3.0f)\r
-#define KM_C (1.0f/3.0f)\r
-#define KM_P0 ((  6.0f - 2.0f * KM_B ) / 6.0f)\r
-#define KM_P2 ((-18.0f + 12.0f * KM_B + 6.0f * KM_C) / 6.0f)\r
-#define KM_P3 (( 12.0f - 9.0f  * KM_B - 6.0f * KM_C) / 6.0f)\r
-#define KM_Q0 ((  8.0f * KM_B + 24.0f * KM_C) / 6.0f)\r
-#define KM_Q1 ((-12.0f * KM_B - 48.0f * KM_C) / 6.0f)\r
-#define KM_Q2 ((  6.0f * KM_B + 30.0f * KM_C) / 6.0f)\r
-#define KM_Q3 (( -1.0f * KM_B -  6.0f * KM_C) / 6.0f)\r
-       \r
-       if (x < -2.0)\r
-               return(0.0f);\r
-       if (x < -1.0)\r
-               return(KM_Q0-x*(KM_Q1-x*(KM_Q2-x*KM_Q3)));\r
-       if (x < 0.0f)\r
-               return(KM_P0+x*x*(KM_P2-x*KM_P3));\r
-       if (x < 1.0f)\r
-               return(KM_P0+x*x*(KM_P2+x*KM_P3));\r
-       if (x < 2.0f)\r
-               return(KM_Q0+x*(KM_Q1+x*(KM_Q2+x*KM_Q3)));\r
-       return(0.0f);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelCatrom(const float x)\r
-{\r
-       if (x < -2.0)\r
-               return(0.0f);\r
-       if (x < -1.0)\r
-               return(0.5f*(4.0f+x*(8.0f+x*(5.0f+x))));\r
-       if (x < 0.0)\r
-               return(0.5f*(2.0f+x*x*(-5.0f-3.0f*x)));\r
-       if (x < 1.0)\r
-               return(0.5f*(2.0f+x*x*(-5.0f+3.0f*x)));\r
-       if (x < 2.0)\r
-               return(0.5f*(4.0f+x*(-8.0f+x*(5.0f-x))));\r
-       return(0.0f);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-float CxImage::KernelPower(const float x, const float a)\r
-{\r
-       if (fabs(x)>1) return 0.0f;\r
-       return (1.0f - (float)fabs(pow(x,a)));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-#endif\r
+// xImaInt.cpp : interpolation functions
+/* 02/2004 - Branko Brevensek 
+ * CxImage version 6.0.0 02/Feb/2008 - 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(long &x, long &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(long x, long 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((BYTE)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
+  int xi=(int)(x); if (x<0) xi--;   //these replace (incredibly slow) floor (Visual c++ 2003, AMD Athlon)
+  int yi=(int)(y); if (y<0) yi--;
+  RGBQUAD color;                    //calculated colour
+
+  switch (inMethod) {
+    case IM_NEAREST_NEIGHBOUR:
+      return GetPixelColorWithOverflow((long)(x+0.5f), (long)(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=(int)(x); if (x<0) xi--;   //x and/or y have changed ... recalculate xi and yi
+            yi=(int)(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)
+        WORD wt1=(WORD)((x-xi)*256.0f), wt2=(WORD)((y-yi)*256.0f);
+        WORD wd=wt1*wt2>>8;
+        WORD wb=wt1-wd;
+        WORD wc=wt2-wd;
+        WORD wa=256-wt1-wc;
+        WORD wrr,wgg,wbb;
+        BYTE *pxptr=(BYTE*)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=(BYTE) (wrr>>8); color.rgbGreen=(BYTE) (wgg>>8); color.rgbBlue=(BYTE) (wbb>>8);
+#if CXIMAGE_SUPPORT_ALPHA
+        if (pAlpha) {
+          WORD 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=(BYTE) (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=(BYTE) (a*rgb11.rgbRed+b*rgb21.rgbRed+c*rgb12.rgbRed+d*rgb22.rgbRed);
+        color.rgbGreen=(BYTE) (a*rgb11.rgbGreen+b*rgb21.rgbGreen+c*rgb12.rgbGreen+d*rgb22.rgbGreen);
+        color.rgbBlue=(BYTE) (a*rgb11.rgbBlue+b*rgb21.rgbBlue+c*rgb12.rgbBlue+d*rgb22.rgbBlue);
+#if CXIMAGE_SUPPORT_ALPHA
+        if (AlphaIsValid())
+                       color.rgbReserved=(BYTE) (a*rgb11.rgbReserved+b*rgb21.rgbReserved+c*rgb12.rgbReserved+d*rgb22.rgbReserved);
+               else
+#endif
+               { //Alpha not supported or no alpha at all
+                       color.rgbReserved = 0;
+               }
+        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=(int)(x); if (x<0) xi--;   //x and/or y have changed ... recalculate xi and yi
+            yi=(int)(y); if (y<0) yi--;
+        }//switch
+      }//if
+
+      //some variables needed from here on
+      int 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
+         int 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;
+      }//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
+        BYTE *pxptr, *pxptra;
+        for (yii=yi-1; yii<yi+3; yii++) {
+          pxptr=(BYTE *)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 int. for image with alpha)
+            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 int. 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=(BYTE) rr;
+      if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(BYTE) gg;
+      if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(BYTE) bb;
+#if CXIMAGE_SUPPORT_ALPHA
+      if (AlphaIsValid()) {
+        if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(BYTE) aa;
+      } else
+#endif
+               { //Alpha not supported or no alpha at all
+                       color.rgbReserved = 0;
+               }
+      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=(int)(x); if (x<0) xi--;   //x and/or y have changed ... recalculate xi and yi
+            yi=(int)(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
+        BYTE *pxptr, *pxptra;
+        for (yii=yi-5; yii<yi+7; yii++) {
+          pxptr=(BYTE *)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
+            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=(BYTE) rr;
+      if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(BYTE) gg;
+      if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(BYTE) bb;
+#if CXIMAGE_SUPPORT_ALPHA
+      if (AlphaIsValid()) {
+        if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(BYTE) aa;   
+      } else
+#endif
+               { //Alpha not supported or no alpha at all
+                       color.rgbReserved = 0;
+               }
+      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
+               int xi1=(int)(area.botLeft.x+0.49999999f);                //low x
+               int yi1=(int)(area.botLeft.y+0.49999999f);                //low y
+               
+               
+               int xi2=(int)(area.topRight.x+0.5f);                      //top x
+               int yi2=(int)(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;
+               int 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=(BYTE) rr;
+               if (gg>255) gg=255; if (gg<0) gg=0; color.rgbGreen=(BYTE) gg;
+               if (bb>255) bb=255; if (bb<0) bb=0; color.rgbBlue=(BYTE) bb;
+#if CXIMAGE_SUPPORT_ALPHA
+               if (AlphaIsValid()) {
+                       if (aa>255) aa=255; if (aa<0) aa=0; color.rgbReserved=(BYTE) aa;
+               }//if
+#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 long 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 long 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 long 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
index 3e5bff9ba831f129eee8cd30c2778e7309a549d5..9788919b8f6d63ee9247fd7f1686ea250e1ca82e 100644 (file)
-/*\r
- * File:       ImaIter.h\r
- * Purpose:    Declaration of the Platform Independent Image Base Class\r
- * Author:     Alejandro Aguilar Sierra\r
- * Created:    1995\r
- * Copyright:  (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>\r
- *\r
- * 07/08/2001 Davide Pizzolato - www.xdp.it\r
- * - removed slow loops\r
- * - added safe checks\r
- *\r
- * Permission is given by the author to freely redistribute and include\r
- * this code in any program as long as this credit is given where due.\r
- *\r
- * COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY\r
- * OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES\r
- * THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE\r
- * OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED\r
- * CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT\r
- * THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY\r
- * SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL\r
- * PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER\r
- * THIS DISCLAIMER.\r
- *\r
- * Use at your own risk!\r
- * ==========================================================\r
- */\r
-\r
-#if !defined(__ImaIter_h)\r
-#define __ImaIter_h\r
-\r
-#include "ximage.h"\r
-#include "ximadef.h"\r
-\r
-class CImageIterator\r
-{\r
-friend class CxImage;\r
-protected:\r
-       int Itx, Ity;           // Counters\r
-       int Stepx, Stepy;\r
-       BYTE* IterImage;        //  Image pointer\r
-       CxImage *ima;\r
-public:\r
-       // Constructors\r
-       CImageIterator ( void );\r
-       CImageIterator ( CxImage *image );\r
-       operator CxImage* ();\r
-\r
-       // Iterators\r
-       BOOL ItOK ();\r
-       void Reset ();\r
-       void Upset ();\r
-       void SetRow(BYTE *buf, int n);\r
-       void GetRow(BYTE *buf, int n);\r
-       BYTE GetByte( ) { return IterImage[Itx]; }\r
-       void SetByte(BYTE b) { IterImage[Itx] = b; }\r
-       BYTE* GetRow(void);\r
-       BYTE* GetRow(int n);\r
-       BOOL NextRow();\r
-       BOOL PrevRow();\r
-       BOOL NextByte();\r
-       BOOL PrevByte();\r
-\r
-       void SetSteps(int x, int y=0) {  Stepx = x; Stepy = y; }\r
-       void GetSteps(int *x, int *y) {  *x = Stepx; *y = Stepy; }\r
-       BOOL NextStep();\r
-       BOOL PrevStep();\r
-\r
-       void SetY(int y);       /* AD - for interlace */\r
-       int  GetY() {return Ity;}\r
-       BOOL GetCol(BYTE* pCol, DWORD x);\r
-       BOOL SetCol(BYTE* pCol, DWORD x);\r
-};\r
-\r
-/////////////////////////////////////////////////////////////////////\r
-inline\r
-CImageIterator::CImageIterator(void)\r
-{\r
-       ima = 0;\r
-       IterImage = 0;\r
-       Itx = Ity = 0;\r
-       Stepx = Stepy = 0;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline\r
-CImageIterator::CImageIterator(CxImage *imageImpl): ima(imageImpl)\r
-{\r
-       if (ima) IterImage = ima->GetBits();\r
-       Itx = Ity = 0;\r
-       Stepx = Stepy = 0;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline\r
-CImageIterator::operator CxImage* ()\r
-{\r
-       return ima;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BOOL CImageIterator::ItOK ()\r
-{\r
-       if (ima) return ima->IsInside(Itx, Ity);\r
-       else     return FALSE;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline void CImageIterator::Reset()\r
-{\r
-       if (ima) IterImage = ima->GetBits();\r
-       else     IterImage=0;\r
-       Itx = Ity = 0;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline void CImageIterator::Upset()\r
-{\r
-       Itx = 0;\r
-       Ity = ima->GetHeight()-1;\r
-       IterImage = ima->GetBits() + ima->GetEffWidth()*(ima->GetHeight()-1);\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BOOL CImageIterator::NextRow()\r
-{\r
-       if (++Ity >= (int)ima->GetHeight()) return 0;\r
-       IterImage += ima->GetEffWidth();\r
-       return 1;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BOOL CImageIterator::PrevRow()\r
-{\r
-       if (--Ity < 0) return 0;\r
-       IterImage -= ima->GetEffWidth();\r
-       return 1;\r
-}\r
-/* AD - for interlace */\r
-inline void CImageIterator::SetY(int y)\r
-{\r
-       if ((y < 0) || (y > (int)ima->GetHeight())) return;\r
-       Ity = y;\r
-       IterImage = ima->GetBits() + ima->GetEffWidth()*y;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline void CImageIterator::SetRow(BYTE *buf, int n)\r
-{\r
-       if (n<0) n = (int)ima->GetEffWidth();\r
-       else n = min(n,(int)ima->GetEffWidth());\r
-\r
-       if ((IterImage!=NULL)&&(buf!=NULL)&&(n>0)) memcpy(IterImage,buf,n);\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline void CImageIterator::GetRow(BYTE *buf, int n)\r
-{\r
-       if ((IterImage!=NULL)&&(buf!=NULL)&&(n>0))\r
-               memcpy(buf,IterImage,min(n,(int)ima->GetEffWidth()));\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BYTE* CImageIterator::GetRow()\r
-{\r
-       return IterImage;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BYTE* CImageIterator::GetRow(int n)\r
-{\r
-       SetY(n);\r
-       return IterImage;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BOOL CImageIterator::NextByte()\r
-{\r
-       if (++Itx < (int)ima->GetEffWidth()) return 1;\r
-       else\r
-               if (++Ity < (int)ima->GetHeight()){\r
-                       IterImage += ima->GetEffWidth();\r
-                       Itx = 0;\r
-                       return 1;\r
-               } else\r
-                       return 0;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BOOL CImageIterator::PrevByte()\r
-{\r
-  if (--Itx >= 0) return 1;\r
-  else\r
-         if (--Ity >= 0){\r
-                 IterImage -= ima->GetEffWidth();\r
-                 Itx = 0;\r
-                 return 1;\r
-         } else\r
-                 return 0;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BOOL CImageIterator::NextStep()\r
-{\r
-       Itx += Stepx;\r
-       if (Itx < (int)ima->GetEffWidth()) return 1;\r
-       else {\r
-               Ity += Stepy;\r
-               if (Ity < (int)ima->GetHeight()){\r
-                       IterImage += ima->GetEffWidth();\r
-                       Itx = 0;\r
-                       return 1;\r
-               } else\r
-                       return 0;\r
-       }\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BOOL CImageIterator::PrevStep()\r
-{\r
-       Itx -= Stepx;\r
-       if (Itx >= 0) return 1;\r
-       else {       \r
-               Ity -= Stepy;\r
-               if (Ity >= 0 && Ity < (int)ima->GetHeight()) {\r
-                       IterImage -= ima->GetEffWidth();\r
-                       Itx = 0;\r
-                       return 1;\r
-               } else\r
-                       return 0;\r
-       }\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BOOL CImageIterator::GetCol(BYTE* pCol, DWORD x)\r
-{\r
-       if ((pCol==0)||(ima->GetBpp()<8)||(x>=ima->GetWidth()))\r
-               return 0;\r
-       DWORD h = ima->GetHeight();\r
-       //DWORD line = ima->GetEffWidth();\r
-       BYTE bytes = (BYTE)(ima->GetBpp()>>3);\r
-       BYTE* pSrc;\r
-       for (DWORD y=0;y<h;y++){\r
-               pSrc = ima->GetBits(y) + x*bytes;\r
-               for (BYTE w=0;w<bytes;w++){\r
-                       *pCol++=*pSrc++;\r
-               }\r
-       }\r
-       return 1;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-inline BOOL CImageIterator::SetCol(BYTE* pCol, DWORD x)\r
-{\r
-       if ((pCol==0)||(ima->GetBpp()<8)||(x>=ima->GetWidth()))\r
-               return 0;\r
-       DWORD h = ima->GetHeight();\r
-       //DWORD line = ima->GetEffWidth();\r
-       BYTE bytes = (BYTE)(ima->GetBpp()>>3);\r
-       BYTE* pSrc;\r
-       for (DWORD y=0;y<h;y++){\r
-               pSrc = ima->GetBits(y) + x*bytes;\r
-               for (BYTE w=0;w<bytes;w++){\r
-                       *pSrc++=*pCol++;\r
-               }\r
-       }\r
-       return 1;\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-#endif\r
+/*
+ * 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 long 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:
+       int Itx, Ity;           // Counters
+       int Stepx, Stepy;
+       BYTE* IterImage;        //  Image pointer
+       CxImage *ima;
+public:
+       // Constructors
+       CImageIterator ( void );
+       CImageIterator ( CxImage *image );
+       operator CxImage* ();
+
+       // Iterators
+       BOOL ItOK ();
+       void Reset ();
+       void Upset ();
+       void SetRow(BYTE *buf, int n);
+       void GetRow(BYTE *buf, int n);
+       BYTE GetByte( ) { return IterImage[Itx]; }
+       void SetByte(BYTE b) { IterImage[Itx] = b; }
+       BYTE* GetRow(void);
+       BYTE* GetRow(int n);
+       BOOL NextRow();
+       BOOL PrevRow();
+       BOOL NextByte();
+       BOOL PrevByte();
+
+       void SetSteps(int x, int y=0) {  Stepx = x; Stepy = y; }
+       void GetSteps(int *x, int *y) {  *x = Stepx; *y = Stepy; }
+       BOOL NextStep();
+       BOOL PrevStep();
+
+       void SetY(int y);       /* AD - for interlace */
+       int  GetY() {return Ity;}
+       BOOL GetCol(BYTE* pCol, DWORD x);
+       BOOL SetCol(BYTE* pCol, DWORD 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 >= (int)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(int y)
+{
+       if ((y < 0) || (y > (int)ima->GetHeight())) return;
+       Ity = y;
+       IterImage = ima->GetBits() + ima->GetEffWidth()*y;
+}
+/////////////////////////////////////////////////////////////////////
+inline void CImageIterator::SetRow(BYTE *buf, int n)
+{
+       if (n<0) n = (int)ima->GetEffWidth();
+       else n = min(n,(int)ima->GetEffWidth());
+
+       if ((IterImage!=NULL)&&(buf!=NULL)&&(n>0)) memcpy(IterImage,buf,n);
+}
+/////////////////////////////////////////////////////////////////////
+inline void CImageIterator::GetRow(BYTE *buf, int n)
+{
+       if ((IterImage!=NULL)&&(buf!=NULL)&&(n>0))
+               memcpy(buf,IterImage,min(n,(int)ima->GetEffWidth()));
+}
+/////////////////////////////////////////////////////////////////////
+inline BYTE* CImageIterator::GetRow()
+{
+       return IterImage;
+}
+/////////////////////////////////////////////////////////////////////
+inline BYTE* CImageIterator::GetRow(int n)
+{
+       SetY(n);
+       return IterImage;
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::NextByte()
+{
+       if (++Itx < (int)ima->GetEffWidth()) return 1;
+       else
+               if (++Ity < (int)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 < (int)ima->GetEffWidth()) return 1;
+       else {
+               Ity += Stepy;
+               if (Ity < (int)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 < (int)ima->GetHeight()) {
+                       IterImage -= ima->GetEffWidth();
+                       Itx = 0;
+                       return 1;
+               } else
+                       return 0;
+       }
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::GetCol(BYTE* pCol, DWORD x)
+{
+       if ((pCol==0)||(ima->GetBpp()<8)||(x>=ima->GetWidth()))
+               return 0;
+       DWORD h = ima->GetHeight();
+       //DWORD line = ima->GetEffWidth();
+       BYTE bytes = (BYTE)(ima->GetBpp()>>3);
+       BYTE* pSrc;
+       for (DWORD y=0;y<h;y++){
+               pSrc = ima->GetBits(y) + x*bytes;
+               for (BYTE w=0;w<bytes;w++){
+                       *pCol++=*pSrc++;
+               }
+       }
+       return 1;
+}
+/////////////////////////////////////////////////////////////////////
+inline BOOL CImageIterator::SetCol(BYTE* pCol, DWORD x)
+{
+       if ((pCol==0)||(ima->GetBpp()<8)||(x>=ima->GetWidth()))
+               return 0;
+       DWORD h = ima->GetHeight();
+       //DWORD line = ima->GetEffWidth();
+       BYTE bytes = (BYTE)(ima->GetBpp()>>3);
+       BYTE* pSrc;
+       for (DWORD y=0;y<h;y++){
+               pSrc = ima->GetBits(y) + x*bytes;
+               for (BYTE w=0;w<bytes;w++){
+                       *pSrc++=*pCol++;
+               }
+       }
+       return 1;
+}
+/////////////////////////////////////////////////////////////////////
+#endif
index 24a6b116bd9d03be83e3f7e988e08e19211c47d7..1c9093ab6fb2bb876d9d2f4864e309aef5001fb7 100644 (file)
-/*\r
- * File:       ximajas.cpp\r
- * Purpose:    Platform Independent JasPer Image Class Loader and Writer\r
- * 12/Apr/2003 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximajas.h"\r
-\r
-#if CXIMAGE_SUPPORT_JASPER\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageJAS::Decode(CxFile *hFile, DWORD imagetype)\r
-{\r
-       if (hFile == NULL) return false;\r
-\r
-       jas_image_t *image=0;\r
-       jas_stream_t *in=0;\r
-       jas_matrix_t **bufs=0;\r
-       long i,error=0;\r
-       int fmt;\r
-       //jas_setdbglevel(0);\r
-\r
-  cx_try\r
-  {\r
-       if (jas_init())\r
-               cx_throw("cannot initialize jasper");\r
-\r
-       in = jas_stream_fdopen(0, "rb");\r
-       if (!in)\r
-               cx_throw("error: cannot open standard input");\r
-\r
-       CxFileJas src(hFile,in);\r
-\r
-       fmt = jas_image_getfmt(in);\r
-       if (fmt<0)\r
-               cx_throw("error: unknowm format");\r
-\r
-       image = jas_image_decode(in, fmt, 0);\r
-       if (!image){\r
-               fmt = -1;\r
-               cx_throw("error: cannot load image data");\r
-       }\r
-\r
-       char szfmt[4];\r
-       *szfmt = '\0';\r
-       strncpy(szfmt,jas_image_fmttostr(fmt),3);\r
-       szfmt[3] = '\0';\r
-\r
-       fmt = -1;\r
-#if CXIMAGE_SUPPORT_JP2\r
-       if (strcmp(szfmt,"jp2")==0) fmt = CXIMAGE_FORMAT_JP2;\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPC\r
-       if (strcmp(szfmt,"jpc")==0) fmt = CXIMAGE_FORMAT_JPC;\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAS\r
-       if (strcmp(szfmt,"ras")==0) fmt = CXIMAGE_FORMAT_RAS;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNM\r
-       if (strcmp(szfmt,"pnm")==0) fmt = CXIMAGE_FORMAT_PNM;\r
-#endif\r
-#if CXIMAGE_SUPPORT_PGX\r
-       if (strcmp(szfmt,"pgx")==0) fmt = CXIMAGE_FORMAT_PGX;\r
-#endif\r
-\r
-       //if (fmt<0)\r
-       //      cx_throw("error: unknowm format");\r
-\r
-       long x,y,w,h,depth,cmptno;\r
-\r
-       w = jas_image_cmptwidth(image,0);\r
-       h = jas_image_cmptheight(image,0);\r
-       depth = jas_image_cmptprec(image,0);\r
-\r
-       if (info.nEscape == -1){\r
-               head.biWidth = w;\r
-               head.biHeight= h;\r
-               info.dwType = fmt<0 ? 0 : fmt;\r
-               cx_throw("output dimensions returned");\r
-       }\r
-\r
-       if (image->numcmpts_ > 64 || image->numcmpts_ < 0)\r
-               cx_throw("error: too many components");\r
-\r
-       // <LD> 01/Jan/2005: Always force conversion to sRGB. Seems to be required for many types of JPEG2000 file.\r
-       // if (depth!=1 && depth!=4 && depth!=8)\r
-       if (image->numcmpts_>=3 && depth <=8)\r
-       {\r
-               jas_image_t *newimage;\r
-               jas_cmprof_t *outprof;\r
-               //jas_eprintf("forcing conversion to sRGB\n");\r
-               outprof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB);\r
-               if (!outprof) {\r
-                       cx_throw("cannot create sRGB profile");\r
-               }\r
-               newimage = jas_image_chclrspc(image, outprof, JAS_CMXFORM_INTENT_PER);\r
-               if (!newimage) {\r
-                       jas_cmprof_destroy(outprof); // <LD> 01/Jan/2005: Destroy color profile on error.\r
-                       cx_throw("cannot convert to sRGB");\r
-               }\r
-               jas_image_destroy(image);\r
-               jas_cmprof_destroy(outprof);\r
-               image = newimage;\r
-       }\r
-\r
-       bufs = (jas_matrix_t **)calloc(image->numcmpts_, sizeof(jas_matrix_t**));\r
-       for (i = 0; i < image->numcmpts_; ++i) {\r
-               bufs[i] = jas_matrix_create(1, w);\r
-               if (!bufs[i]) {\r
-                       cx_throw("error: cannot allocate memory");\r
-               }\r
-       }\r
-\r
-       int nshift = (depth>8) ? (depth-8) : 0;\r
-\r
-       if (image->numcmpts_==3 &&\r
-               image->cmpts_[0]->width_ == image->cmpts_[1]->width_ &&\r
-               image->cmpts_[1]->width_ == image->cmpts_[2]->width_ &&\r
-               image->cmpts_[0]->height_ == image->cmpts_[1]->height_ &&\r
-               image->cmpts_[1]->height_ == image->cmpts_[2]->height_ &&\r
-               image->cmpts_[0]->prec_  == image->cmpts_[1]->prec_ &&\r
-               image->cmpts_[1]->prec_ == image->cmpts_[2]->prec_ )\r
-       {\r
-\r
-               if(!Create(w,h,24,fmt))\r
-                       cx_throw("");\r
-\r
-               RGBQUAD c;\r
-        for (y=0; y<h; y++) {\r
-                       for (cmptno = 0; cmptno < image->numcmpts_; ++cmptno) {\r
-                               jas_image_readcmpt(image, cmptno, 0, y, w, 1, bufs[cmptno]);\r
-                       }\r
-\r
-                       for (x=0; x<w; x++){\r
-                               c.rgbRed   = (BYTE)((jas_matrix_getv(bufs[0], x)>>nshift));\r
-                               c.rgbGreen = (BYTE)((jas_matrix_getv(bufs[1], x)>>nshift));\r
-                               c.rgbBlue  = (BYTE)((jas_matrix_getv(bufs[2], x)>>nshift));\r
-                               SetPixelColor(x,h-1-y,c);\r
-                       }\r
-               }\r
-       } else {\r
-               info.nNumFrames = image->numcmpts_;\r
-               if ((info.nFrame<0)||(info.nFrame>=info.nNumFrames)){\r
-                       cx_throw("wrong frame!");\r
-               }\r
-               for (cmptno=0; cmptno<=info.nFrame; cmptno++) {\r
-                       w = jas_image_cmptwidth(image,cmptno);\r
-                       h = jas_image_cmptheight(image,cmptno);\r
-                       depth = jas_image_cmptprec(image,cmptno);\r
-                       if (depth>8) depth=8;\r
-                       if(!Create(w,h,depth,imagetype))\r
-                               cx_throw("");\r
-                       SetGrayPalette();\r
-                       for (y=0; y<h; y++) {\r
-                               jas_image_readcmpt(image, cmptno, 0, y, w, 1, bufs[0]);\r
-                               for (x=0; x<w; x++){\r
-                                       SetPixelIndex(x,h-1-y,(BYTE)((jas_matrix_getv(bufs[0], x)>>nshift)));\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       if (info.nEscape == -1 && fmt>0){\r
-               error = 0;\r
-       } else {\r
-               error = 1;\r
-       }\r
-  }\r
-\r
-       if (bufs) {\r
-               for (i = 0; i < image->numcmpts_; ++i){ if (bufs[i]) jas_matrix_destroy(bufs[i]);}\r
-               free(bufs);\r
-       }\r
-       jas_cleanup();\r
-       if (image) jas_image_destroy(image);\r
-       if (in) jas_stream_close(in);\r
-       return (error==0);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageJAS::Encode(CxFile * hFile, DWORD imagetype)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       if (head.biClrUsed!=0 && !IsGrayScale()){\r
-               strcpy(info.szLastError,"JasPer can save only RGB or GrayScale images");\r
-               return false;\r
-       }\r
-\r
-       jas_image_t *image=0;\r
-       jas_stream_t *out=0;\r
-       jas_matrix_t *cmpts[3];\r
-       long x,y,yflip,error=0;\r
-       uint_fast16_t cmptno, numcmpts=0;\r
-       jas_image_cmptparm_t cmptparms[3], *cmptparm;\r
-\r
-  cx_try {\r
-\r
-       if (jas_init())\r
-               cx_throw("cannot initialize jasper");\r
-\r
-       out = jas_stream_fdopen(0, "wb");\r
-       if (!out)\r
-               cx_throw("error: cannot open standard output");\r
-\r
-       CxFileJas src(hFile,out);\r
-\r
-       numcmpts = head.biClrUsed==0 ? 3 : 1;\r
-\r
-       for (cmptno = 0, cmptparm = cmptparms; cmptno < numcmpts; ++cmptno, ++cmptparm) {\r
-               cmptparm->tlx = 0;\r
-               cmptparm->tly = 0;\r
-               cmptparm->hstep = 1;\r
-               cmptparm->vstep = 1;\r
-               cmptparm->width = head.biWidth;\r
-               cmptparm->height = head.biHeight;\r
-               cmptparm->prec = 8;\r
-               cmptparm->sgnd = false;\r
-       }\r
-\r
-       /* Create image object. */\r
-       image = jas_image_create(numcmpts, cmptparms, JAS_CLRSPC_UNKNOWN);\r
-       if (!image)\r
-               cx_throw("error : jas_image_create");\r
-\r
-       if (numcmpts == 3) {\r
-               jas_image_setclrspc(image, JAS_CLRSPC_SRGB);\r
-               jas_image_setcmpttype(image, 0,\r
-                 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));\r
-               jas_image_setcmpttype(image, 1,\r
-                 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));\r
-               jas_image_setcmpttype(image, 2,\r
-                 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));\r
-       } else {\r
-               jas_image_setclrspc(image, JAS_CLRSPC_SGRAY);\r
-               jas_image_setcmpttype(image, 0,\r
-                 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));\r
-       }\r
-\r
-\r
-       for (x = 0; x < numcmpts; ++x) { cmpts[x] = 0; }\r
-       /* Create temporary matrices to hold component data. */\r
-       for (x = 0; x < numcmpts; ++x) {\r
-               cmpts[x] = jas_matrix_create(1, head.biWidth);\r
-               if (!cmpts[x]) {\r
-                       cx_throw("error : can't allocate memory");\r
-               }\r
-       }\r
-\r
-       RGBQUAD c;\r
-       for (y = 0; y < head.biHeight; ++y) {\r
-               for (x = 0; x < head.biWidth; ++x) {\r
-                       if (head.biClrUsed==0){\r
-                               c = GetPixelColor(x,y);\r
-                               jas_matrix_setv(cmpts[0], x, c.rgbRed);\r
-                               jas_matrix_setv(cmpts[1], x, c.rgbGreen);\r
-                               jas_matrix_setv(cmpts[2], x, c.rgbBlue);\r
-                       } else {\r
-                               jas_matrix_setv(cmpts[0], x, GetPixelIndex(x,y));\r
-                       }\r
-               }\r
-               yflip = head.biHeight - 1 - y;\r
-               for (cmptno = 0; cmptno < numcmpts; ++cmptno) {\r
-                       if (jas_image_writecmpt(image, cmptno, 0, yflip, head.biWidth, 1, cmpts[cmptno])) {\r
-                               cx_throw("error : jas_image_writecmpt");\r
-                       }\r
-               }\r
-       }\r
-\r
-        char szfmt[4];\r
-       *szfmt = '\0';\r
-#if CXIMAGE_SUPPORT_JP2\r
-       if (imagetype == CXIMAGE_FORMAT_JP2) strcpy(szfmt,"jp2");\r
-#endif\r
-#if CXIMAGE_SUPPORT_JPC\r
-       if (imagetype == CXIMAGE_FORMAT_JPC) strcpy(szfmt,"jpc");\r
-#endif\r
-#if CXIMAGE_SUPPORT_RAS\r
-       if (imagetype == CXIMAGE_FORMAT_RAS) strcpy(szfmt,"ras");\r
-#endif\r
-#if CXIMAGE_SUPPORT_PNM\r
-       if (imagetype == CXIMAGE_FORMAT_PNM) strcpy(szfmt,"pnm");\r
-#endif\r
-#if CXIMAGE_SUPPORT_PGX\r
-       if (imagetype == CXIMAGE_FORMAT_PGX){\r
-               strcpy(szfmt,"pgx");\r
-               if (head.biClrUsed==0) cx_throw("PGX can save only GrayScale images");\r
-       }\r
-#endif\r
-       int outfmt = jas_image_strtofmt(szfmt);\r
-\r
-       char szoutopts[32];\r
-       sprintf(szoutopts,"rate=%.3f", info.fQuality/100.0f);\r
-\r
-       if (jas_image_encode(image, out, outfmt, szoutopts)) {\r
-               cx_throw("error: cannot encode image");\r
-       }\r
-       jas_stream_flush(out);\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       error = 1;\r
-  }\r
-\r
-       for (x = 0; x < numcmpts; ++x) { if (cmpts[x]) { jas_matrix_destroy(cmpts[x]); } }\r
-       jas_cleanup();\r
-       if (image) jas_image_destroy(image);\r
-       if (out) jas_stream_close(out);\r
-\r
-       return (error==0);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_JASPER\r
-\r
+/*
+ * File:       ximajas.cpp
+ * Purpose:    Platform Independent JasPer Image Class Loader and Writer
+ * 12/Apr/2003 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximajas.h"
+
+#if CXIMAGE_SUPPORT_JASPER
+
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageJAS::Decode(CxFile *hFile, DWORD imagetype)
+{
+       if (hFile == NULL) return false;
+
+       jas_image_t *image=0;
+       jas_stream_t *in=0;
+       jas_matrix_t **bufs=0;
+       long i,error=0;
+       int 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");
+
+       long 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");
+               }
+       }
+
+       int 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   = (BYTE)((jas_matrix_getv(bufs[0], x)>>nshift));
+                               c.rgbGreen = (BYTE)((jas_matrix_getv(bufs[1], x)>>nshift));
+                               c.rgbBlue  = (BYTE)((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,(BYTE)((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, DWORD 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];
+       long 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
+       int 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
+
index 7225f0132eb22d99d86faeba9906a3c0ddade3a5..c5874d17939925e1830dab8b3db5a02a51564db3 100644 (file)
@@ -1,84 +1,84 @@
-/*\r
- * File:       ximajas.h\r
- * Purpose:    Jasper Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageJAS (c) 12/Apr/2003 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * based on JasPer Copyright (c) 2001-2003 Michael David Adams - All rights reserved.\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaJAS_h)\r
-#define __ximaJAS_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_JASPER\r
-\r
-#include "../jasper/include/jasper/jasper.h"\r
-\r
-class CxImageJAS: public CxImage\r
-{\r
-public:\r
-       CxImageJAS(): CxImage((DWORD)0) {}      // <vho> cast to DWORD\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,0);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,0);}\r
-       bool Decode(CxFile * hFile, DWORD imagetype = 0);\r
-       bool Decode(FILE *hFile, DWORD imagetype = 0) { CxIOFile file(hFile); return Decode(&file,imagetype); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile, DWORD imagetype = 0);\r
-       bool Encode(FILE *hFile, DWORD imagetype = 0) { CxIOFile file(hFile); return Encode(&file,imagetype); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-protected:\r
-\r
-       class CxFileJas\r
-       {\r
-       public:\r
-               CxFileJas(CxFile* pFile,jas_stream_t *stream)\r
-               {\r
-                       if (stream->obj_) jas_free(stream->obj_);\r
-                       stream->obj_ = pFile;\r
-\r
-                       // <vho> - cannot set the stream->ops_->functions here,\r
-                       // because this overwrites a static structure in the Jasper library.\r
-                       // This structure is used by Jasper for internal operations too, e.g. tempfile.\r
-                       // However the ops_ pointer in the stream can be overwritten.\r
-\r
-                       //stream->ops_->close_ = JasClose;\r
-                       //stream->ops_->read_  = JasRead;\r
-                       //stream->ops_->seek_  = JasSeek;\r
-                       //stream->ops_->write_ = JasWrite;\r
-\r
-                       jas_stream_CxFile.close_ = JasClose;\r
-                       jas_stream_CxFile.read_  = JasRead;\r
-                       jas_stream_CxFile.seek_  = JasSeek;\r
-                       jas_stream_CxFile.write_ = JasWrite;\r
-\r
-                       stream->ops_ = &jas_stream_CxFile;\r
-\r
-                       // <vho> - end\r
-               }\r
-               static int JasRead(jas_stream_obj_t *obj, char *buf, int cnt)\r
-               {               return ((CxFile*)obj)->Read(buf,1,cnt); }\r
-               static int JasWrite(jas_stream_obj_t *obj, char *buf, int cnt)\r
-               {               return ((CxFile*)obj)->Write(buf,1,cnt); }\r
-               static long JasSeek(jas_stream_obj_t *obj, long offset, int origin)\r
-               {               return ((CxFile*)obj)->Seek(offset,origin); }\r
-               static int JasClose(jas_stream_obj_t * /*obj*/)\r
-               {               return 1; }\r
-\r
-       // <vho>\r
-private:\r
-               jas_stream_ops_t jas_stream_CxFile;\r
-       // <vho> - end\r
-\r
-       };\r
-\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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
+
+#include "../jasper/include/jasper/jasper.h"
+
+class CxImageJAS: public CxImage
+{
+public:
+       CxImageJAS(): CxImage((DWORD)0) {}      // <vho> cast to DWORD
+
+//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,0);}
+//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,0);}
+       bool Decode(CxFile * hFile, DWORD imagetype = 0);
+       bool Decode(FILE *hFile, DWORD imagetype = 0) { CxIOFile file(hFile); return Decode(&file,imagetype); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+       bool Encode(CxFile * hFile, DWORD imagetype = 0);
+       bool Encode(FILE *hFile, DWORD 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 int JasRead(jas_stream_obj_t *obj, char *buf, int cnt)
+               {               return ((CxFile*)obj)->Read(buf,1,cnt); }
+               static int JasWrite(jas_stream_obj_t *obj, char *buf, int cnt)
+               {               return ((CxFile*)obj)->Write(buf,1,cnt); }
+               static long JasSeek(jas_stream_obj_t *obj, long offset, int origin)
+               {               return ((CxFile*)obj)->Seek(offset,origin); }
+               static int JasClose(jas_stream_obj_t * /*obj*/)
+               {               return 1; }
+
+       // <vho>
+private:
+               jas_stream_ops_t jas_stream_CxFile;
+       // <vho> - end
+
+       };
+
+};
+
+#endif
+
+#endif
index 25331080da2e39094ce9080665676a1d2b845739..06fb9bfa26bcef3fcd4da6e000d1468c3c5a9e04 100644 (file)
-/*\r
- * File:       ximajbg.cpp\r
- * Purpose:    Platform Independent JBG Image Class Loader and Writer\r
- * 18/Aug/2002 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximajbg.h"\r
-\r
-#if CXIMAGE_SUPPORT_JBG\r
-\r
-#include "ximaiter.h"\r
-\r
-#define JBIG_BUFSIZE 8192\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageJBG::Decode(CxFile *hFile)\r
-{\r
-       if (hFile == NULL) return false;\r
-\r
-       struct jbg_dec_state jbig_state;\r
-       unsigned long xmax = 4294967295UL, ymax = 4294967295UL;\r
-       unsigned int len, cnt;\r
-       BYTE *buffer,*p;\r
-       int result;\r
-\r
-  cx_try\r
-  {\r
-       jbg_dec_init(&jbig_state);\r
-       jbg_dec_maxsize(&jbig_state, xmax, ymax);\r
-\r
-       buffer = (BYTE*)malloc(JBIG_BUFSIZE);\r
-       if (!buffer) cx_throw("Sorry, not enough memory available!");\r
-\r
-       result = JBG_EAGAIN;\r
-       do {\r
-               len = hFile->Read(buffer, 1, JBIG_BUFSIZE);\r
-               if (!len) break;\r
-               cnt = 0;\r
-               p = buffer;\r
-               while (len > 0 && (result == JBG_EAGAIN || result == JBG_EOK)) {\r
-                       result = jbg_dec_in(&jbig_state, p, len, &cnt);\r
-                       p += cnt;\r
-                       len -= cnt;\r
-               }\r
-       } while (result == JBG_EAGAIN || result == JBG_EOK);\r
-\r
-       if (hFile->Error())\r
-               cx_throw("Problem while reading input file");\r
-       if (result != JBG_EOK && result != JBG_EOK_INTR)\r
-               cx_throw("Problem with input file"); \r
-\r
-       int w, h, bpp, planes, ew;\r
-\r
-       w = jbg_dec_getwidth(&jbig_state);\r
-       h = jbg_dec_getheight(&jbig_state);\r
-       planes = jbg_dec_getplanes(&jbig_state);\r
-       bpp = (planes+7)>>3;\r
-       ew = (w + 7)>>3;\r
-\r
-       if (info.nEscape == -1){\r
-               head.biWidth = w;\r
-               head.biHeight= h;\r
-               info.dwType = CXIMAGE_FORMAT_JBG;\r
-               cx_throw("output dimensions returned");\r
-       }\r
-\r
-       switch (planes){\r
-       case 1:\r
-               {\r
-                       BYTE* binary_image = jbg_dec_getimage(&jbig_state, 0);\r
-\r
-                       if (!Create(w,h,1,CXIMAGE_FORMAT_JBG))\r
-                               cx_throw("");\r
-\r
-                       SetPaletteColor(0,255,255,255);\r
-                       SetPaletteColor(1,0,0,0);\r
-\r
-                       CImageIterator iter(this);\r
-                       iter.Upset();\r
-                       for (int i=0;i<h;i++){\r
-                               iter.SetRow(binary_image+i*ew,ew);\r
-                               iter.PrevRow();\r
-                       }\r
-\r
-                       break;\r
-               }\r
-       default:\r
-               cx_throw("cannot decode images with more than 1 plane");\r
-       }\r
-\r
-       jbg_dec_free(&jbig_state);\r
-       free(buffer);\r
-\r
-  } cx_catch {\r
-       jbg_dec_free(&jbig_state);\r
-       if (buffer) free(buffer);\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_JBG) return true;\r
-       return false;\r
-  }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageJBG::Encode(CxFile * hFile)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       if (head.biBitCount != 1){\r
-               strcpy(info.szLastError,"JBG can save only 1-bpp images");\r
-               return false;\r
-       }\r
-\r
-       int w, h, bpp, planes, ew, i, j, x, y;\r
-\r
-       w = head.biWidth;\r
-       h = head.biHeight;\r
-       planes = 1;\r
-       bpp = (planes+7)>>3;\r
-       ew = (w + 7)>>3;\r
-\r
-       BYTE mask;\r
-       RGBQUAD *rgb = GetPalette();\r
-       if (CompareColors(&rgb[0],&rgb[1])<0) mask=255; else mask=0;\r
-\r
-       BYTE *buffer = (BYTE*)malloc(ew*h*2);\r
-       if (!buffer) {\r
-               strcpy(info.szLastError,"Sorry, not enough memory available!");\r
-               return false;\r
-       }\r
-\r
-       for (y=0; y<h; y++){\r
-               i= y*ew;\r
-               j= (h-y-1)*info.dwEffWidth;\r
-               for (x=0; x<ew; x++){\r
-                       buffer[i + x]=info.pImage[j + x]^mask;\r
-               }\r
-       }\r
-\r
-       struct jbg_enc_state jbig_state;\r
-       jbg_enc_init(&jbig_state, w, h, planes, &buffer, jbig_data_out, hFile);\r
-\r
-    //jbg_enc_layers(&jbig_state, 2);\r
-    //jbg_enc_lrlmax(&jbig_state, 800, 600);\r
-\r
-       // Specify a few other options (each is ignored if negative)\r
-       int dl = -1, dh = -1, d = -1, l0 = -1, mx = -1;\r
-       int options = JBG_TPDON | JBG_TPBON | JBG_DPON;\r
-       int order = JBG_ILEAVE | JBG_SMID;\r
-       jbg_enc_lrange(&jbig_state, dl, dh);\r
-       jbg_enc_options(&jbig_state, order, options, l0, mx, -1);\r
-\r
-       // now encode everything and send it to data_out()\r
-       jbg_enc_out(&jbig_state);\r
-\r
-       // give encoder a chance to free its temporary data structures\r
-       jbg_enc_free(&jbig_state);\r
-\r
-       free(buffer);\r
-\r
-       if (hFile->Error()){\r
-               strcpy(info.szLastError,"Problem while writing JBG file");\r
-               return false;\r
-       }\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif         // CXIMAGE_SUPPORT_JBG\r
-\r
+/*
+ * File:       ximajbg.cpp
+ * Purpose:    Platform Independent JBG Image Class Loader and Writer
+ * 18/Aug/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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;
+       unsigned long xmax = 4294967295UL, ymax = 4294967295UL;
+       unsigned int len, cnt;
+       BYTE *buffer,*p;
+       int result;
+
+  cx_try
+  {
+       jbg_dec_init(&jbig_state);
+       jbg_dec_maxsize(&jbig_state, xmax, ymax);
+
+       buffer = (BYTE*)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"); 
+
+       int 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:
+               {
+                       BYTE* 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 (int 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;
+       }
+
+       int 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;
+
+       BYTE mask;
+       RGBQUAD *rgb = GetPalette();
+       if (CompareColors(&rgb[0],&rgb[1])<0) mask=255; else mask=0;
+
+       BYTE *buffer = (BYTE*)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)
+       int dl = -1, dh = -1, d = -1, l0 = -1, mx = -1;
+       int options = JBG_TPDON | JBG_TPBON | JBG_DPON;
+       int 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
+
index 137eedfa0d540a42da102211497e215dd302a931..926b591ce560856649798d4318e557c4a13ddcfe 100644 (file)
@@ -1,44 +1,44 @@
-/*\r
- * File:       ximajbg.h\r
- * Purpose:    JBG Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageJBG (c) 18/Aug/2002 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * based on LIBJBG Copyright (c) 2002, Markus Kuhn - All rights reserved.\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaJBG_h)\r
-#define __ximaJBG_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_JBG\r
-\r
-extern "C" {\r
-#include "../jbig/jbig.h"\r
-};\r
-\r
-class CxImageJBG: public CxImage\r
-{\r
-public:\r
-       CxImageJBG(): CxImage(CXIMAGE_FORMAT_JBG) {}\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_JBG);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_JBG);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-protected:\r
-       static void jbig_data_out(BYTE *buffer, unsigned int len, void *file)\r
-                                                       {((CxFile*)file)->Write(buffer,len,1);}\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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(BYTE *buffer, unsigned int len, void *file)
+                                                       {((CxFile*)file)->Write(buffer,len,1);}
+};
+
+#endif
+
+#endif
index 30146aa731d1b0fa6b5b3b75e7316e74d669ed3b..1cf5a00dba489fd626430e2309a094e00ba92857 100644 (file)
-/*\r
- * File:       ximajpg.cpp\r
- * Purpose:    Platform Independent JPEG Image Class Loader and Writer\r
- * 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
\r
-#include "ximajpg.h"\r
-\r
-#if CXIMAGE_SUPPORT_JPG\r
-\r
-#include "../jpeg/jmorecfg.h"\r
-\r
-#include "ximaiter.h"\r
-         \r
-#include <setjmp.h>\r
-\r
-struct jpg_error_mgr {\r
-       struct jpeg_error_mgr pub;      /* "public" fields */\r
-       jmp_buf setjmp_buffer;          /* for return to caller */\r
-       char* buffer;                           /* error message <CSC>*/\r
-};\r
-typedef jpg_error_mgr *jpg_error_ptr;\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Here's the routine that will replace the standard error_exit method:\r
-////////////////////////////////////////////////////////////////////////////////\r
-static void\r
-ima_jpeg_error_exit (j_common_ptr cinfo)\r
-{\r
-       /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */\r
-       jpg_error_ptr myerr = (jpg_error_ptr) cinfo->err;\r
-       /* Create the message */\r
-       myerr->pub.format_message (cinfo, myerr->buffer);\r
-       /* Send it to stderr, adding a newline */\r
-       /* Return control to the setjmp point */\r
-       longjmp(myerr->setjmp_buffer, 1);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-CxImageJPG::CxImageJPG(): CxImage(CXIMAGE_FORMAT_JPG)\r
-{\r
-#if CXIMAGEJPG_SUPPORT_EXIF\r
-       m_exif = NULL;\r
-       memset(&m_exifinfo, 0, sizeof(EXIFINFO));\r
-#endif\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-CxImageJPG::~CxImageJPG()\r
-{\r
-#if CXIMAGEJPG_SUPPORT_EXIF\r
-       if (m_exif) delete m_exif;\r
-#endif\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGEJPG_SUPPORT_EXIF\r
-bool CxImageJPG::DecodeExif(CxFile * hFile)\r
-{\r
-       m_exif = new CxExifInfo(&m_exifinfo);\r
-       if (m_exif){\r
-               long pos=hFile->Tell();\r
-               m_exif->DecodeExif(hFile);\r
-               hFile->Seek(pos,SEEK_SET);\r
-               return m_exif->m_exifinfo->IsExif;\r
-       } else {\r
-               return false;\r
-       }\r
-}\r
-#endif //CXIMAGEJPG_SUPPORT_EXIF\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageJPG::Decode(CxFile * hFile)\r
-{\r
-\r
-       bool is_exif = false;\r
-#if CXIMAGEJPG_SUPPORT_EXIF\r
-       is_exif = DecodeExif(hFile);\r
-#endif\r
-\r
-       CImageIterator iter(this);\r
-       /* This struct contains the JPEG decompression parameters and pointers to\r
-       * working space (which is allocated as needed by the JPEG library).\r
-       */\r
-       struct jpeg_decompress_struct cinfo;\r
-       /* We use our private extension JPEG error handler. <CSC> */\r
-       struct jpg_error_mgr jerr;\r
-       jerr.buffer=info.szLastError;\r
-       /* More stuff */\r
-       JSAMPARRAY buffer;      /* Output row buffer */\r
-       int row_stride;         /* physical row width in output buffer */\r
-\r
-       /* In this example we want to open the input file before doing anything else,\r
-       * so that the setjmp() error recovery below can assume the file is open.\r
-       * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that\r
-       * requires it in order to read binary files.\r
-       */\r
-\r
-       /* Step 1: allocate and initialize JPEG decompression object */\r
-       /* We set up the normal JPEG error routines, then override error_exit. */\r
-       cinfo.err = jpeg_std_error(&jerr.pub);\r
-       jerr.pub.error_exit = ima_jpeg_error_exit;\r
-\r
-       /* Establish the setjmp return context for my_error_exit to use. */\r
-       if (setjmp(jerr.setjmp_buffer)) {\r
-               /* If we get here, the JPEG code has signaled an error.\r
-               * We need to clean up the JPEG object, close the input file, and return.\r
-               */\r
-               jpeg_destroy_decompress(&cinfo);\r
-               return 0;\r
-       }\r
-       /* Now we can initialize the JPEG decompression object. */\r
-       jpeg_create_decompress(&cinfo);\r
-\r
-       /* Step 2: specify data source (eg, a file) */\r
-       //jpeg_stdio_src(&cinfo, infile);\r
-       CxFileJpg src(hFile);\r
-    cinfo.src = &src;\r
-\r
-       /* Step 3: read file parameters with jpeg_read_header() */\r
-       (void) jpeg_read_header(&cinfo, TRUE);\r
-\r
-       /* Step 4 <chupeev> handle decoder options*/\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_GRAYSCALE) != 0)\r
-               cinfo.out_color_space = JCS_GRAYSCALE;\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_QUANTIZE) != 0) {\r
-               cinfo.quantize_colors = TRUE;\r
-               cinfo.desired_number_of_colors = GetJpegQuality();\r
-       }\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_DITHER) != 0)\r
-               cinfo.dither_mode = m_nDither;\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_ONEPASS) != 0)\r
-               cinfo.two_pass_quantize = FALSE;\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_NOSMOOTH) != 0)\r
-               cinfo.do_fancy_upsampling = FALSE;\r
-\r
-//<DP>: Load true color images as RGB (no quantize) \r
-/* Step 4: set parameters for decompression */\r
-/*  if (cinfo.jpeg_color_space!=JCS_GRAYSCALE) {\r
- *     cinfo.quantize_colors = TRUE;\r
- *     cinfo.desired_number_of_colors = 128;\r
- *}\r
- */ //</DP>\r
-\r
-       // Set the scale <ignacio>\r
-       cinfo.scale_denom = GetJpegScale();\r
-\r
-       // Borrowed the idea from GIF implementation <ignacio>\r
-       if (info.nEscape == -1) {\r
-               // Return output dimensions only\r
-               jpeg_calc_output_dimensions(&cinfo);\r
-               head.biWidth = cinfo.output_width;\r
-               head.biHeight = cinfo.output_height;\r
-               info.dwType = CXIMAGE_FORMAT_JPG;\r
-               jpeg_destroy_decompress(&cinfo);\r
-               return true;\r
-       }\r
-\r
-       /* Step 5: Start decompressor */\r
-       jpeg_start_decompress(&cinfo);\r
-\r
-       /* We may need to do some setup of our own at this point before reading\r
-       * the data.  After jpeg_start_decompress() we have the correct scaled\r
-       * output image dimensions available, as well as the output colormap\r
-       * if we asked for color quantization.\r
-       */\r
-       //Create the image using output dimensions <ignacio>\r
-       //Create(cinfo.image_width, cinfo.image_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG);\r
-       Create(cinfo.output_width, cinfo.output_height, 8*cinfo.output_components, CXIMAGE_FORMAT_JPG);\r
-\r
-       if (!pDib) longjmp(jerr.setjmp_buffer, 1);  //<DP> check if the image has been created\r
-\r
-       if (is_exif){\r
-#if CXIMAGEJPG_SUPPORT_EXIF\r
-       if ((m_exifinfo.Xresolution != 0.0) && (m_exifinfo.ResolutionUnit != 0))\r
-               SetXDPI((long)(m_exifinfo.Xresolution/m_exifinfo.ResolutionUnit));\r
-       if ((m_exifinfo.Yresolution != 0.0) && (m_exifinfo.ResolutionUnit != 0))\r
-               SetYDPI((long)(m_exifinfo.Yresolution/m_exifinfo.ResolutionUnit));\r
-#endif\r
-       } else {\r
-               switch (cinfo.density_unit) {\r
-               case 0: // [andy] fix for aspect ratio...\r
-                       if((cinfo.Y_density > 0) && (cinfo.X_density > 0)){\r
-                               SetYDPI((long)(GetXDPI()*(float(cinfo.Y_density)/float(cinfo.X_density))));\r
-                       }\r
-                       break;\r
-               case 2: // [andy] fix: cinfo.X/Y_density is pixels per centimeter\r
-                       SetXDPI((long)floor(cinfo.X_density * 2.54 + 0.5));\r
-                       SetYDPI((long)floor(cinfo.Y_density * 2.54 + 0.5));\r
-                       break;\r
-               default:\r
-                       SetXDPI(cinfo.X_density);\r
-                       SetYDPI(cinfo.Y_density);\r
-               }\r
-       }\r
-\r
-       if (cinfo.out_color_space==JCS_GRAYSCALE){\r
-               SetGrayPalette();\r
-               head.biClrUsed =256;\r
-       } else {\r
-               if (cinfo.quantize_colors){\r
-                       SetPalette(cinfo.actual_number_of_colors, cinfo.colormap[0], cinfo.colormap[1], cinfo.colormap[2]);\r
-                       head.biClrUsed=cinfo.actual_number_of_colors;\r
-               } else {\r
-                       head.biClrUsed=0;\r
-               }\r
-       }\r
-\r
-       /* JSAMPLEs per row in output buffer */\r
-       row_stride = cinfo.output_width * cinfo.output_components;\r
-\r
-       /* Make a one-row-high sample array that will go away when done with image */\r
-       buffer = (*cinfo.mem->alloc_sarray)\r
-               ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);\r
-\r
-       /* Step 6: while (scan lines remain to be read) */\r
-       /*           jpeg_read_scanlines(...); */\r
-       /* Here we use the library's state variable cinfo.output_scanline as the\r
-       * loop counter, so that we don't have to keep track ourselves.\r
-       */\r
-       iter.Upset();\r
-       while (cinfo.output_scanline < cinfo.output_height) {\r
-\r
-               if (info.nEscape) longjmp(jerr.setjmp_buffer, 1); // <vho> - cancel decoding\r
-               \r
-               (void) jpeg_read_scanlines(&cinfo, buffer, 1);\r
-               // info.nProgress = (long)(100*cinfo.output_scanline/cinfo.output_height);\r
-               //<DP> Step 6a: CMYK->RGB */ \r
-               if ((cinfo.num_components==4)&&(cinfo.quantize_colors==FALSE)){\r
-                       BYTE k,*dst,*src;\r
-                       dst=iter.GetRow();\r
-                       src=buffer[0];\r
-                       for(long x3=0,x4=0; x3<(long)info.dwEffWidth && x4<row_stride; x3+=3, x4+=4){\r
-                               k=src[x4+3];\r
-                               dst[x3]  =(BYTE)((k * src[x4+2])/255);\r
-                               dst[x3+1]=(BYTE)((k * src[x4+1])/255);\r
-                               dst[x3+2]=(BYTE)((k * src[x4+0])/255);\r
-                       }\r
-               } else {\r
-                       /* Assume put_scanline_someplace wants a pointer and sample count. */\r
-                       iter.SetRow(buffer[0], row_stride);\r
-               }\r
-                       iter.PrevRow();\r
-       }\r
-\r
-       /* Step 7: Finish decompression */\r
-       (void) jpeg_finish_decompress(&cinfo);\r
-       /* We can ignore the return value since suspension is not possible\r
-       * with the stdio data source.\r
-       */\r
-\r
-       //<DP> Step 7A: Swap red and blue components\r
-       // not necessary if swapped red and blue definition in jmorecfg.h;ln322 <W. Morrison>\r
-       if ((cinfo.num_components==3)&&(cinfo.quantize_colors==FALSE)){\r
-               BYTE* r0=GetBits();\r
-               for(long y=0;y<head.biHeight;y++){\r
-                       if (info.nEscape) longjmp(jerr.setjmp_buffer, 1); // <vho> - cancel decoding\r
-                       RGBtoBGR(r0,3*head.biWidth);\r
-                       r0+=info.dwEffWidth;\r
-               }\r
-       }\r
-\r
-       /* Step 8: Release JPEG decompression object */\r
-       /* This is an important step since it will release a good deal of memory. */\r
-       jpeg_destroy_decompress(&cinfo);\r
-\r
-       /* At this point you may want to check to see whether any corrupt-data\r
-       * warnings occurred (test whether jerr.pub.num_warnings is nonzero).\r
-       */\r
-\r
-       /* And we're done! */\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageJPG::Encode(CxFile * hFile)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       if (head.biClrUsed!=0 && !IsGrayScale()){\r
-               strcpy(info.szLastError,"JPEG can save only RGB or GreyScale images");\r
-               return false;\r
-       }       \r
-\r
-       // necessary for EXIF, and for roll backs\r
-       long pos=hFile->Tell();\r
-\r
-       /* This struct contains the JPEG compression parameters and pointers to\r
-       * working space (which is allocated as needed by the JPEG library).\r
-       * It is possible to have several such structures, representing multiple\r
-       * compression/decompression processes, in existence at once.  We refer\r
-       * to any one struct (and its associated working data) as a "JPEG object".\r
-       */\r
-       struct jpeg_compress_struct cinfo;\r
-       /* This struct represents a JPEG error handler.  It is declared separately\r
-       * because applications often want to supply a specialized error handler\r
-       * (see the second half of this file for an example).  But here we just\r
-       * take the easy way out and use the standard error handler, which will\r
-       * print a message on stderr and call exit() if compression fails.\r
-       * Note that this struct must live as long as the main JPEG parameter\r
-       * struct, to avoid dangling-pointer problems.\r
-       */\r
-       //struct jpeg_error_mgr jerr;\r
-       /* We use our private extension JPEG error handler. <CSC> */\r
-       struct jpg_error_mgr jerr;\r
-       jerr.buffer=info.szLastError;\r
-       /* More stuff */\r
-       int row_stride;         /* physical row width in image buffer */\r
-       JSAMPARRAY buffer;              /* Output row buffer */\r
-\r
-       /* Step 1: allocate and initialize JPEG compression object */\r
-       /* We have to set up the error handler first, in case the initialization\r
-       * step fails.  (Unlikely, but it could happen if you are out of memory.)\r
-       * This routine fills in the contents of struct jerr, and returns jerr's\r
-       * address which we place into the link field in cinfo.\r
-       */\r
-       //cinfo.err = jpeg_std_error(&jerr); <CSC>\r
-       /* We set up the normal JPEG error routines, then override error_exit. */\r
-       cinfo.err = jpeg_std_error(&jerr.pub);\r
-       jerr.pub.error_exit = ima_jpeg_error_exit;\r
-\r
-       /* Establish the setjmp return context for my_error_exit to use. */\r
-       if (setjmp(jerr.setjmp_buffer)) {\r
-               /* If we get here, the JPEG code has signaled an error.\r
-               * We need to clean up the JPEG object, close the input file, and return.\r
-               */\r
-               strcpy(info.szLastError, jerr.buffer); //<CSC>\r
-               jpeg_destroy_compress(&cinfo);\r
-               return 0;\r
-       }\r
-       \r
-       /* Now we can initialize the JPEG compression object. */\r
-       jpeg_create_compress(&cinfo);\r
-       /* Step 2: specify data destination (eg, a file) */\r
-       /* Note: steps 2 and 3 can be done in either order. */\r
-       /* Here we use the library-supplied code to send compressed data to a\r
-       * stdio stream.  You can also write your own code to do something else.\r
-       * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that\r
-       * requires it in order to write binary files.\r
-       */\r
-\r
-       //jpeg_stdio_dest(&cinfo, outfile);\r
-       CxFileJpg dest(hFile);\r
-    cinfo.dest = &dest;\r
-\r
-       /* Step 3: set parameters for compression */\r
-       /* First we supply a description of the input image.\r
-       * Four fields of the cinfo struct must be filled in:\r
-       */\r
-       cinfo.image_width = GetWidth();         // image width and height, in pixels\r
-       cinfo.image_height = GetHeight();\r
-\r
-       if (IsGrayScale()){\r
-               cinfo.input_components = 1;                     // # of color components per pixel\r
-               cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */\r
-       } else {\r
-               cinfo.input_components = 3;     // # of color components per pixel\r
-               cinfo.in_color_space = JCS_RGB; /* colorspace of input image */\r
-       }\r
-\r
-       /* Now use the library's routine to set default compression parameters.\r
-       * (You must set at least cinfo.in_color_space before calling this,\r
-       * since the defaults depend on the source color space.)\r
-       */\r
-       jpeg_set_defaults(&cinfo);\r
-       /* Now you can set any non-default parameters you wish to.\r
-       * Here we just illustrate the use of quality (quantization table) scaling:\r
-       */\r
-\r
-//#ifdef C_ARITH_CODING_SUPPORTED\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_ARITHMETIC) != 0)\r
-               cinfo.arith_code = TRUE;\r
-//#endif\r
-\r
-//#ifdef ENTROPY_OPT_SUPPORTED\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_OPTIMIZE) != 0)\r
-               cinfo.optimize_coding = TRUE;\r
-//#endif\r
-\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_GRAYSCALE) != 0)\r
-               jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE);\r
-\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_SMOOTHING) != 0)\r
-               cinfo.smoothing_factor = m_nSmoothing;\r
-\r
-       jpeg_set_quality(&cinfo, GetJpegQuality(), (GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_BASELINE) != 0);\r
-\r
-//#ifdef C_PROGRESSIVE_SUPPORTED\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_PROGRESSIVE) != 0)\r
-               jpeg_simple_progression(&cinfo);\r
-//#endif\r
-\r
-#ifdef C_LOSSLESS_SUPPORTED\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_LOSSLESS) != 0)\r
-               jpeg_simple_lossless(&cinfo, m_nPredictor, m_nPointTransform);\r
-#endif\r
-\r
-       //SetCodecOption(ENCODE_SUBSAMPLE_444 | GetCodecOption(CXIMAGE_FORMAT_JPG),CXIMAGE_FORMAT_JPG);\r
-\r
-               // 2x2, 1x1, 1x1 (4:1:1) : High (default sub sampling)\r
-               cinfo.comp_info[0].h_samp_factor = 2;\r
-               cinfo.comp_info[0].v_samp_factor = 2;\r
-               cinfo.comp_info[1].h_samp_factor = 1;\r
-               cinfo.comp_info[1].v_samp_factor = 1;\r
-               cinfo.comp_info[2].h_samp_factor = 1;\r
-               cinfo.comp_info[2].v_samp_factor = 1;\r
-\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_SUBSAMPLE_422) != 0){\r
-               // 2x1, 1x1, 1x1 (4:2:2) : Medium\r
-               cinfo.comp_info[0].h_samp_factor = 2;\r
-               cinfo.comp_info[0].v_samp_factor = 1;\r
-               cinfo.comp_info[1].h_samp_factor = 1;\r
-               cinfo.comp_info[1].v_samp_factor = 1;\r
-               cinfo.comp_info[2].h_samp_factor = 1;\r
-               cinfo.comp_info[2].v_samp_factor = 1;\r
-       }\r
-\r
-       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_SUBSAMPLE_444) != 0){\r
-               // 1x1 1x1 1x1 (4:4:4) : None\r
-               cinfo.comp_info[0].h_samp_factor = 1;\r
-               cinfo.comp_info[0].v_samp_factor = 1;\r
-               cinfo.comp_info[1].h_samp_factor = 1;\r
-               cinfo.comp_info[1].v_samp_factor = 1;\r
-               cinfo.comp_info[2].h_samp_factor = 1;\r
-               cinfo.comp_info[2].v_samp_factor = 1;\r
-       }\r
-\r
-       cinfo.density_unit=1;\r
-       cinfo.X_density=(unsigned short)GetXDPI();\r
-       cinfo.Y_density=(unsigned short)GetYDPI();\r
-\r
-       /* Step 4: Start compressor */\r
-       /* TRUE ensures that we will write a complete interchange-JPEG file.\r
-       * Pass TRUE unless you are very sure of what you're doing.\r
-       */\r
-       jpeg_start_compress(&cinfo, TRUE);\r
-\r
-       /* Step 5: while (scan lines remain to be written) */\r
-       /*           jpeg_write_scanlines(...); */\r
-       /* Here we use the library's state variable cinfo.next_scanline as the\r
-       * loop counter, so that we don't have to keep track ourselves.\r
-       * To keep things simple, we pass one scanline per call; you can pass\r
-       * more if you wish, though.\r
-       */\r
-       row_stride = info.dwEffWidth;   /* JSAMPLEs per row in image_buffer */\r
-\r
-       //<DP> "8+row_stride" fix heap deallocation problem during debug???\r
-       buffer = (*cinfo.mem->alloc_sarray)\r
-               ((j_common_ptr) &cinfo, JPOOL_IMAGE, 8+row_stride, 1);\r
-\r
-       CImageIterator iter(this);\r
-\r
-       iter.Upset();\r
-       while (cinfo.next_scanline < cinfo.image_height) {\r
-               // info.nProgress = (long)(100*cinfo.next_scanline/cinfo.image_height);\r
-               iter.GetRow(buffer[0], row_stride);\r
-               // not necessary if swapped red and blue definition in jmorecfg.h;ln322 <W. Morrison>\r
-               if (head.biClrUsed==0){                          // swap R & B for RGB images\r
-                       RGBtoBGR(buffer[0], row_stride); // Lance : 1998/09/01 : Bug ID: EXP-2.1.1-9\r
-               }\r
-               iter.PrevRow();\r
-               (void) jpeg_write_scanlines(&cinfo, buffer, 1);\r
-       }\r
-\r
-       /* Step 6: Finish compression */\r
-       jpeg_finish_compress(&cinfo);\r
-\r
-       /* Step 7: release JPEG compression object */\r
-       /* This is an important step since it will release a good deal of memory. */\r
-       jpeg_destroy_compress(&cinfo);\r
-\r
-\r
-#if CXIMAGEJPG_SUPPORT_EXIF\r
-       if (m_exif && m_exif->m_exifinfo->IsExif){\r
-               // discard useless sections (if any) read from original image\r
-               m_exif->DiscardAllButExif();\r
-               // read new created image, to split the sections\r
-               hFile->Seek(pos,SEEK_SET);\r
-               m_exif->DecodeExif(hFile,EXIF_READ_IMAGE);\r
-               // save back the image, adding EXIF section\r
-               hFile->Seek(pos,SEEK_SET);\r
-               m_exif->EncodeExif(hFile);\r
-       }\r
-#endif\r
-\r
-\r
-       /* And we're done! */\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_JPG\r
-\r
+/*
+ * File:       ximajpg.cpp
+ * Purpose:    Platform Independent JPEG Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+#include "ximajpg.h"
+
+#if CXIMAGE_SUPPORT_JPG
+
+#include "../jpeg/jmorecfg.h"
+
+#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(&m_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(&m_exifinfo);
+       if (m_exif){
+               long pos=hFile->Tell();
+               m_exif->DecodeExif(hFile);
+               hFile->Seek(pos,SEEK_SET);
+               return m_exif->m_exifinfo->IsExif;
+       } else {
+               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 */
+       int 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;
+
+       /* 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);
+       CxFileJpg src(hFile);
+    cinfo.src = &src;
+
+       /* Step 3: read file parameters with jpeg_read_header() */
+       (void) jpeg_read_header(&cinfo, TRUE);
+
+       /* Step 4 <chupeev> handle decoder options*/
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_GRAYSCALE) != 0)
+               cinfo.out_color_space = JCS_GRAYSCALE;
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_QUANTIZE) != 0) {
+               cinfo.quantize_colors = TRUE;
+               cinfo.desired_number_of_colors = GetJpegQuality();
+       }
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_DITHER) != 0)
+               cinfo.dither_mode = m_nDither;
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & DECODE_ONEPASS) != 0)
+               cinfo.two_pass_quantize = FALSE;
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & 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>
+
+       // 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 ((m_exifinfo.Xresolution != 0.0) && (m_exifinfo.ResolutionUnit != 0))
+               SetXDPI((long)(m_exifinfo.Xresolution/m_exifinfo.ResolutionUnit));
+       if ((m_exifinfo.Yresolution != 0.0) && (m_exifinfo.ResolutionUnit != 0))
+               SetYDPI((long)(m_exifinfo.Yresolution/m_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((long)(GetXDPI()*(float(cinfo.Y_density)/float(cinfo.X_density))));
+                       }
+                       break;
+               case 2: // [andy] fix: cinfo.X/Y_density is pixels per centimeter
+                       SetXDPI((long)floor(cinfo.X_density * 2.54 + 0.5));
+                       SetYDPI((long)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 = (long)(100*cinfo.output_scanline/cinfo.output_height);
+               //<DP> Step 6a: CMYK->RGB */ 
+               if ((cinfo.num_components==4)&&(cinfo.quantize_colors==FALSE)){
+                       BYTE k,*dst,*src;
+                       dst=iter.GetRow();
+                       src=buffer[0];
+                       for(long x3=0,x4=0; x3<(long)info.dwEffWidth && x4<row_stride; x3+=3, x4+=4){
+                               k=src[x4+3];
+                               dst[x3]  =(BYTE)((k * src[x4+2])/255);
+                               dst[x3+1]=(BYTE)((k * src[x4+1])/255);
+                               dst[x3+2]=(BYTE)((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)){
+               BYTE* r0=GetBits();
+               for(long 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
+       long 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 long 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 */
+       int 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:
+       */
+
+//#ifdef C_ARITH_CODING_SUPPORTED
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_ARITHMETIC) != 0)
+               cinfo.arith_code = TRUE;
+//#endif
+
+//#ifdef ENTROPY_OPT_SUPPORTED
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_OPTIMIZE) != 0)
+               cinfo.optimize_coding = TRUE;
+//#endif
+
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_GRAYSCALE) != 0)
+               jpeg_set_colorspace(&cinfo, JCS_GRAYSCALE);
+
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_SMOOTHING) != 0)
+               cinfo.smoothing_factor = m_nSmoothing;
+
+       jpeg_set_quality(&cinfo, GetJpegQuality(), (GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_BASELINE) != 0);
+
+//#ifdef C_PROGRESSIVE_SUPPORTED
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & ENCODE_PROGRESSIVE) != 0)
+               jpeg_simple_progression(&cinfo);
+//#endif
+
+#ifdef C_LOSSLESS_SUPPORTED
+       if ((GetCodecOption(CXIMAGE_FORMAT_JPG) & 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 ((GetCodecOption(CXIMAGE_FORMAT_JPG) & 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 ((GetCodecOption(CXIMAGE_FORMAT_JPG) & 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=(unsigned short)GetXDPI();
+       cinfo.Y_density=(unsigned short)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 = (long)(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
+
index 899c6bc123beb2fd3e268809850736faa8b9b7d4..de7835a6d84476a889fb0561d95f8930d71787f5 100644 (file)
-/*\r
- * File:       ximajpg.h\r
- * Purpose:    JPG Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageJPG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes\r
- *\r
- * Special thanks to Chris Shearer Cooper for CxFileJpg tips & code\r
- *\r
- * EXIF support based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>\r
- *\r
- * original CImageJPG  and CImageIterator implementation are:\r
- * Copyright:  (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>\r
- *\r
- * This software is based in part on the work of the Independent JPEG Group.\r
- * Copyright (C) 1991-1998, Thomas G. Lane.\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaJPEG_h)\r
-#define __ximaJPEG_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_JPG\r
-\r
-#define CXIMAGEJPG_SUPPORT_EXIF 1\r
-\r
-extern "C" {\r
- #include "../jpeg/jpeglib.h"\r
- #include "../jpeg/jerror.h"\r
-}\r
-\r
-class DLL_EXP CxImageJPG: public CxImage\r
-{\r
-public:\r
-       CxImageJPG();\r
-       ~CxImageJPG();\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_JPG);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_JPG);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-\r
-/*\r
- * EXIF support based on jhead-1.8 by Matthias Wandel <mwandel(at)rim(dot)net>\r
- */\r
-\r
-#if CXIMAGEJPG_SUPPORT_EXIF\r
-\r
-#define MAX_COMMENT 1000\r
-#define MAX_SECTIONS 20\r
-\r
-typedef struct tag_ExifInfo {\r
-       char  Version      [5];\r
-    char  CameraMake   [32];\r
-    char  CameraModel  [40];\r
-    char  DateTime     [20];\r
-    int   Height, Width;\r
-    int   Orientation;\r
-    int   IsColor;\r
-    int   Process;\r
-    int   FlashUsed;\r
-    float FocalLength;\r
-    float ExposureTime;\r
-    float ApertureFNumber;\r
-    float Distance;\r
-    float CCDWidth;\r
-    float ExposureBias;\r
-    int   Whitebalance;\r
-    int   MeteringMode;\r
-    int   ExposureProgram;\r
-    int   ISOequivalent;\r
-    int   CompressionLevel;\r
-       float FocalplaneXRes;\r
-       float FocalplaneYRes;\r
-       float FocalplaneUnits;\r
-       float Xresolution;\r
-       float Yresolution;\r
-       float ResolutionUnit;\r
-       float Brightness;\r
-    char  Comments[MAX_COMMENT];\r
-\r
-    unsigned char * ThumbnailPointer;  /* Pointer at the thumbnail */\r
-    unsigned ThumbnailSize;     /* Size of thumbnail. */\r
-\r
-       bool  IsExif;\r
-} EXIFINFO;\r
-\r
-//--------------------------------------------------------------------------\r
-// JPEG markers consist of one or more 0xFF bytes, followed by a marker\r
-// code byte (which is not an FF).  Here are the marker codes of interest\r
-// in this program.  (See jdmarker.c for a more complete list.)\r
-//--------------------------------------------------------------------------\r
-\r
-#define M_SOF0  0xC0            // Start Of Frame N\r
-#define M_SOF1  0xC1            // N indicates which compression process\r
-#define M_SOF2  0xC2            // Only SOF0-SOF2 are now in common use\r
-#define M_SOF3  0xC3\r
-#define M_SOF5  0xC5            // NB: codes C4 and CC are NOT SOF markers\r
-#define M_SOF6  0xC6\r
-#define M_SOF7  0xC7\r
-#define M_SOF9  0xC9\r
-#define M_SOF10 0xCA\r
-#define M_SOF11 0xCB\r
-#define M_SOF13 0xCD\r
-#define M_SOF14 0xCE\r
-#define M_SOF15 0xCF\r
-#define M_SOI   0xD8            // Start Of Image (beginning of datastream)\r
-#define M_EOI   0xD9            // End Of Image (end of datastream)\r
-#define M_SOS   0xDA            // Start Of Scan (begins compressed data)\r
-#define M_JFIF  0xE0            // Jfif marker\r
-#define M_EXIF  0xE1            // Exif marker\r
-#define M_COM   0xFE            // COMment \r
-\r
-#define PSEUDO_IMAGE_MARKER 0x123; // Extra value.\r
-\r
-#define EXIF_READ_EXIF  0x01\r
-#define EXIF_READ_IMAGE 0x02\r
-#define EXIF_READ_ALL   0x03\r
-\r
-class DLL_EXP CxExifInfo\r
-{\r
-\r
-typedef struct tag_Section_t{\r
-    BYTE*    Data;\r
-    int      Type;\r
-    unsigned Size;\r
-} Section_t;\r
-\r
-public:\r
-       EXIFINFO* m_exifinfo;\r
-       char m_szLastError[256];\r
-       CxExifInfo(EXIFINFO* info = NULL);\r
-       ~CxExifInfo();\r
-       bool DecodeExif(CxFile * hFile, int nReadMode = EXIF_READ_EXIF);\r
-       bool EncodeExif(CxFile * hFile);\r
-       void DiscardAllButExif();\r
-protected:\r
-       bool process_EXIF(unsigned char * CharBuf, unsigned int length);\r
-       void process_COM (const BYTE * Data, int length);\r
-       void process_SOFn (const BYTE * Data, int marker);\r
-       int Get16u(void * Short);\r
-       int Get16m(void * Short);\r
-       long Get32s(void * Long);\r
-       unsigned long Get32u(void * Long);\r
-       double ConvertAnyFormat(void * ValuePtr, int Format);\r
-       void* FindSection(int SectionType);\r
-       bool ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,\r
-                           EXIFINFO * const pInfo, unsigned char ** const LastExifRefdP, int NestingLevel=0);\r
-       int ExifImageWidth;\r
-       int MotorolaOrder;\r
-       Section_t Sections[MAX_SECTIONS];\r
-       int SectionsRead;\r
-       bool freeinfo;\r
-};\r
-\r
-       CxExifInfo* m_exif;\r
-       EXIFINFO m_exifinfo;\r
-       bool DecodeExif(CxFile * hFile);\r
-       bool DecodeExif(FILE * hFile) { CxIOFile file(hFile); return DecodeExif(&file); }\r
-\r
-#endif //CXIMAGEJPG_SUPPORT_EXIF\r
-\r
-////////////////////////////////////////////////////////////////////////////////////////\r
-//////////////////////        C x F i l e J p g         ////////////////////////////////\r
-////////////////////////////////////////////////////////////////////////////////////////\r
-\r
-// thanks to Chris Shearer Cooper <cscooper(at)frii(dot)com>\r
-class CxFileJpg : public jpeg_destination_mgr, public jpeg_source_mgr\r
-       {\r
-public:\r
-       enum { eBufSize = 4096 };\r
-\r
-       CxFileJpg(CxFile* pFile)\r
-       {\r
-        m_pFile = pFile;\r
-\r
-               init_destination = InitDestination;\r
-               empty_output_buffer = EmptyOutputBuffer;\r
-               term_destination = TermDestination;\r
-\r
-               init_source = InitSource;\r
-               fill_input_buffer = FillInputBuffer;\r
-               skip_input_data = SkipInputData;\r
-               resync_to_restart = jpeg_resync_to_restart; // use default method\r
-               term_source = TermSource;\r
-               next_input_byte = NULL; //* => next byte to read from buffer \r
-               bytes_in_buffer = 0;    //* # of bytes remaining in buffer \r
-\r
-               m_pBuffer = new unsigned char[eBufSize];\r
-       }\r
-       ~CxFileJpg()\r
-       {\r
-               delete [] m_pBuffer;\r
-       }\r
-\r
-       static void InitDestination(j_compress_ptr cinfo)\r
-       {\r
-               CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;\r
-               pDest->next_output_byte = pDest->m_pBuffer;\r
-               pDest->free_in_buffer = eBufSize;\r
-       }\r
-\r
-       static boolean EmptyOutputBuffer(j_compress_ptr cinfo)\r
-       {\r
-               CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;\r
-               if (pDest->m_pFile->Write(pDest->m_pBuffer,1,eBufSize)!=(size_t)eBufSize)\r
-                       ERREXIT(cinfo, JERR_FILE_WRITE);\r
-               pDest->next_output_byte = pDest->m_pBuffer;\r
-               pDest->free_in_buffer = eBufSize;\r
-               return TRUE;\r
-       }\r
-\r
-       static void TermDestination(j_compress_ptr cinfo)\r
-       {\r
-               CxFileJpg* pDest = (CxFileJpg*)cinfo->dest;\r
-               size_t datacount = eBufSize - pDest->free_in_buffer;\r
-               /* Write any data remaining in the buffer */\r
-               if (datacount > 0) {\r
-                       if (!pDest->m_pFile->Write(pDest->m_pBuffer,1,datacount))\r
-                               ERREXIT(cinfo, JERR_FILE_WRITE);\r
-               }\r
-               pDest->m_pFile->Flush();\r
-               /* Make sure we wrote the output file OK */\r
-               if (pDest->m_pFile->Error()) ERREXIT(cinfo, JERR_FILE_WRITE);\r
-               return;\r
-       }\r
-\r
-       static void InitSource(j_decompress_ptr cinfo)\r
-       {\r
-               CxFileJpg* pSource = (CxFileJpg*)cinfo->src;\r
-               pSource->m_bStartOfFile = TRUE;\r
-       }\r
-\r
-       static boolean FillInputBuffer(j_decompress_ptr cinfo)\r
-       {\r
-               size_t nbytes;\r
-               CxFileJpg* pSource = (CxFileJpg*)cinfo->src;\r
-               nbytes = pSource->m_pFile->Read(pSource->m_pBuffer,1,eBufSize);\r
-               if (nbytes <= 0){\r
-                       if (pSource->m_bStartOfFile)    //* Treat empty input file as fatal error \r
-                               ERREXIT(cinfo, JERR_INPUT_EMPTY);\r
-                       WARNMS(cinfo, JWRN_JPEG_EOF);\r
-                       // Insert a fake EOI marker \r
-                       pSource->m_pBuffer[0] = (JOCTET) 0xFF;\r
-                       pSource->m_pBuffer[1] = (JOCTET) JPEG_EOI;\r
-                       nbytes = 2;\r
-               }\r
-               pSource->next_input_byte = pSource->m_pBuffer;\r
-               pSource->bytes_in_buffer = nbytes;\r
-               pSource->m_bStartOfFile = FALSE;\r
-               return TRUE;\r
-       }\r
-\r
-       static void SkipInputData(j_decompress_ptr cinfo, long num_bytes)\r
-       {\r
-               CxFileJpg* pSource = (CxFileJpg*)cinfo->src;\r
-               if (num_bytes > 0){\r
-                       while (num_bytes > (long)pSource->bytes_in_buffer){\r
-                               num_bytes -= (long)pSource->bytes_in_buffer;\r
-                               FillInputBuffer(cinfo);\r
-                               // note we assume that fill_input_buffer will never return FALSE,\r
-                               // so suspension need not be handled.\r
-                       }\r
-                       pSource->next_input_byte += (size_t) num_bytes;\r
-                       pSource->bytes_in_buffer -= (size_t) num_bytes;\r
-               }\r
-       }\r
-\r
-       static void TermSource(j_decompress_ptr /*cinfo*/)\r
-       {\r
-               return;\r
-       }\r
-protected:\r
-    CxFile  *m_pFile;\r
-       unsigned char *m_pBuffer;\r
-       bool m_bStartOfFile;\r
-};\r
-\r
-public:\r
-       enum CODEC_OPTION\r
-       {\r
-               ENCODE_BASELINE = 0x1,\r
-               ENCODE_ARITHMETIC = 0x2,\r
-               ENCODE_GRAYSCALE = 0x4,\r
-               ENCODE_OPTIMIZE = 0x8,\r
-               ENCODE_PROGRESSIVE = 0x10,\r
-               ENCODE_LOSSLESS = 0x20,\r
-               ENCODE_SMOOTHING = 0x40,\r
-               DECODE_GRAYSCALE = 0x80,\r
-               DECODE_QUANTIZE = 0x100,\r
-               DECODE_DITHER = 0x200,\r
-               DECODE_ONEPASS = 0x400,\r
-               DECODE_NOSMOOTH = 0x800,\r
-               ENCODE_SUBSAMPLE_422 = 0x1000,\r
-               ENCODE_SUBSAMPLE_444 = 0x2000\r
-       }; \r
-\r
-       int m_nPredictor;\r
-       int m_nPointTransform;\r
-       int m_nSmoothing;\r
-       int m_nQuantize;\r
-       J_DITHER_MODE m_nDither;\r
-\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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 1
+
+extern "C" {
+ #include "../jpeg/jpeglib.h"
+ #include "../jpeg/jerror.h"
+}
+
+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
+
+#define MAX_COMMENT 1000
+#define MAX_SECTIONS 20
+
+typedef struct tag_ExifInfo {
+       char  Version      [5];
+    char  CameraMake   [32];
+    char  CameraModel  [40];
+    char  DateTime     [20];
+    int   Height, Width;
+    int   Orientation;
+    int   IsColor;
+    int   Process;
+    int   FlashUsed;
+    float FocalLength;
+    float ExposureTime;
+    float ApertureFNumber;
+    float Distance;
+    float CCDWidth;
+    float ExposureBias;
+    int   Whitebalance;
+    int   MeteringMode;
+    int   ExposureProgram;
+    int   ISOequivalent;
+    int   CompressionLevel;
+       float FocalplaneXRes;
+       float FocalplaneYRes;
+       float FocalplaneUnits;
+       float Xresolution;
+       float Yresolution;
+       float ResolutionUnit;
+       float Brightness;
+    char  Comments[MAX_COMMENT];
+
+    unsigned char * ThumbnailPointer;  /* Pointer at the thumbnail */
+    unsigned ThumbnailSize;     /* Size of thumbnail. */
+
+       bool  IsExif;
+} EXIFINFO;
+
+//--------------------------------------------------------------------------
+// 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{
+    BYTE*    Data;
+    int      Type;
+    unsigned Size;
+} Section_t;
+
+public:
+       EXIFINFO* m_exifinfo;
+       char m_szLastError[256];
+       CxExifInfo(EXIFINFO* info = NULL);
+       ~CxExifInfo();
+       bool DecodeExif(CxFile * hFile, int nReadMode = EXIF_READ_EXIF);
+       bool EncodeExif(CxFile * hFile);
+       void DiscardAllButExif();
+protected:
+       bool process_EXIF(unsigned char * CharBuf, unsigned int length);
+       void process_COM (const BYTE * Data, int length);
+       void process_SOFn (const BYTE * Data, int marker);
+       int Get16u(void * Short);
+       int Get16m(void * Short);
+       long Get32s(void * Long);
+       unsigned long Get32u(void * Long);
+       double ConvertAnyFormat(void * ValuePtr, int Format);
+       void* FindSection(int SectionType);
+       bool ProcessExifDir(unsigned char * DirStart, unsigned char * OffsetBase, unsigned ExifLength,
+                           EXIFINFO * const pInfo, unsigned char ** const LastExifRefdP, int NestingLevel=0);
+       int ExifImageWidth;
+       int MotorolaOrder;
+       Section_t Sections[MAX_SECTIONS];
+       int SectionsRead;
+       bool freeinfo;
+};
+
+       CxExifInfo* m_exif;
+       EXIFINFO m_exifinfo;
+       bool DecodeExif(CxFile * hFile);
+       bool DecodeExif(FILE * hFile) { CxIOFile file(hFile); return DecodeExif(&file); }
+
+#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 unsigned char[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 > (long)pSource->bytes_in_buffer){
+                               num_bytes -= (long)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;
+       unsigned char *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
+       }; 
+
+       int m_nPredictor;
+       int m_nPointTransform;
+       int m_nSmoothing;
+       int m_nQuantize;
+       J_DITHER_MODE m_nDither;
+
+};
+
+#endif
+
+#endif
index 8233dcbd58418738663f85b61d9fda505b55c174..823c3cef22c2beb99f8bb29361c760f7fbc1e838 100644 (file)
-// xImalpha.cpp : Alpha channel functions\r
-/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa AlphaSetMax\r
- */\r
-BYTE CxImage::AlphaGetMax() const\r
-{\r
-       return info.nAlphaMax;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets global Alpha (opacity) value applied to the whole image,\r
- * valid only for painting functions.\r
- * \param nAlphaMax: can be from 0 to 255\r
- */\r
-void CxImage::AlphaSetMax(BYTE nAlphaMax)\r
-{\r
-       info.nAlphaMax=nAlphaMax;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if the image has a valid alpha channel.\r
- */\r
-bool CxImage::AlphaIsValid()\r
-{\r
-       return pAlpha!=0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Enables the alpha palette, so the Draw() function changes its behavior.\r
- */\r
-void CxImage::AlphaPaletteEnable(bool enable)\r
-{\r
-       info.bAlphaPaletteEnabled=enable;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * True if the alpha palette is enabled for painting.\r
- */\r
-bool CxImage::AlphaPaletteIsEnabled()\r
-{\r
-       return info.bAlphaPaletteEnabled;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the alpha channel to full transparent. AlphaSet(0) has the same effect\r
- */\r
-void CxImage::AlphaClear()\r
-{\r
-       if (pAlpha)     memset(pAlpha,0,head.biWidth * head.biHeight);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the alpha level for the whole image.\r
- * \param level : from 0 (transparent) to 255 (opaque)\r
- */\r
-void CxImage::AlphaSet(BYTE level)\r
-{\r
-       if (pAlpha)     memset(pAlpha,level,head.biWidth * head.biHeight);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Allocates an empty (opaque) alpha channel.\r
- */\r
-bool CxImage::AlphaCreate()\r
-{\r
-       if (pAlpha==NULL) {\r
-               pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-               if (pAlpha) memset(pAlpha,255,head.biWidth * head.biHeight);\r
-       }\r
-       return (pAlpha!=0);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::AlphaDelete()\r
-{\r
-       if (pAlpha) { free(pAlpha); pAlpha=0; }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::AlphaInvert()\r
-{\r
-       if (pAlpha) {\r
-               BYTE *iSrc=pAlpha;\r
-               long n=head.biHeight*head.biWidth;\r
-               for(long i=0; i < n; i++){\r
-                       *iSrc=(BYTE)~(*(iSrc));\r
-                       iSrc++;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Imports an existing alpa channel from another image with the same width and height.\r
- */\r
-bool CxImage::AlphaCopy(CxImage &from)\r
-{\r
-       if (from.pAlpha == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;\r
-       if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-       if (pAlpha==NULL) return false;\r
-       memcpy(pAlpha,from.pAlpha,head.biWidth * head.biHeight);\r
-       info.nAlphaMax=from.info.nAlphaMax;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Creates the alpha channel from a gray scale image.\r
- */\r
-bool CxImage::AlphaSet(CxImage &from)\r
-{\r
-       if (!from.IsGrayScale() || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;\r
-       if (pAlpha==NULL) pAlpha = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-       BYTE* src = from.info.pImage;\r
-       BYTE* dst = pAlpha;\r
-       if (src==NULL || dst==NULL) return false;\r
-       for (long y=0; y<head.biHeight; y++){\r
-               memcpy(dst,src,head.biWidth);\r
-               dst += head.biWidth;\r
-               src += from.info.dwEffWidth;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the alpha level for a single pixel \r
- */\r
-void CxImage::AlphaSet(const long x,const long y,const BYTE level)\r
-{\r
-       if (pAlpha && IsInside(x,y)) pAlpha[x+y*head.biWidth]=level;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Gets the alpha level for a single pixel \r
- */\r
-BYTE CxImage::AlphaGet(const long x,const long y)\r
-{\r
-       if (pAlpha && IsInside(x,y)) return pAlpha[x+y*head.biWidth];\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns pointer to alpha data for pixel (x,y).\r
- *\r
- * \author ***bd*** 2.2004\r
- */\r
-BYTE* CxImage::AlphaGetPointer(const long x,const long y)\r
-{\r
-       if (pAlpha && IsInside(x,y)) return pAlpha+x+y*head.biWidth;\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Get alpha value without boundscheck (a bit faster). Pixel must be inside the image.\r
- *\r
- * \author ***bd*** 2.2004\r
- */\r
-BYTE CxImage::BlindAlphaGet(const long x,const long y)\r
-{\r
-#ifdef _DEBUG\r
-       if (!IsInside(x,y) || (pAlpha==0))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return 0;\r
-  #endif\r
-#endif\r
-       return pAlpha[x+y*head.biWidth];\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Resets the alpha palette \r
- */\r
-void CxImage::AlphaPaletteClear()\r
-{\r
-       RGBQUAD c;\r
-       for(WORD ip=0; ip<head.biClrUsed;ip++){\r
-               c=GetPaletteColor((BYTE)ip);\r
-               c.rgbReserved=0;\r
-               SetPaletteColor((BYTE)ip,c);\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if the image has a valid alpha palette. \r
- */\r
-bool CxImage::AlphaPaletteIsValid()\r
-{\r
-       RGBQUAD c;\r
-       for(WORD ip=0; ip<head.biClrUsed;ip++){\r
-               c=GetPaletteColor((BYTE)ip);\r
-               if (c.rgbReserved != 0) return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Blends the alpha channel and the alpha palette with the pixels. The result is a 24 bit image.\r
- * The background color can be selected using SetTransColor().\r
- */\r
-void CxImage::AlphaStrip()\r
-{\r
-       bool bAlphaPaletteIsValid = AlphaPaletteIsValid();\r
-       bool bAlphaIsValid = AlphaIsValid();\r
-       if (!(bAlphaIsValid || bAlphaPaletteIsValid)) return;\r
-       RGBQUAD c;\r
-       long a, a1;\r
-       if (head.biBitCount==24){\r
-               for(long y=0; y<head.biHeight; y++){\r
-                       for(long x=0; x<head.biWidth; x++){\r
-                               c = BlindGetPixelColor(x,y);\r
-                               if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;\r
-                               a1 = 256-a;\r
-                               c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);\r
-                               c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);\r
-                               c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);\r
-                               BlindSetPixelColor(x,y,c);\r
-                       }\r
-               }\r
-               AlphaDelete();\r
-       } else {\r
-               CxImage tmp(head.biWidth,head.biHeight,24);\r
-               if (!tmp.IsValid()){\r
-                       strcpy(info.szLastError,tmp.GetLastError());\r
-                       return;\r
-               }\r
-\r
-               for(long y=0; y<head.biHeight; y++){\r
-                       for(long x=0; x<head.biWidth; x++){\r
-                               c = BlindGetPixelColor(x,y);\r
-                               if (bAlphaIsValid) a=(BlindAlphaGet(x,y)*info.nAlphaMax)/255; else a=info.nAlphaMax;\r
-                               if (bAlphaPaletteIsValid) a=(c.rgbReserved*a)/255;\r
-                               a1 = 256-a;\r
-                               c.rgbBlue = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);\r
-                               c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);\r
-                               c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);\r
-                               tmp.BlindSetPixelColor(x,y,c);\r
-                       }\r
-               }\r
-               Transfer(tmp);\r
-       }\r
-       return;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::AlphaFlip()\r
-{\r
-       if (!pAlpha) return false;\r
-\r
-       BYTE *buff = (BYTE*)malloc(head.biWidth);\r
-       if (!buff) return false;\r
-\r
-       BYTE *iSrc,*iDst;\r
-       iSrc = pAlpha + (head.biHeight-1)*head.biWidth;\r
-       iDst = pAlpha;\r
-       for (long i=0; i<(head.biHeight/2); ++i)\r
-       {\r
-               memcpy(buff, iSrc, head.biWidth);\r
-               memcpy(iSrc, iDst, head.biWidth);\r
-               memcpy(iDst, buff, head.biWidth);\r
-               iSrc-=head.biWidth;\r
-               iDst+=head.biWidth;\r
-       }\r
-\r
-       free(buff);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::AlphaMirror()\r
-{\r
-       if (!pAlpha) return false;\r
-       BYTE* pAlpha2 = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-       if (!pAlpha2) return false;\r
-       BYTE *iSrc,*iDst;\r
-       long wdt=head.biWidth-1;\r
-       iSrc=pAlpha + wdt;\r
-       iDst=pAlpha2;\r
-       for(long y=0; y < head.biHeight; y++){\r
-               for(long x=0; x <= wdt; x++)\r
-                       *(iDst+x)=*(iSrc-x);\r
-               iSrc+=head.biWidth;\r
-               iDst+=head.biWidth;\r
-       }\r
-       free(pAlpha);\r
-       pAlpha=pAlpha2;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Exports the alpha channel in a 8bpp grayscale image. \r
- */\r
-bool CxImage::AlphaSplit(CxImage *dest)\r
-{\r
-       if (!pAlpha || !dest) return false;\r
-\r
-       CxImage tmp(head.biWidth,head.biHeight,8);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       tmp.BlindSetPixelIndex(x,y,pAlpha[x+y*head.biWidth]);\r
-               }\r
-       }\r
-\r
-       tmp.SetGrayPalette();\r
-       dest->Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Exports the alpha palette channel in a 8bpp grayscale image. \r
- */\r
-bool CxImage::AlphaPaletteSplit(CxImage *dest)\r
-{\r
-       if (!AlphaPaletteIsValid() || !dest) return false;\r
-\r
-       CxImage tmp(head.biWidth,head.biHeight,8);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       tmp.BlindSetPixelIndex(x,y,BlindGetPixelColor(x,y).rgbReserved);\r
-               }\r
-       }\r
-\r
-       tmp.SetGrayPalette();\r
-       dest->Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Merge in the alpha layer the transparent color mask\r
- * (previously set with SetTransColor or SetTransIndex) \r
- */\r
-bool CxImage::AlphaFromTransparency()\r
-{\r
-       if (!IsValid() || !IsTransparent())\r
-               return false;\r
-\r
-       AlphaCreate();\r
-\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       if (IsTransparent(x,y)){\r
-                               AlphaSet(x,y,0);\r
-                       }\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
+// xImalpha.cpp : Alpha channel functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_ALPHA
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \sa AlphaSetMax
+ */
+BYTE 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(BYTE 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(BYTE level)
+{
+       if (pAlpha)     memset(pAlpha,level,head.biWidth * head.biHeight);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Allocates an empty (opaque) alpha channel.
+ */
+bool CxImage::AlphaCreate()
+{
+       if (pAlpha==NULL) {
+               pAlpha = (BYTE*)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) {
+               BYTE *iSrc=pAlpha;
+               long n=head.biHeight*head.biWidth;
+               for(long i=0; i < n; i++){
+                       *iSrc=(BYTE)~(*(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 = (BYTE*)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 = (BYTE*)malloc(head.biWidth * head.biHeight);
+       BYTE* src = from.info.pImage;
+       BYTE* dst = pAlpha;
+       if (src==NULL || dst==NULL) return false;
+       for (long 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 long x,const long y,const BYTE level)
+{
+       if (pAlpha && IsInside(x,y)) pAlpha[x+y*head.biWidth]=level;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the alpha level for a single pixel 
+ */
+BYTE CxImage::AlphaGet(const long x,const long 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
+ */
+BYTE* CxImage::AlphaGetPointer(const long x,const long 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
+ */
+BYTE CxImage::BlindAlphaGet(const long x,const long 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(WORD ip=0; ip<head.biClrUsed;ip++){
+               c=GetPaletteColor((BYTE)ip);
+               c.rgbReserved=0;
+               SetPaletteColor((BYTE)ip,c);
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the image has a valid alpha palette. 
+ */
+bool CxImage::AlphaPaletteIsValid()
+{
+       RGBQUAD c;
+       for(WORD ip=0; ip<head.biClrUsed;ip++){
+               c=GetPaletteColor((BYTE)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;
+       long a, a1;
+       if (head.biBitCount==24){
+               for(long y=0; y<head.biHeight; y++){
+                       for(long 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 = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);
+                               c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);
+                               c.rgbRed = (BYTE)((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(long y=0; y<head.biHeight; y++){
+                       for(long 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 = (BYTE)((c.rgbBlue * a + a1 * info.nBkgndColor.rgbBlue)>>8);
+                               c.rgbGreen = (BYTE)((c.rgbGreen * a + a1 * info.nBkgndColor.rgbGreen)>>8);
+                               c.rgbRed = (BYTE)((c.rgbRed * a + a1 * info.nBkgndColor.rgbRed)>>8);
+                               tmp.BlindSetPixelColor(x,y,c);
+                       }
+               }
+               Transfer(tmp);
+       }
+       return;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::AlphaFlip()
+{
+       if (!pAlpha) return false;
+
+       BYTE *buff = (BYTE*)malloc(head.biWidth);
+       if (!buff) return false;
+
+       BYTE *iSrc,*iDst;
+       iSrc = pAlpha + (head.biHeight-1)*head.biWidth;
+       iDst = pAlpha;
+       for (long 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;
+       BYTE* pAlpha2 = (BYTE*)malloc(head.biWidth * head.biHeight);
+       if (!pAlpha2) return false;
+       BYTE *iSrc,*iDst;
+       long wdt=head.biWidth-1;
+       iSrc=pAlpha + wdt;
+       iDst=pAlpha2;
+       for(long y=0; y < head.biHeight; y++){
+               for(long 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;
+       }
+
+       for(long y=0; y<head.biHeight; y++){
+               for(long x=0; x<head.biWidth; x++){
+                       tmp.BlindSetPixelIndex(x,y,pAlpha[x+y*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(long y=0; y<head.biHeight; y++){
+               for(long 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(long y=0; y<head.biHeight; y++){
+               for(long x=0; x<head.biWidth; x++){
+                       if (IsTransparent(x,y)){
+                               AlphaSet(x,y,0);
+                       }
+               }
+       }
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_ALPHA
index 0b409c2ee9a56a090444395760a15c5deec0e092..18363639849f22b500a63785bb667777ad58ef57 100644 (file)
-// xImaLyr.cpp : Layers functions\r
-/* 21/04/2003 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_LAYERS\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * If the object is an internal layer, GetParent return its parent in the hierarchy.\r
- */\r
-CxImage* CxImage::GetParent() const\r
-{\r
-       return info.pParent;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Number of layers allocated directly by the object.\r
- */\r
-long CxImage::GetNumLayers() const\r
-{\r
-       return info.nNumLayers;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Creates an empty layer. If position is less than 0, the new layer will be placed in the last position\r
- */\r
-bool CxImage::LayerCreate(long position)\r
-{\r
-       if ( position < 0 || position > info.nNumLayers ) position = info.nNumLayers;\r
-\r
-       CxImage** ptmp = new CxImage*[info.nNumLayers + 1];\r
-       if (ptmp==0) return false;\r
-\r
-       int i=0;\r
-       for (int n=0; n<info.nNumLayers; n++){\r
-               if (position == n){\r
-                       ptmp[n] = new CxImage();\r
-                       i=1;\r
-               }\r
-               ptmp[n+i]=ppLayers[n];\r
-       }\r
-       if (i==0) ptmp[info.nNumLayers] = new CxImage();\r
-\r
-       if (ptmp[position]){\r
-               ptmp[position]->info.pParent = this;\r
-       } else {\r
-               free(ptmp);\r
-               return false;\r
-       }\r
-\r
-       info.nNumLayers++;\r
-       delete [] ppLayers;\r
-       ppLayers = ptmp;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Deletes a layer. If position is less than 0, the last layer will be deleted\r
- */\r
-bool CxImage::LayerDelete(long position)\r
-{\r
-       if ( position >= info.nNumLayers ) return false;\r
-       if ( position < 0) position = info.nNumLayers - 1;\r
-       if ( position < 0) return false;\r
-\r
-       if (info.nNumLayers>1){\r
-\r
-               CxImage** ptmp = new CxImage*[info.nNumLayers - 1];\r
-               if (ptmp==0) return false;\r
-\r
-               int i=0;\r
-               for (int n=0; n<info.nNumLayers; n++){\r
-                       if (position == n){\r
-                               delete ppLayers[n];\r
-                               i=1;\r
-                       }\r
-                       ptmp[n]=ppLayers[n+i];\r
-               }\r
-\r
-               info.nNumLayers--;\r
-               delete [] ppLayers;\r
-               ppLayers = ptmp;\r
-\r
-       } else {\r
-               delete ppLayers[0];\r
-               delete [] ppLayers;\r
-               ppLayers = 0;\r
-               info.nNumLayers = 0;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::LayerDeleteAll()\r
-{\r
-       if (ppLayers) { \r
-               for(long n=0; n<info.nNumLayers;n++){ delete ppLayers[n]; }\r
-               delete [] ppLayers; ppLayers=0; info.nNumLayers = 0;\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns a pointer to a layer. If position is less than 0, the last layer will be returned\r
- */\r
-CxImage* CxImage::GetLayer(long position)\r
-{\r
-       if ( ppLayers == NULL) return NULL;\r
-       if ( info.nNumLayers == 0) return NULL;\r
-       if ( position >= info.nNumLayers ) return NULL;\r
-       if ( position < 0) position = info.nNumLayers - 1;\r
-       return ppLayers[position];\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_LAYERS\r
+// xImaLyr.cpp : Layers functions
+/* 21/04/2003 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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.
+ */
+long 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(long position)
+{
+       if ( position < 0 || position > info.nNumLayers ) position = info.nNumLayers;
+
+       CxImage** ptmp = new CxImage*[info.nNumLayers + 1];
+       if (ptmp==0) return false;
+
+       int i=0;
+       for (int 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(long 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;
+
+               int i=0;
+               for (int 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(long 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(long 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
index cc86f4e600e1df09faa8fe7881a34c3108647841..865c49003c317035a30b31910504d187c5031531 100644 (file)
-/*\r
- * File:       ximamng.cpp\r
- * Purpose:    Platform Independent MNG Image Class Loader and Writer\r
- * Author:     07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximamng.h"\r
-\r
-#if CXIMAGE_SUPPORT_MNG\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// callbacks for the mng decoder:\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// memory allocation; data must be zeroed\r
-static mng_ptr\r
-mymngalloc( mng_uint32 size )\r
-{\r
-       return (mng_ptr)calloc(1, size);\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// memory deallocation\r
-static void mymngfree(mng_ptr p, mng_uint32 size)\r
-{\r
-       free(p);\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Stream open/close:\r
-// since the user is responsible for opening and closing the file,\r
-// we leave the default implementation open\r
-static mng_bool mymngopenstream(mng_handle mng)      { return MNG_TRUE; }\r
-static mng_bool mymngopenstreamwrite(mng_handle mng) { return MNG_TRUE; }\r
-static mng_bool mymngclosestream(mng_handle mng)     { return MNG_TRUE; }\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// feed data to the decoder\r
-static mng_bool mymngreadstream(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread)\r
-{\r
-       mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);\r
-       // read the requested amount of data from the file\r
-       *bytesread = mymng->file->Read( buffer, sizeof(BYTE), size);\r
-       return MNG_TRUE;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-static mng_bool mymngwritestream (mng_handle mng, mng_ptr pBuf, mng_uint32 iSize, mng_uint32 *iWritten)\r
-{\r
-       mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);\r
-       // write it\r
-       *iWritten = mymng->file->Write (pBuf, 1, iSize);\r
-       return MNG_TRUE;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// the header's been read. set up the display stuff\r
-static mng_bool mymngprocessheader( mng_handle mng, mng_uint32 width, mng_uint32 height )\r
-{\r
-       // normally the image buffer is allocated here,\r
-       // but in this module we don't know nothing about\r
-       // the final environment.\r
-\r
-       mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);\r
-       \r
-       mymng->width  = width;\r
-       mymng->height = height;\r
-       mymng->bpp    = 24;\r
-       mymng->effwdt = ((((width * mymng->bpp) + 31) >> 5) << 2);\r
-\r
-       if (mng->bUseBKGD){\r
-               mymng->nBkgndIndex = 0;\r
-               mymng->nBkgndColor.rgbRed  = mng->iBGred >> 8;\r
-               mymng->nBkgndColor.rgbGreen =mng->iBGgreen >> 8;\r
-               mymng->nBkgndColor.rgbBlue = mng->iBGblue >> 8;\r
-       }\r
-\r
-       mymng->image = (BYTE*)malloc(height * mymng->effwdt);\r
-\r
-       // tell the mng decoder about our bit-depth choice\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       mng_set_canvasstyle( mng, MNG_CANVAS_RGB8_A8 );\r
-       mymng->alpha = (BYTE*)malloc(height * width);\r
-#else\r
-       mng_set_canvasstyle( mng, MNG_CANVAS_BGR8);\r
-       mymng->alpha = NULL;\r
-#endif\r
-       return MNG_TRUE;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// return a row pointer for the decoder to fill\r
-static mng_ptr mymnggetcanvasline( mng_handle mng, mng_uint32 line )\r
-{\r
-       mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);\r
-       return (mng_ptr)(mymng->image + (mymng->effwdt * (mymng->height - 1 - line)));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// return a row pointer for the decoder to fill for alpha channel\r
-static mng_ptr mymnggetalphaline( mng_handle mng, mng_uint32 line )\r
-{\r
-       mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);\r
-       return (mng_ptr)(mymng->alpha + (mymng->width * (mymng->height - 1 - line)));\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// timer\r
-static mng_uint32 mymnggetticks(mng_handle mng)\r
-{\r
-#ifdef WIN32\r
-       return (mng_uint32)GetTickCount();\r
-#else\r
-  return 0;\r
-#endif\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Refresh: actual frame need to be updated (Invalidate)\r
-static mng_bool mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)\r
-{\r
-//     mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);\r
-       return MNG_TRUE;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// interframe delay callback\r
-static mng_bool mymngsettimer(mng_handle mng, mng_uint32 msecs)\r
-{\r
-       mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);\r
-       mymng->delay = msecs;   // set the timer for when the decoder wants to be woken\r
-       return MNG_TRUE;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-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)\r
-{\r
-       return mng_cleanup(&mng); //<Arkadiy Olovyannikov>\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// CxImage members\r
-////////////////////////////////////////////////////////////////////////////////\r
-CxImageMNG::CxImageMNG(): CxImage(CXIMAGE_FORMAT_MNG)\r
-{\r
-       hmng = NULL;\r
-       memset(&mnginfo,0,sizeof(mngstuff));\r
-       mnginfo.nBkgndIndex = -1;\r
-       mnginfo.speed = 1.0f;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-CxImageMNG::~CxImageMNG()\r
-{\r
-       // cleanup and return\r
-       if (mnginfo.thread){ //close the animation thread\r
-               mnginfo.animation_enabled=0;\r
-               ResumeThread(mnginfo.thread);\r
-               WaitForSingleObject(mnginfo.thread,500);\r
-               CloseHandle(mnginfo.thread);\r
-       }\r
-       // free objects\r
-       if (mnginfo.image) free(mnginfo.image);\r
-       if (mnginfo.alpha) free(mnginfo.alpha);\r
-       if (hmng) mng_cleanup(&hmng); //be sure it's not needed any more. (active timers ?)\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageMNG::SetCallbacks(mng_handle mng)\r
-{\r
-       // set the callbacks\r
-       mng_setcb_errorproc(mng, mymngerror);\r
-       mng_setcb_openstream(mng, mymngopenstream);\r
-       mng_setcb_closestream(mng, mymngclosestream);\r
-       mng_setcb_readdata(mng, mymngreadstream);\r
-       mng_setcb_processheader(mng, mymngprocessheader);\r
-       mng_setcb_getcanvasline(mng, mymnggetcanvasline);\r
-       mng_setcb_refresh(mng, mymngrefresh);\r
-       mng_setcb_gettickcount(mng, mymnggetticks);\r
-       mng_setcb_settimer(mng, mymngsettimer);\r
-       mng_setcb_refresh(mng, mymngrefresh);\r
-       mng_setcb_getalphaline(mng, mymnggetalphaline);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// can't use the CxImage implementation because it looses mnginfo\r
-bool CxImageMNG::Load(const TCHAR * imageFileName){\r
-       FILE* hFile;    //file handle to read the image\r
-#ifdef WIN32\r
-       if ((hFile=_tfopen(imageFileName,_T("rb")))==NULL)  return false;       // For UNICODE support\r
-#else\r
-       if ((hFile=fopen(imageFileName,"rb"))==NULL)  return false;\r
-#endif\r
-       bool bOK = Decode(hFile);\r
-       fclose(hFile);\r
-       return bOK;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageMNG::Decode(CxFile *hFile)\r
-{\r
-       if (hFile == NULL) return false;\r
-\r
-       cx_try\r
-       {\r
-               // set up the mng decoder for our stream\r
-               hmng = mng_initialize(&mnginfo, mymngalloc, mymngfree, MNG_NULL);\r
-               if (hmng == NULL) cx_throw("could not initialize libmng");                      \r
-\r
-               // set the file we want to play\r
-               mnginfo.file = hFile;\r
-\r
-               // Set the colorprofile, lcms uses this:\r
-               mng_set_srgb(hmng, MNG_TRUE );\r
-               // Set white as background color:\r
-               WORD Red,Green,Blue;\r
-               Red = Green = Blue = (255 << 8) + 255;\r
-               mng_set_bgcolor(hmng, Red, Green, Blue );\r
-               // If PNG Background is available, use it:\r
-               mng_set_usebkgd(hmng, MNG_TRUE );\r
-\r
-               // No need to store chunks:\r
-               mng_set_storechunks(hmng, MNG_FALSE);\r
-               // No need to wait: straight reading\r
-               mng_set_suspensionmode(hmng, MNG_FALSE);\r
-\r
-               SetCallbacks(hmng);\r
-\r
-               mng_datap pData = (mng_datap)hmng;\r
-\r
-               // read in the image\r
-               info.nNumFrames=0;\r
-               int retval=MNG_NOERROR;\r
-\r
-               retval = mng_readdisplay(hmng);\r
-\r
-               if (retval != MNG_NOERROR && retval != MNG_NEEDTIMERWAIT){\r
-                       mng_store_error(hmng,retval,0,0);\r
-                       if (hmng->zErrortext){\r
-                               cx_throw(hmng->zErrortext);\r
-                       } else {\r
-                               cx_throw("Error in MNG file");\r
-                       }\r
-               }\r
-\r
-               if (info.nEscape == -1) {\r
-                       // Return output dimensions only\r
-                       head.biWidth = hmng->iWidth;\r
-                       head.biHeight = hmng->iHeight;\r
-                       info.dwType = CXIMAGE_FORMAT_MNG;\r
-                       return true;\r
-               }\r
-\r
-               // read all\r
-               while(pData->bReading){\r
-                       retval = mng_display_resume(hmng);\r
-                       info.nNumFrames++;\r
-               }\r
-\r
-               // single frame check:\r
-               if (retval != MNG_NEEDTIMERWAIT){\r
-                       info.nNumFrames--;\r
-               } else {\r
-                       mnginfo.animation=1;\r
-               }\r
-\r
-               if (info.nNumFrames<=0) info.nNumFrames=1;\r
-\r
-               if (mnginfo.animation_enabled==0){\r
-                       // select the frame\r
-                       if (info.nFrame>=0 && info.nFrame<info.nNumFrames){\r
-                               for (int n=0;n<info.nFrame;n++) mng_display_resume(hmng);\r
-                       } else cx_throw("Error: frame not present in MNG file");\r
-               }\r
-\r
-               if (mnginfo.nBkgndIndex >= 0){\r
-                       info.nBkgndIndex = mnginfo.nBkgndIndex;\r
-                       info.nBkgndColor.rgbRed = mnginfo.nBkgndColor.rgbRed;\r
-                       info.nBkgndColor.rgbGreen = mnginfo.nBkgndColor.rgbGreen;\r
-                       info.nBkgndColor.rgbBlue = mnginfo.nBkgndColor.rgbBlue;\r
-               }\r
-\r
-               //store the newly created image\r
-               if (Create(mnginfo.width,mnginfo.height,mnginfo.bpp, CXIMAGE_FORMAT_MNG)){\r
-                       memcpy(GetBits(), mnginfo.image, info.dwEffWidth * head.biHeight);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       SwapRGB2BGR();\r
-                       AlphaCreate();\r
-                       if(AlphaIsValid() && mnginfo.alpha){\r
-                               memcpy(AlphaGetPointer(),mnginfo.alpha,mnginfo.width * mnginfo.height);\r
-                       }\r
-#endif\r
-               } else cx_throw("CxImageMNG::Decode cannot create image");\r
-\r
-\r
-       } cx_catch {\r
-               if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-               return false;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageMNG::Encode(CxFile *hFile)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       cx_try\r
-       {\r
-               if (head.biClrUsed != 0) cx_throw("MNG encoder can save only RGB images");\r
-               // set the file we want to play\r
-               mnginfo.file = hFile;\r
-               mnginfo.bpp = head.biBitCount;\r
-               mnginfo.effwdt = info.dwEffWidth;\r
-               mnginfo.height = head.biHeight;\r
-               mnginfo.width =  head.biWidth;\r
-\r
-               mnginfo.image = (BYTE*)malloc(head.biSizeImage);\r
-               if (mnginfo.image == NULL) cx_throw("could not allocate memory for MNG");\r
-               memcpy(mnginfo.image,info.pImage, head.biSizeImage);\r
-\r
-               // set up the mng decoder for our stream\r
-               hmng = mng_initialize(&mnginfo, mymngalloc, mymngfree, MNG_NULL);\r
-               if (hmng == NULL) cx_throw("could not initialize libmng");                      \r
-\r
-               mng_setcb_openstream(hmng, mymngopenstreamwrite );\r
-               mng_setcb_closestream(hmng, mymngclosestream);\r
-               mng_setcb_writedata(hmng, mymngwritestream);\r
-\r
-               // Write File:\r
-               mng_create(hmng);\r
-               // Just a single Frame (save a normal PNG):\r
-               WritePNG(hmng, 0, 1 );\r
-               // Now write file:\r
-               mng_write(hmng);\r
-\r
-       } cx_catch {\r
-               if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-               return false;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Writes a single PNG datastream\r
-void CxImageMNG::WritePNG( mng_handle hMNG, int Frame, int FrameCount )\r
-{\r
-       mngstuff *mymng = (mngstuff *)mng_get_userdata(hMNG);\r
-       \r
-       int OffsetX=0,OffsetY=0,OffsetW=mymng->width,OffsetH=mymng->height;\r
-\r
-       BYTE *tmpbuffer = new BYTE[ (mymng->effwdt+1) * mymng->height];\r
-       if( tmpbuffer == 0 ) return;\r
-\r
-       // Write DEFI chunk.\r
-       mng_putchunk_defi( hMNG, 0, 0, 0, MNG_TRUE, OffsetX, OffsetY, MNG_FALSE, 0, 0, 0, 0 );\r
-                \r
-       // Write Header:\r
-       mng_putchunk_ihdr(\r
-               hMNG, \r
-               OffsetW, OffsetH, \r
-               MNG_BITDEPTH_8, \r
-               MNG_COLORTYPE_RGB, \r
-               MNG_COMPRESSION_DEFLATE, \r
-               MNG_FILTER_ADAPTIVE, \r
-               MNG_INTERLACE_NONE \r
-       );\r
-\r
-       // transfer data, add Filterbyte:\r
-       for( int Row=0; Row<OffsetH; Row++ ){\r
-               // First Byte in each Scanline is Filterbyte: Currently 0 -> No Filter.\r
-               tmpbuffer[Row*(mymng->effwdt+1)]=0; \r
-               // Copy the scanline: (reverse order)\r
-               memcpy(tmpbuffer+Row*(mymng->effwdt+1)+1, \r
-                       mymng->image+((OffsetH-1-(OffsetY+Row))*(mymng->effwdt))+OffsetX,mymng->effwdt);\r
-               // swap red and blue components\r
-               RGBtoBGR(tmpbuffer+Row*(mymng->effwdt+1)+1,mymng->effwdt);\r
-       } \r
-\r
-       // Compress data with ZLib (Deflate):\r
-       BYTE *dstbuffer = new BYTE[(mymng->effwdt+1)*OffsetH];\r
-       if( dstbuffer == 0 ) return;\r
-       DWORD dstbufferSize=(mymng->effwdt+1)*OffsetH;\r
-\r
-       // Compress data:\r
-       if(Z_OK != compress2((Bytef *)dstbuffer,(ULONG *)&dstbufferSize,(const Bytef*)tmpbuffer,\r
-                                               (ULONG) (mymng->effwdt+1)*OffsetH,9 )) return;\r
-\r
-       // Write Data into MNG File:\r
-       mng_putchunk_idat( hMNG, dstbufferSize, (mng_ptr*)dstbuffer);\r
-       mng_putchunk_iend(hMNG);\r
-\r
-       // Free the stuff:\r
-       delete [] tmpbuffer;\r
-       delete [] dstbuffer;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImageMNG::Resume()\r
-{\r
-       if (MNG_NEEDTIMERWAIT == mng_display_resume(hmng)){\r
-               if (info.pImage==NULL){\r
-                       Create(mnginfo.width,mnginfo.height,mnginfo.bpp, CXIMAGE_FORMAT_MNG);\r
-               }\r
-               if (IsValid()){\r
-                       memcpy(GetBits(), mnginfo.image, info.dwEffWidth * head.biHeight);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       SwapRGB2BGR();\r
-                       AlphaCreate();\r
-                       if(AlphaIsValid() && mnginfo.alpha){\r
-                               memcpy(AlphaGetPointer(),mnginfo.alpha,mnginfo.width * mnginfo.height);\r
-                       }\r
-#endif\r
-               }\r
-       } else {\r
-               mnginfo.animation_enabled = 0;\r
-       }\r
-       return mnginfo.animation_enabled;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageMNG::SetSpeed(float speed)\r
-{\r
-       if (speed>10.0) mnginfo.speed = 10.0f;\r
-       else if (speed<0.1) mnginfo.speed = 0.1f;\r
-       else mnginfo.speed=speed;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_MNG\r
+/*
+ * File:       ximamng.cpp
+ * Purpose:    Platform Independent MNG Image Class Loader and Writer
+ * Author:     07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximamng.h"
+
+#if CXIMAGE_SUPPORT_MNG
+
+////////////////////////////////////////////////////////////////////////////////
+// callbacks for the mng decoder:
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+// memory allocation; data must be zeroed
+static mng_ptr
+mymngalloc( mng_uint32 size )
+{
+       return (mng_ptr)calloc(1, size);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// memory deallocation
+static void mymngfree(mng_ptr p, mng_uint32 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(BYTE), 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 = (BYTE*)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 = (BYTE*)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, mymngalloc, 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:
+               WORD 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;
+               int 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 (int 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 = (BYTE*)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, mymngalloc, 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, int Frame, int FrameCount )
+{
+       mngstuff *mymng = (mngstuff *)mng_get_userdata(hMNG);
+       
+       int OffsetX=0,OffsetY=0,OffsetW=mymng->width,OffsetH=mymng->height;
+
+       BYTE *tmpbuffer = new BYTE[ (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( int 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):
+       BYTE *dstbuffer = new BYTE[(mymng->effwdt+1)*OffsetH];
+       if( dstbuffer == 0 ) return;
+       DWORD 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;
+}
+////////////////////////////////////////////////////////////////////////////////
+long 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
index adc922ca2ac0323c16fbe68e912d82667a4cb8fc..86c05c3977d91cbcdeb9bc1e38a5e12873b7bb59 100644 (file)
@@ -1,88 +1,88 @@
-/*\r
- * File:       ximamng.h\r
- * Purpose:    Declaration of the MNG Image Class\r
- * Author:     Davide Pizzolato - www.xdp.it\r
- * Created:    2001\r
- */\r
-/* ==========================================================\r
- * CxImageMNG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * Special thanks to Frank Haug <f.haug(at)jdm(dot)de> for suggestions and code.\r
- *\r
- * original mng.cpp code created by Nikolaus Brennig, November 14th, 2000. <virtualnik(at)nol(dot)at>\r
- *\r
- * LIBMNG Copyright (c) 2000,2001 Gerard Juyn (gerard@libmng.com)\r
- * ==========================================================\r
- */\r
-\r
-#if !defined(__ximaMNG_h)\r
-#define __ximaMNG_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_MNG\r
-\r
-//#define MNG_NO_CMS\r
-#define MNG_SUPPORT_DISPLAY\r
-#define MNG_SUPPORT_READ\r
-#define        MNG_SUPPORT_WRITE\r
-#define MNG_ACCESS_CHUNKS\r
-#define MNG_STORE_CHUNKS\r
-\r
-extern "C" {\r
-#include "../mng/libmng.h"\r
-#include "../mng/libmng_data.h"\r
-#include "../mng/libmng_error.h"\r
-}\r
-\r
-//unsigned long _stdcall RunMNGThread(void *lpParam);\r
-\r
-typedef struct tagmngstuff \r
-{\r
-       CxFile          *file;\r
-       BYTE            *image;\r
-       BYTE            *alpha;\r
-       HANDLE          thread;\r
-       mng_uint32      delay;\r
-       mng_uint32  width;\r
-       mng_uint32  height;\r
-       mng_uint32  effwdt;\r
-       mng_int16       bpp;\r
-       mng_bool        animation;\r
-       mng_bool        animation_enabled;\r
-       float           speed;\r
-       long            nBkgndIndex;\r
-       RGBQUAD         nBkgndColor;\r
-} mngstuff;\r
-\r
-class CxImageMNG: public CxImage\r
-{\r
-public:\r
-       CxImageMNG();\r
-       ~CxImageMNG();\r
-\r
-       bool Load(const TCHAR * imageFileName);\r
-\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-       bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_MNG);}\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-\r
-       long Resume();\r
-       void SetSpeed(float speed);\r
-       \r
-       mng_handle hmng;\r
-       mngstuff mnginfo;\r
-protected:\r
-       void WritePNG(mng_handle hMNG, int Frame, int FrameCount );\r
-       void SetCallbacks(mng_handle mng);\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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"
+}
+
+//unsigned long _stdcall RunMNGThread(void *lpParam);
+
+typedef struct tagmngstuff 
+{
+       CxFile          *file;
+       BYTE            *image;
+       BYTE            *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;
+       long            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
+
+       long Resume();
+       void SetSpeed(float speed);
+       
+       mng_handle hmng;
+       mngstuff mnginfo;
+protected:
+       void WritePNG(mng_handle hMNG, int Frame, int FrameCount );
+       void SetCallbacks(mng_handle mng);
+};
+
+#endif
+
+#endif
index f7de9eb73768c654eb50a3bc58f3caad01ede1b5..b3bd3da39a5b7b0c50043d9725246328b2103aba 100644 (file)
-// xImaPal.cpp : Palette and Pixel functions\r
-/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * returns the palette dimension in byte\r
- */\r
-DWORD CxImage::GetPaletteSize()\r
-{\r
-       return (head.biClrUsed * sizeof(RGBQUAD));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha)\r
-{\r
-       if ((pDib)&&(head.biClrUsed)){\r
-               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-               if (idx<head.biClrUsed){\r
-                       long ldx=idx*sizeof(RGBQUAD);\r
-                       iDst[ldx++] = (BYTE) b;\r
-                       iDst[ldx++] = (BYTE) g;\r
-                       iDst[ldx++] = (BYTE) r;\r
-                       iDst[ldx] = (BYTE) alpha;\r
-                       info.last_c_isvalid = false;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPaletteColor(BYTE idx, RGBQUAD c)\r
-{\r
-       if ((pDib)&&(head.biClrUsed)){\r
-               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-               if (idx<head.biClrUsed){\r
-                       long ldx=idx*sizeof(RGBQUAD);\r
-                       iDst[ldx++] = (BYTE) c.rgbBlue;\r
-                       iDst[ldx++] = (BYTE) c.rgbGreen;\r
-                       iDst[ldx++] = (BYTE) c.rgbRed;\r
-                       iDst[ldx] = (BYTE) c.rgbReserved;\r
-                       info.last_c_isvalid = false;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPaletteColor(BYTE idx, COLORREF cr)\r
-{\r
-       if ((pDib)&&(head.biClrUsed)){\r
-               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-               if (idx<head.biClrUsed){\r
-                       long ldx=idx*sizeof(RGBQUAD);\r
-                       iDst[ldx++] = (BYTE) GetBValue(cr);\r
-                       iDst[ldx++] = (BYTE) GetGValue(cr);\r
-                       iDst[ldx++] = (BYTE) GetRValue(cr);\r
-                       iDst[ldx] = (BYTE) 0;\r
-                       info.last_c_isvalid = false;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * returns the pointer to the first palette index\r
- */\r
-RGBQUAD* CxImage::GetPalette() const\r
-{\r
-       if ((pDib)&&(head.biClrUsed))\r
-               return (RGBQUAD*)((BYTE*)pDib + sizeof(BITMAPINFOHEADER));\r
-       return NULL;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns the color of the specified index.\r
- */\r
-RGBQUAD CxImage::GetPaletteColor(BYTE idx)\r
-{\r
-       RGBQUAD rgb = {0,0,0,0};\r
-       if ((pDib)&&(head.biClrUsed)){\r
-               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-               if (idx<head.biClrUsed){\r
-                       long ldx=idx*sizeof(RGBQUAD);\r
-                       rgb.rgbBlue = iDst[ldx++];\r
-                       rgb.rgbGreen=iDst[ldx++];\r
-                       rgb.rgbRed =iDst[ldx++];\r
-                       rgb.rgbReserved = iDst[ldx];\r
-               }\r
-       }\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns the palette index of the specified pixel.\r
- */\r
-BYTE CxImage::GetPixelIndex(long x,long y)\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)) return 0;\r
-\r
-       if ((x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) {\r
-               if (info.nBkgndIndex >= 0)      return (BYTE)info.nBkgndIndex;\r
-               else return *info.pImage;\r
-       }\r
-       if (head.biBitCount==8){\r
-               return info.pImage[y*info.dwEffWidth + x];\r
-       } else {\r
-               BYTE pos;\r
-               BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];\r
-               if (head.biBitCount==4){\r
-                       pos = (BYTE)(4*(1-x%2));\r
-                       iDst &= (0x0F<<pos);\r
-                       return (BYTE)(iDst >> pos);\r
-               } else if (head.biBitCount==1){\r
-                       pos = (BYTE)(7-x%8);\r
-                       iDst &= (0x01<<pos);\r
-                       return (BYTE)(iDst >> pos);\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-BYTE CxImage::BlindGetPixelIndex(const long x,const long y)\r
-{\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL) || (head.biClrUsed==0) || !IsInside(x,y))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return 0;\r
-  #endif\r
-#endif\r
-\r
-       if (head.biBitCount==8){\r
-               return info.pImage[y*info.dwEffWidth + x];\r
-       } else {\r
-               BYTE pos;\r
-               BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];\r
-               if (head.biBitCount==4){\r
-                       pos = (BYTE)(4*(1-x%2));\r
-                       iDst &= (0x0F<<pos);\r
-                       return (BYTE)(iDst >> pos);\r
-               } else if (head.biBitCount==1){\r
-                       pos = (BYTE)(7-x%8);\r
-                       iDst &= (0x01<<pos);\r
-                       return (BYTE)(iDst >> pos);\r
-               }\r
-       }\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::GetPixelColor(long x,long y, bool bGetAlpha)\r
-{\r
-//     RGBQUAD rgb={0,0,0,0};\r
-       RGBQUAD rgb=info.nBkgndColor; //<mpwolski>\r
-       if ((pDib==NULL)||(x<0)||(y<0)||\r
-               (x>=head.biWidth)||(y>=head.biHeight)){\r
-               if (info.nBkgndIndex >= 0){\r
-                       if (head.biBitCount<24) return GetPaletteColor((BYTE)info.nBkgndIndex);\r
-                       else return info.nBkgndColor;\r
-               } else if (pDib) return GetPixelColor(0,0);\r
-               return rgb;\r
-       }\r
-\r
-       if (head.biClrUsed){\r
-               rgb = GetPaletteColor(BlindGetPixelIndex(x,y));\r
-       } else {\r
-               BYTE* iDst  = info.pImage + y*info.dwEffWidth + x*3;\r
-               rgb.rgbBlue = *iDst++;\r
-               rgb.rgbGreen= *iDst++;\r
-               rgb.rgbRed  = *iDst;\r
-       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);\r
-#else\r
-       rgb.rgbReserved = 0;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * This is (a bit) faster version of GetPixelColor. \r
- * It tests bounds only in debug mode (_DEBUG defined).\r
- * \r
- * It is an error to request out-of-borders pixel with this method. \r
- * In DEBUG mode an exception will be thrown, and data will be violated in non-DEBUG mode. \r
- * \author ***bd*** 2.2004\r
- */\r
-RGBQUAD CxImage::BlindGetPixelColor(const long x,const long y, bool bGetAlpha)\r
-{\r
-  RGBQUAD rgb;\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL) || !IsInside(x,y))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               {rgb.rgbReserved = 0; return rgb;}\r
-  #endif\r
-#endif\r
-\r
-       if (head.biClrUsed){\r
-               rgb = GetPaletteColor(BlindGetPixelIndex(x,y));\r
-       } else {\r
-               BYTE* iDst  = info.pImage + y*info.dwEffWidth + x*3;\r
-               rgb.rgbBlue = *iDst++;\r
-               rgb.rgbGreen= *iDst++;\r
-               rgb.rgbRed  = *iDst;\r
-               rgb.rgbReserved = 0; //needed for images without alpha layer\r
-       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (pAlpha && bGetAlpha) rgb.rgbReserved = BlindAlphaGet(x,y);\r
-#else\r
-       rgb.rgbReserved = 0;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       return rgb;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-BYTE CxImage::GetPixelGray(long x, long y)\r
-{\r
-       RGBQUAD color = GetPixelColor(x,y);\r
-       return (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::BlindSetPixelIndex(long x,long y,BYTE i)\r
-{\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL)||(head.biClrUsed==0)||\r
-               (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return;\r
-  #endif\r
-#endif\r
-\r
-       if (head.biBitCount==8){\r
-               info.pImage[y*info.dwEffWidth + x]=i;\r
-               return;\r
-       } else {\r
-               BYTE pos;\r
-               BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);\r
-               if (head.biBitCount==4){\r
-                       pos = (BYTE)(4*(1-x%2));\r
-                       *iDst &= ~(0x0F<<pos);\r
-                       *iDst |= ((i & 0x0F)<<pos);\r
-                       return;\r
-               } else if (head.biBitCount==1){\r
-                       pos = (BYTE)(7-x%8);\r
-                       *iDst &= ~(0x01<<pos);\r
-                       *iDst |= ((i & 0x01)<<pos);\r
-                       return;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPixelIndex(long x,long y,BYTE i)\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)||\r
-               (x<0)||(y<0)||(x>=head.biWidth)||(y>=head.biHeight)) return ;\r
-\r
-       if (head.biBitCount==8){\r
-               info.pImage[y*info.dwEffWidth + x]=i;\r
-               return;\r
-       } else {\r
-               BYTE pos;\r
-               BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);\r
-               if (head.biBitCount==4){\r
-                       pos = (BYTE)(4*(1-x%2));\r
-                       *iDst &= ~(0x0F<<pos);\r
-                       *iDst |= ((i & 0x0F)<<pos);\r
-                       return;\r
-               } else if (head.biBitCount==1){\r
-                       pos = (BYTE)(7-x%8);\r
-                       *iDst &= ~(0x01<<pos);\r
-                       *iDst |= ((i & 0x01)<<pos);\r
-                       return;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPixelColor(long x,long y,COLORREF cr)\r
-{\r
-       SetPixelColor(x,y,RGBtoRGBQUAD(cr));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::BlindSetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha)\r
-{\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL)||(x<0)||(y<0)||\r
-               (x>=head.biWidth)||(y>=head.biHeight))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return;\r
-  #endif\r
-#endif\r
-       if (head.biClrUsed)\r
-               BlindSetPixelIndex(x,y,GetNearestIndex(c));\r
-       else {\r
-               BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;\r
-               *iDst++ = c.rgbBlue;\r
-               *iDst++ = c.rgbGreen;\r
-               *iDst   = c.rgbRed;\r
-       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPixelColor(long x,long y,RGBQUAD c, bool bSetAlpha)\r
-{\r
-       if ((pDib==NULL)||(x<0)||(y<0)||\r
-               (x>=head.biWidth)||(y>=head.biHeight)) return;\r
-       if (head.biClrUsed)\r
-               BlindSetPixelIndex(x,y,GetNearestIndex(c));\r
-       else {\r
-               BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;\r
-               *iDst++ = c.rgbBlue;\r
-               *iDst++ = c.rgbGreen;\r
-               *iDst   = c.rgbRed;\r
-       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Blends the current pixel color with a new color.\r
- * \param x,y = pixel\r
- * \param c = new color\r
- * \param blend = can be from 0 (no effect) to 1 (full effect).\r
- * \param bSetAlpha = if true, blends also the alpha component stored in c.rgbReserved\r
- */\r
-void CxImage::BlendPixelColor(long x,long y,RGBQUAD c, float blend, bool bSetAlpha)\r
-{\r
-       if ((pDib==NULL)||(x<0)||(y<0)||\r
-               (x>=head.biWidth)||(y>=head.biHeight)) return;\r
-\r
-       int a0 = (int)(256*blend);\r
-       int a1 = 256 - a0;\r
-\r
-       RGBQUAD c0 = BlindGetPixelColor(x,y);\r
-       c.rgbRed  = (BYTE)((c.rgbRed * a0 + c0.rgbRed * a1)>>8);\r
-       c.rgbBlue  = (BYTE)((c.rgbBlue * a0 + c0.rgbBlue * a1)>>8);\r
-       c.rgbGreen  = (BYTE)((c.rgbGreen * a0 + c0.rgbGreen * a1)>>8);\r
-\r
-       if (head.biClrUsed)\r
-               BlindSetPixelIndex(x,y,GetNearestIndex(c));\r
-       else {\r
-               BYTE* iDst = info.pImage + y*info.dwEffWidth + x*3;\r
-               *iDst++ = c.rgbBlue;\r
-               *iDst++ = c.rgbGreen;\r
-               *iDst   = c.rgbRed;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               if (bSetAlpha) AlphaSet(x,y,c.rgbReserved);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns the best palette index that matches a specified color.\r
- */\r
-BYTE CxImage::GetNearestIndex(RGBQUAD c)\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)) return 0;\r
-\r
-       // <RJ> check matching with the previous result\r
-       if (info.last_c_isvalid && (*(long*)&info.last_c == *(long*)&c)) return info.last_c_index;\r
-       info.last_c = c;\r
-       info.last_c_isvalid = true;\r
-\r
-       BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-       long distance=200000;\r
-       int i,j = 0;\r
-       long k,l;\r
-       int m = (int)(head.biClrImportant==0 ? head.biClrUsed : head.biClrImportant);\r
-       for(i=0,l=0;i<m;i++,l+=sizeof(RGBQUAD)){\r
-               k = (iDst[l]-c.rgbBlue)*(iDst[l]-c.rgbBlue)+\r
-                       (iDst[l+1]-c.rgbGreen)*(iDst[l+1]-c.rgbGreen)+\r
-                       (iDst[l+2]-c.rgbRed)*(iDst[l+2]-c.rgbRed);\r
-//             k = abs(iDst[l]-c.rgbBlue)+abs(iDst[l+1]-c.rgbGreen)+abs(iDst[l+2]-c.rgbRed);\r
-               if (k==0){\r
-                       j=i;\r
-                       break;\r
-               }\r
-               if (k<distance){\r
-                       distance=k;\r
-                       j=i;\r
-               }\r
-       }\r
-       info.last_c_index = (BYTE)j;\r
-       return (BYTE)j;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * swaps the blue and red components (for RGB images)\r
- * \param buffer : pointer to the pixels\r
- * \param length : number of bytes to swap. lenght may not exceed the scan line.\r
- */\r
-void CxImage::RGBtoBGR(BYTE *buffer, int length)\r
-{\r
-       if (buffer && (head.biClrUsed==0)){\r
-               BYTE temp;\r
-               length = min(length,(int)info.dwEffWidth);\r
-               length = min(length,(int)(3*head.biWidth));\r
-               for (int i=0;i<length;i+=3){\r
-                       temp = buffer[i]; buffer[i] = buffer[i+2]; buffer[i+2] = temp;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-RGBQUAD CxImage::RGBtoRGBQUAD(COLORREF cr)\r
-{\r
-       RGBQUAD c;\r
-       c.rgbRed = GetRValue(cr);       /* get R, G, and B out of DWORD */\r
-       c.rgbGreen = GetGValue(cr);\r
-       c.rgbBlue = GetBValue(cr);\r
-       c.rgbReserved=0;\r
-       return c;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-COLORREF CxImage::RGBQUADtoRGB (RGBQUAD c)\r
-{\r
-       return RGB(c.rgbRed,c.rgbGreen,c.rgbBlue);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns the color of the specified index.\r
- * \param i = palette index\r
- * \param r, g, b = output color channels\r
- */\r
-bool CxImage::GetPaletteColor(BYTE i, BYTE* r, BYTE* g, BYTE* b)\r
-{\r
-       RGBQUAD* ppal=GetPalette();\r
-       if (ppal) {\r
-               *r = ppal[i].rgbRed;\r
-               *g = ppal[i].rgbGreen;\r
-               *b = ppal[i].rgbBlue; \r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPalette(DWORD n, BYTE *r, BYTE *g, BYTE *b)\r
-{\r
-       if ((!r)||(pDib==NULL)||(head.biClrUsed==0)) return;\r
-       if (!g) g = r;\r
-       if (!b) b = g;\r
-       RGBQUAD* ppal=GetPalette();\r
-       DWORD m=min(n,head.biClrUsed);\r
-       for (DWORD i=0; i<m;i++){\r
-               ppal[i].rgbRed=r[i];\r
-               ppal[i].rgbGreen=g[i];\r
-               ppal[i].rgbBlue=b[i];\r
-       }\r
-       info.last_c_isvalid = false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPalette(rgb_color *rgb,DWORD nColors)\r
-{\r
-       if ((!rgb)||(pDib==NULL)||(head.biClrUsed==0)) return;\r
-       RGBQUAD* ppal=GetPalette();\r
-       DWORD m=min(nColors,head.biClrUsed);\r
-       for (DWORD i=0; i<m;i++){\r
-               ppal[i].rgbRed=rgb[i].r;\r
-               ppal[i].rgbGreen=rgb[i].g;\r
-               ppal[i].rgbBlue=rgb[i].b;\r
-       }\r
-       info.last_c_isvalid = false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::SetPalette(RGBQUAD* pPal,DWORD nColors)\r
-{\r
-       if ((pPal==NULL)||(pDib==NULL)||(head.biClrUsed==0)) return;\r
-       memcpy(GetPalette(),pPal,min(GetPaletteSize(),nColors*sizeof(RGBQUAD)));\r
-       info.last_c_isvalid = false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets (or replaces) the palette to gray scale palette.\r
- * The function doesn't change the pixels; for standard\r
- * gray scale conversion use GrayScale().\r
- */\r
-void CxImage::SetGrayPalette()\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)) return;\r
-       RGBQUAD* pal=GetPalette();\r
-       for (DWORD ni=0;ni<head.biClrUsed;ni++)\r
-               pal[ni].rgbBlue=pal[ni].rgbGreen = pal[ni].rgbRed = (BYTE)(ni*(255/(head.biClrUsed-1)));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Colorize the palette.\r
- * \sa Colorize\r
- */\r
-void CxImage::BlendPalette(COLORREF cr,long perc)\r
-{\r
-       if ((pDib==NULL)||(head.biClrUsed==0)) return;\r
-       BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);\r
-       DWORD i,r,g,b;\r
-       RGBQUAD* pPal=(RGBQUAD*)iDst;\r
-       r = GetRValue(cr);\r
-       g = GetGValue(cr);\r
-       b = GetBValue(cr);\r
-       if (perc>100) perc=100;\r
-       for(i=0;i<head.biClrUsed;i++){\r
-               pPal[i].rgbBlue=(BYTE)((pPal[i].rgbBlue*(100-perc)+b*perc)/100);\r
-               pPal[i].rgbGreen =(BYTE)((pPal[i].rgbGreen*(100-perc)+g*perc)/100);\r
-               pPal[i].rgbRed =(BYTE)((pPal[i].rgbRed*(100-perc)+r*perc)/100);\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns true if the image has 256 colors and a linear grey scale palette.\r
- */\r
-bool CxImage::IsGrayScale()\r
-{\r
-       RGBQUAD* ppal=GetPalette();\r
-       if(!(pDib && ppal && head.biClrUsed)) return false;\r
-       for(DWORD i=0;i<head.biClrUsed;i++){\r
-               if (ppal[i].rgbBlue!=i || ppal[i].rgbGreen!=i || ppal[i].rgbRed!=i) return false;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * swap two indexes in the image and their colors in the palette\r
- */\r
-void CxImage::SwapIndex(BYTE idx1, BYTE idx2)\r
-{\r
-       RGBQUAD* ppal=GetPalette();\r
-       if(!(pDib && ppal)) return;\r
-       //swap the colors\r
-       RGBQUAD tempRGB=GetPaletteColor(idx1);\r
-       SetPaletteColor(idx1,GetPaletteColor(idx2));\r
-       SetPaletteColor(idx2,tempRGB);\r
-       //swap the pixels\r
-       BYTE idx;\r
-       for(long y=0; y < head.biHeight; y++){\r
-               for(long x=0; x < head.biWidth; x++){\r
-                       idx=BlindGetPixelIndex(x,y);\r
-                       if (idx==idx1) BlindSetPixelIndex(x,y,idx2);\r
-                       if (idx==idx2) BlindSetPixelIndex(x,y,idx1);\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * swap Red and Blue colors\r
- */\r
-void CxImage::SwapRGB2BGR()\r
-{\r
-       if (!pDib) return;\r
-\r
-       if (head.biClrUsed){\r
-               RGBQUAD* ppal=GetPalette();\r
-               BYTE b;\r
-               if(!ppal) return;\r
-               for(WORD a=0;a<head.biClrUsed;a++){\r
-                       b=ppal[a].rgbBlue; ppal[a].rgbBlue=ppal[a].rgbRed; ppal[a].rgbRed=b;\r
-               }\r
-       } else {\r
-               for(long y=0;y<head.biHeight;y++){\r
-                       RGBtoBGR(GetBits(y),3*head.biWidth);\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::IsTransparent(long x, long y)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       if (info.nBkgndIndex>=0){\r
-               if (head.biClrUsed){\r
-                       if (GetPixelIndex(x,y) == info.nBkgndIndex) return true;\r
-               } else {\r
-                       RGBQUAD ct = info.nBkgndColor;\r
-                       RGBQUAD c = GetPixelColor(x,y,false);\r
-                       if (*(long*)&c==*(long*)&ct) return true;\r
-               }\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (pAlpha) return AlphaGet(x,y)==0;\r
-#endif\r
-\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::GetTransparentMask(CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       CxImage tmp;\r
-       tmp.Create(head.biWidth, head.biHeight, 1, GetType());\r
-       tmp.SetStdPalette();\r
-       tmp.Clear(0);\r
-\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       if (IsTransparent(x,y)){\r
-                               tmp.BlindSetPixelIndex(x,y,1);\r
-                       }\r
-               }\r
-       }\r
-\r
-       if (iDst) iDst->Transfer(tmp);\r
-       else Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if image has the same palette, if any.\r
- * \param img = image to compare.\r
- * \param bCheckAlpha = check also the rgbReserved field.\r
- */\r
-bool CxImage::IsSamePalette(CxImage &img, bool bCheckAlpha)\r
-{\r
-       if (head.biClrUsed != img.head.biClrUsed)\r
-               return false;\r
-       if (head.biClrUsed == 0)\r
-               return false;\r
-\r
-       RGBQUAD c1,c2;\r
-       for (DWORD n=0; n<head.biClrUsed; n++){\r
-               c1 = GetPaletteColor((BYTE)n);\r
-               c2 = img.GetPaletteColor((BYTE)n);\r
-               if (c1.rgbRed != c2.rgbRed) return false;\r
-               if (c1.rgbBlue != c2.rgbBlue) return false;\r
-               if (c1.rgbGreen != c2.rgbGreen) return false;\r
-               if (bCheckAlpha && (c1.rgbReserved != c2.rgbReserved)) return false;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa SetClrImportant\r
- */\r
-DWORD CxImage::GetClrImportant() const\r
-{\r
-       return head.biClrImportant;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * sets the maximum number of colors that some functions like\r
- * DecreaseBpp() or GetNearestIndex() will use on indexed images\r
- * \param ncolors should be less than 2^bpp,\r
- * or 0 if all the colors are important.\r
- */\r
-void CxImage::SetClrImportant(DWORD ncolors)\r
-{\r
-       if (ncolors==0 || ncolors>256) {\r
-               head.biClrImportant = 0;\r
-               return;\r
-       }\r
-\r
-       switch(head.biBitCount){\r
-       case 1:\r
-               head.biClrImportant = min(ncolors,2);\r
-               break;\r
-       case 4:\r
-               head.biClrImportant = min(ncolors,16);\r
-               break;\r
-       case 8:\r
-               head.biClrImportant = ncolors;\r
-               break;\r
-       }\r
-       return;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns pointer to pixel. Currently implemented only for truecolor images.\r
- *  \r
- * \param  x,y - coordinates\r
- *\r
- * \return pointer to first byte of pixel data\r
- *\r
- * \author ***bd*** 2.2004\r
- */\r
-void* CxImage::BlindGetPixelPointer(const long x, const long y)\r
-{\r
-#ifdef _DEBUG\r
-       if ((pDib==NULL) || !IsInside(x,y))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return 0;\r
-  #endif\r
-#endif\r
-  if (!IsIndexed())\r
-    return info.pImage + y*info.dwEffWidth + x*3;\r
-  else\r
-    return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, COLORREF cr)\r
-{\r
-       DrawLine(StartX, EndX, StartY, EndY, RGBtoRGBQUAD(cr));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha)\r
-{\r
-       if (!pDib) return;\r
-       //////////////////////////////////////////////////////\r
-       // Draws a line using the Bresenham line algorithm\r
-       // Thanks to Jordan DeLozier <JDL>\r
-       //////////////////////////////////////////////////////\r
-       int x1 = StartX;\r
-       int y1 = StartY;\r
-       int x = x1;                       // Start x off at the first pixel\r
-       int y = y1;                       // Start y off at the first pixel\r
-       int x2 = EndX;\r
-       int y2 = EndY;\r
-\r
-       int xinc1,xinc2,yinc1,yinc2;      // Increasing values\r
-       int den, num, numadd,numpixels;   \r
-       int deltax = abs(x2 - x1);        // The difference between the x's\r
-       int deltay = abs(y2 - y1);        // The difference between the y's\r
-\r
-       // Get Increasing Values\r
-       if (x2 >= x1) {                // The x-values are increasing\r
-               xinc1 = 1;\r
-               xinc2 = 1;\r
-       } else {                         // The x-values are decreasing\r
-               xinc1 = -1;\r
-               xinc2 = -1;\r
-       }\r
-\r
-       if (y2 >= y1) {                // The y-values are increasing\r
-               yinc1 = 1;\r
-               yinc2 = 1;\r
-       } else {                         // The y-values are decreasing\r
-               yinc1 = -1;\r
-               yinc2 = -1;\r
-       }\r
-\r
-       // Actually draw the line\r
-       if (deltax >= deltay)         // There is at least one x-value for every y-value\r
-       {\r
-               xinc1 = 0;                  // Don't change the x when numerator >= denominator\r
-               yinc2 = 0;                  // Don't change the y for every iteration\r
-               den = deltax;\r
-               num = deltax / 2;\r
-               numadd = deltay;\r
-               numpixels = deltax;         // There are more x-values than y-values\r
-       }\r
-       else                          // There is at least one y-value for every x-value\r
-       {\r
-               xinc2 = 0;                  // Don't change the x for every iteration\r
-               yinc1 = 0;                  // Don't change the y when numerator >= denominator\r
-               den = deltay;\r
-               num = deltay / 2;\r
-               numadd = deltax;\r
-               numpixels = deltay;         // There are more y-values than x-values\r
-       }\r
-       \r
-       for (int curpixel = 0; curpixel <= numpixels; curpixel++)\r
-       {\r
-               // Draw the current pixel\r
-               SetPixelColor(x,y,color,bSetAlpha);\r
-               \r
-               num += numadd;              // Increase the numerator by the top of the fraction\r
-               if (num >= den)             // Check if numerator >= denominator\r
-               {\r
-                       num -= den;               // Calculate the new numerator value\r
-                       x += xinc1;               // Change the x as appropriate\r
-                       y += yinc1;               // Change the y as appropriate\r
-               }\r
-               x += xinc2;                 // Change the x as appropriate\r
-               y += yinc2;                 // Change the y as appropriate\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets a palette with standard colors for 1, 4 and 8 bpp images.\r
- */\r
-void CxImage::SetStdPalette()\r
-{\r
-       if (!pDib) return;\r
-       switch (head.biBitCount){\r
-       case 8:\r
-               {\r
-                       const BYTE 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,\r
-                       192,220,192,0,240,202,166,0,212,240,255,0,177,226,255,0,142,212,255,0,107,198,255,0,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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,\r
-                       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};\r
-                       memcpy(GetPalette(),pal256,1024);\r
-                       break;\r
-               }\r
-       case 4:\r
-               {\r
-                       const BYTE 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,\r
-                                                               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};\r
-                       memcpy(GetPalette(),pal16,64);\r
-                       break;\r
-               }\r
-       case 1:\r
-               {\r
-                       const BYTE pal2[8]={0,0,0,0,255,255,255,0};\r
-                       memcpy(GetPalette(),pal2,8);\r
-                       break;\r
-               }\r
-       }\r
-       info.last_c_isvalid = false;\r
-       return;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
+// xImaPal.cpp : Palette and Pixel functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximage.h"
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * returns the palette dimension in byte
+ */
+DWORD CxImage::GetPaletteSize()
+{
+       return (head.biClrUsed * sizeof(RGBQUAD));
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPaletteColor(BYTE idx, BYTE r, BYTE g, BYTE b, BYTE alpha)
+{
+       if ((pDib)&&(head.biClrUsed)){
+               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
+               if (idx<head.biClrUsed){
+                       long ldx=idx*sizeof(RGBQUAD);
+                       iDst[ldx++] = (BYTE) b;
+                       iDst[ldx++] = (BYTE) g;
+                       iDst[ldx++] = (BYTE) r;
+                       iDst[ldx] = (BYTE) alpha;
+                       info.last_c_isvalid = false;
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPaletteColor(BYTE idx, RGBQUAD c)
+{
+       if ((pDib)&&(head.biClrUsed)){
+               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
+               if (idx<head.biClrUsed){
+                       long ldx=idx*sizeof(RGBQUAD);
+                       iDst[ldx++] = (BYTE) c.rgbBlue;
+                       iDst[ldx++] = (BYTE) c.rgbGreen;
+                       iDst[ldx++] = (BYTE) c.rgbRed;
+                       iDst[ldx] = (BYTE) c.rgbReserved;
+                       info.last_c_isvalid = false;
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPaletteColor(BYTE idx, COLORREF cr)
+{
+       if ((pDib)&&(head.biClrUsed)){
+               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
+               if (idx<head.biClrUsed){
+                       long ldx=idx*sizeof(RGBQUAD);
+                       iDst[ldx++] = (BYTE) GetBValue(cr);
+                       iDst[ldx++] = (BYTE) GetGValue(cr);
+                       iDst[ldx++] = (BYTE) GetRValue(cr);
+                       iDst[ldx] = (BYTE) 0;
+                       info.last_c_isvalid = false;
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * returns the pointer to the first palette index
+ */
+RGBQUAD* CxImage::GetPalette() const
+{
+       if ((pDib)&&(head.biClrUsed))
+               return (RGBQUAD*)((BYTE*)pDib + sizeof(BITMAPINFOHEADER));
+       return NULL;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the color of the specified index.
+ */
+RGBQUAD CxImage::GetPaletteColor(BYTE idx)
+{
+       RGBQUAD rgb = {0,0,0,0};
+       if ((pDib)&&(head.biClrUsed)){
+               BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
+               if (idx<head.biClrUsed){
+                       long 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.
+ */
+BYTE CxImage::GetPixelIndex(long x,long 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 (BYTE)info.nBkgndIndex;
+               else return *info.pImage;
+       }
+       if (head.biBitCount==8){
+               return info.pImage[y*info.dwEffWidth + x];
+       } else {
+               BYTE pos;
+               BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];
+               if (head.biBitCount==4){
+                       pos = (BYTE)(4*(1-x%2));
+                       iDst &= (0x0F<<pos);
+                       return (BYTE)(iDst >> pos);
+               } else if (head.biBitCount==1){
+                       pos = (BYTE)(7-x%8);
+                       iDst &= (0x01<<pos);
+                       return (BYTE)(iDst >> pos);
+               }
+       }
+       return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+BYTE CxImage::BlindGetPixelIndex(const long x,const long 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 {
+               BYTE pos;
+               BYTE iDst= info.pImage[y*info.dwEffWidth + (x*head.biBitCount >> 3)];
+               if (head.biBitCount==4){
+                       pos = (BYTE)(4*(1-x%2));
+                       iDst &= (0x0F<<pos);
+                       return (BYTE)(iDst >> pos);
+               } else if (head.biBitCount==1){
+                       pos = (BYTE)(7-x%8);
+                       iDst &= (0x01<<pos);
+                       return (BYTE)(iDst >> pos);
+               }
+       }
+       return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+RGBQUAD CxImage::GetPixelColor(long x,long 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((BYTE)info.nBkgndIndex);
+                       else return info.nBkgndColor;
+               } else if (pDib) return GetPixelColor(0,0);
+               return rgb;
+       }
+
+       if (head.biClrUsed){
+               rgb = GetPaletteColor(BlindGetPixelIndex(x,y));
+       } else {
+               BYTE* 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 long x,const long 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 {
+               BYTE* 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;
+}
+////////////////////////////////////////////////////////////////////////////////
+BYTE CxImage::GetPixelGray(long x, long y)
+{
+       RGBQUAD color = GetPixelColor(x,y);
+       return (BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue);
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::BlindSetPixelIndex(long x,long y,BYTE 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 {
+               BYTE pos;
+               BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);
+               if (head.biBitCount==4){
+                       pos = (BYTE)(4*(1-x%2));
+                       *iDst &= ~(0x0F<<pos);
+                       *iDst |= ((i & 0x0F)<<pos);
+                       return;
+               } else if (head.biBitCount==1){
+                       pos = (BYTE)(7-x%8);
+                       *iDst &= ~(0x01<<pos);
+                       *iDst |= ((i & 0x01)<<pos);
+                       return;
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPixelIndex(long x,long y,BYTE 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 {
+               BYTE pos;
+               BYTE* iDst= info.pImage + y*info.dwEffWidth + (x*head.biBitCount >> 3);
+               if (head.biBitCount==4){
+                       pos = (BYTE)(4*(1-x%2));
+                       *iDst &= ~(0x0F<<pos);
+                       *iDst |= ((i & 0x0F)<<pos);
+                       return;
+               } else if (head.biBitCount==1){
+                       pos = (BYTE)(7-x%8);
+                       *iDst &= ~(0x01<<pos);
+                       *iDst |= ((i & 0x01)<<pos);
+                       return;
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::SetPixelColor(long x,long y,COLORREF cr)
+{
+       SetPixelColor(x,y,RGBtoRGBQUAD(cr));
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::BlindSetPixelColor(long x,long 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 {
+               BYTE* 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(long x,long 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 {
+               BYTE* 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(long x,long y,RGBQUAD c, float blend, bool bSetAlpha)
+{
+       if ((pDib==NULL)||(x<0)||(y<0)||
+               (x>=head.biWidth)||(y>=head.biHeight)) return;
+
+       int a0 = (int)(256*blend);
+       int a1 = 256 - a0;
+
+       RGBQUAD c0 = BlindGetPixelColor(x,y);
+       c.rgbRed  = (BYTE)((c.rgbRed * a0 + c0.rgbRed * a1)>>8);
+       c.rgbBlue  = (BYTE)((c.rgbBlue * a0 + c0.rgbBlue * a1)>>8);
+       c.rgbGreen  = (BYTE)((c.rgbGreen * a0 + c0.rgbGreen * a1)>>8);
+
+       if (head.biClrUsed)
+               BlindSetPixelIndex(x,y,GetNearestIndex(c));
+       else {
+               BYTE* 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.
+ */
+BYTE CxImage::GetNearestIndex(RGBQUAD c)
+{
+       if ((pDib==NULL)||(head.biClrUsed==0)) return 0;
+
+       // <RJ> check matching with the previous result
+       if (info.last_c_isvalid && (*(long*)&info.last_c == *(long*)&c)) return info.last_c_index;
+       info.last_c = c;
+       info.last_c_isvalid = true;
+
+       BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
+       long distance=200000;
+       int i,j = 0;
+       long k,l;
+       int m = (int)(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 = (BYTE)j;
+       return (BYTE)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(BYTE *buffer, int length)
+{
+       if (buffer && (head.biClrUsed==0)){
+               BYTE temp;
+               length = min(length,(int)info.dwEffWidth);
+               length = min(length,(int)(3*head.biWidth));
+               for (int 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 DWORD */
+       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(BYTE i, BYTE* r, BYTE* g, BYTE* 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(DWORD n, BYTE *r, BYTE *g, BYTE *b)
+{
+       if ((!r)||(pDib==NULL)||(head.biClrUsed==0)) return;
+       if (!g) g = r;
+       if (!b) b = g;
+       RGBQUAD* ppal=GetPalette();
+       DWORD m=min(n,head.biClrUsed);
+       for (DWORD 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,DWORD nColors)
+{
+       if ((!rgb)||(pDib==NULL)||(head.biClrUsed==0)) return;
+       RGBQUAD* ppal=GetPalette();
+       DWORD m=min(nColors,head.biClrUsed);
+       for (DWORD 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,DWORD 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 (DWORD ni=0;ni<head.biClrUsed;ni++)
+               pal[ni].rgbBlue=pal[ni].rgbGreen = pal[ni].rgbRed = (BYTE)(ni*(255/(head.biClrUsed-1)));
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Colorize the palette.
+ * \sa Colorize
+ */
+void CxImage::BlendPalette(COLORREF cr,long perc)
+{
+       if ((pDib==NULL)||(head.biClrUsed==0)) return;
+       BYTE* iDst = (BYTE*)(pDib) + sizeof(BITMAPINFOHEADER);
+       DWORD 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=(BYTE)((pPal[i].rgbBlue*(100-perc)+b*perc)/100);
+               pPal[i].rgbGreen =(BYTE)((pPal[i].rgbGreen*(100-perc)+g*perc)/100);
+               pPal[i].rgbRed =(BYTE)((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(DWORD 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(BYTE idx1, BYTE 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
+       BYTE idx;
+       for(long y=0; y < head.biHeight; y++){
+               for(long 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();
+               BYTE b;
+               if(!ppal) return;
+               for(WORD a=0;a<head.biClrUsed;a++){
+                       b=ppal[a].rgbBlue; ppal[a].rgbBlue=ppal[a].rgbRed; ppal[a].rgbRed=b;
+               }
+       } else {
+               for(long y=0;y<head.biHeight;y++){
+                       RGBtoBGR(GetBits(y),3*head.biWidth);
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::IsTransparent(long x, long 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 (*(long*)&c==*(long*)&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(long y=0; y<head.biHeight; y++){
+               for(long 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 (DWORD n=0; n<head.biClrUsed; n++){
+               c1 = GetPaletteColor((BYTE)n);
+               c2 = img.GetPaletteColor((BYTE)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
+ */
+DWORD 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(DWORD 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 long x, const long 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(int StartX, int EndX, int StartY, int EndY, COLORREF cr)
+{
+       DrawLine(StartX, EndX, StartY, EndY, RGBtoRGBQUAD(cr));
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::DrawLine(int StartX, int EndX, int StartY, int EndY, RGBQUAD color, bool bSetAlpha)
+{
+       if (!pDib) return;
+       //////////////////////////////////////////////////////
+       // Draws a line using the Bresenham line algorithm
+       // Thanks to Jordan DeLozier <JDL>
+       //////////////////////////////////////////////////////
+       int x1 = StartX;
+       int y1 = StartY;
+       int x = x1;                       // Start x off at the first pixel
+       int y = y1;                       // Start y off at the first pixel
+       int x2 = EndX;
+       int y2 = EndY;
+
+       int xinc1,xinc2,yinc1,yinc2;      // Increasing values
+       int den, num, numadd,numpixels;   
+       int deltax = abs(x2 - x1);        // The difference between the x's
+       int 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 (int 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 BYTE 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 BYTE 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 BYTE pal2[8]={0,0,0,0,255,255,255,0};
+                       memcpy(GetPalette(),pal2,8);
+                       break;
+               }
+       }
+       info.last_c_isvalid = false;
+       return;
+}
+////////////////////////////////////////////////////////////////////////////////
index 0d7e0a862465109064c5001675549f4b75ea44ff..f32ba33bd2f8bf547f1e9250939cfd9e9a23947d 100644 (file)
-/*\r
- * File:       ximapcx.cpp\r
- * Purpose:    Platform Independent PCX Image Class Loader and Writer\r
- * 05/Jan/2002 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- *\r
- * based on ppmtopcx.c - convert a portable pixmap to PCX\r
- * Copyright (C) 1994 by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)\r
- * based on ppmtopcx.c by Michael Davidson\r
- */\r
-\r
-#include "ximapcx.h"\r
-\r
-#if CXIMAGE_SUPPORT_PCX\r
-\r
-#include "xmemfile.h"\r
-\r
-#define PCX_MAGIC 0X0A  // PCX magic number\r
-#define PCX_256_COLORS 0X0C  // magic number for 256 colors\r
-#define PCX_HDR_SIZE 128  // size of PCX header\r
-#define PCX_MAXCOLORS 256\r
-#define PCX_MAXPLANES 4\r
-#define PCX_MAXVAL 255\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImagePCX::Decode(CxFile *hFile)\r
-{\r
-       if (hFile == NULL) return false;\r
-\r
-       PCXHEADER pcxHeader;\r
-       int i, x, y, y2, nbytes, count, Height, Width;\r
-       BYTE c, ColorMap[PCX_MAXCOLORS][3];\r
-       BYTE *pcximage = NULL, *lpHead1 = NULL, *lpHead2 = NULL;\r
-       BYTE *pcxplanes, *pcxpixels;\r
-\r
-  cx_try\r
-  {\r
-       if (hFile->Read(&pcxHeader,sizeof(PCXHEADER),1)==0) cx_throw("Can't read PCX image");\r
-\r
-       PCX_toh(&pcxHeader);\r
-\r
-    if (pcxHeader.Manufacturer != PCX_MAGIC) cx_throw("Error: Not a PCX file");\r
-    // Check for PCX run length encoding\r
-    if (pcxHeader.Encoding != 1) cx_throw("PCX file has unknown encoding scheme");\r
\r
-    Width = (pcxHeader.Xmax - pcxHeader.Xmin) + 1;\r
-    Height = (pcxHeader.Ymax - pcxHeader.Ymin) + 1;\r
-       info.xDPI = pcxHeader.Hres;\r
-       info.yDPI = pcxHeader.Vres;\r
-\r
-       if (info.nEscape == -1){\r
-               head.biWidth = Width;\r
-               head.biHeight= Height;\r
-               info.dwType = CXIMAGE_FORMAT_PCX;\r
-               return true;\r
-       }\r
-\r
-    // Check that we can handle this image format\r
-    if (pcxHeader.ColorPlanes > 4)\r
-               cx_throw("Can't handle image with more than 4 planes");\r
-\r
-       // Create the image\r
-       if (pcxHeader.ColorPlanes >= 3 && pcxHeader.BitsPerPixel == 8){\r
-               Create (Width, Height, 24, CXIMAGE_FORMAT_PCX);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               if (pcxHeader.ColorPlanes==4) AlphaCreate();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 1)\r
-               Create (Width, Height, 4, CXIMAGE_FORMAT_PCX);\r
-       else\r
-               Create (Width, Height, pcxHeader.BitsPerPixel, CXIMAGE_FORMAT_PCX);\r
-\r
-       if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding\r
-\r
-       //Read the image and check if it's ok\r
-    nbytes = pcxHeader.BytesPerLine * pcxHeader.ColorPlanes * Height;\r
-    lpHead1 = pcximage = (BYTE*)malloc(nbytes);\r
-    while (nbytes > 0){\r
-               if (hFile == NULL || hFile->Eof()) cx_throw("corrupted PCX");\r
-\r
-               hFile->Read(&c,1,1);\r
-               if ((c & 0XC0) != 0XC0){ // Repeated group\r
-                       *pcximage++ = c;\r
-                       --nbytes;\r
-                       continue;\r
-               }\r
-               count = c & 0X3F; // extract count\r
-               hFile->Read(&c,1,1);\r
-               if (count > nbytes) cx_throw("repeat count spans end of image");\r
-\r
-               nbytes -= count;\r
-               while (--count >=0) *pcximage++ = c;\r
-       }\r
-    pcximage = lpHead1;\r
-\r
-       //store the palette\r
-    for (i = 0; i < 16; i++){\r
-               ColorMap[i][0] = pcxHeader.ColorMap[i][0];\r
-               ColorMap[i][1] = pcxHeader.ColorMap[i][1];\r
-               ColorMap[i][2] = pcxHeader.ColorMap[i][2];\r
-       }\r
-    if (pcxHeader.BitsPerPixel == 8 && pcxHeader.ColorPlanes == 1){\r
-               hFile->Read(&c,1,1);\r
-               if (c != PCX_256_COLORS) cx_throw("bad color map signature");\r
-               \r
-               for (i = 0; i < PCX_MAXCOLORS; i++){\r
-                       hFile->Read(&ColorMap[i][0],1,1);\r
-                       hFile->Read(&ColorMap[i][1],1,1);\r
-                       hFile->Read(&ColorMap[i][2],1,1);\r
-               }\r
-       }\r
-    if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){\r
-               ColorMap[0][0] = ColorMap[0][1] = ColorMap[0][2] = 0;\r
-               ColorMap[1][0] = ColorMap[1][1] = ColorMap[1][2] = 255;\r
-       }\r
-\r
-       for (DWORD idx=0; idx<head.biClrUsed; idx++) SetPaletteColor((BYTE)idx,ColorMap[idx][0],ColorMap[idx][1],ColorMap[idx][2]);\r
-\r
-    lpHead2 = pcxpixels = (BYTE *)malloc(Width + pcxHeader.BytesPerLine * 8);\r
-    // Convert the image\r
-    for (y = 0; y < Height; y++){\r
-\r
-               if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding\r
-\r
-               y2=Height-1-y;\r
-               pcxpixels = lpHead2;\r
-               pcxplanes = pcximage + (y * pcxHeader.BytesPerLine * pcxHeader.ColorPlanes);\r
-\r
-               if (pcxHeader.ColorPlanes == 3 && pcxHeader.BitsPerPixel == 8){\r
-                       // Deal with 24 bit color image\r
-                       for (x = 0; x < Width; x++){\r
-                               SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x]));\r
-                       }\r
-                       continue;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               } else if (pcxHeader.ColorPlanes == 4 && pcxHeader.BitsPerPixel == 8){\r
-                       for (x = 0; x < Width; x++){\r
-                               SetPixelColor(x,y2,RGB(pcxplanes[x],pcxplanes[pcxHeader.BytesPerLine + x],pcxplanes[2*pcxHeader.BytesPerLine + x]));\r
-                               AlphaSet(x,y2,pcxplanes[3*pcxHeader.BytesPerLine + x]);\r
-                       }\r
-                       continue;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-               } else if (pcxHeader.ColorPlanes == 1) {\r
-                       if (!PCX_UnpackPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel)){\r
-                               cx_throw("PCX_UnpackPixels: Can't handle packed pixels with more than 1 plane");\r
-                       }\r
-               } else {\r
-                       if (!PCX_PlanesToPixels(pcxpixels, pcxplanes, pcxHeader.BytesPerLine, pcxHeader.ColorPlanes, pcxHeader.BitsPerPixel)){\r
-                               cx_throw("PCX_PlanesToPixels: more than 4 planes or more than 1 bit per pixel");\r
-                       }\r
-               }\r
-               for (x = 0; x < Width; x++)     SetPixelIndex(x,y2,pcxpixels[x]);\r
-       }\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       if (lpHead1){ free(lpHead1); lpHead1 = NULL; }\r
-    if (lpHead2){ free(lpHead2); lpHead2 = NULL; }\r
-       return false;\r
-  }\r
-       if (lpHead1){ free(lpHead1); lpHead1 = NULL; }\r
-    if (lpHead2){ free(lpHead2); lpHead2 = NULL; }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImagePCX::Encode(CxFile * hFile)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-  cx_try\r
-  {\r
-       PCXHEADER pcxHeader;\r
-       memset(&pcxHeader,0,sizeof(pcxHeader));\r
-       pcxHeader.Manufacturer = PCX_MAGIC;\r
-       pcxHeader.Version = 5;\r
-       pcxHeader.Encoding = 1;\r
-       pcxHeader.Xmin = 0;\r
-       pcxHeader.Ymin = 0;\r
-       pcxHeader.Xmax = (WORD)head.biWidth-1;\r
-       pcxHeader.Ymax = (WORD)head.biHeight-1;\r
-       pcxHeader.Hres = (WORD)info.xDPI;\r
-       pcxHeader.Vres = (WORD)info.yDPI;\r
-       pcxHeader.Reserved = 0;\r
-       pcxHeader.PaletteType = head.biClrUsed==0;\r
-\r
-       switch(head.biBitCount){\r
-       case 24:\r
-       case 8:\r
-               {\r
-                       pcxHeader.BitsPerPixel = 8;\r
-                       pcxHeader.ColorPlanes = head.biClrUsed==0 ? 3 : 1;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       if (AlphaIsValid() && head.biClrUsed==0) pcxHeader.ColorPlanes =4;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       pcxHeader.BytesPerLine = (WORD)head.biWidth;\r
-                       break;\r
-               }\r
-       default: //(4 1)\r
-               pcxHeader.BitsPerPixel = 1;\r
-               pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1;\r
-               pcxHeader.BytesPerLine = (WORD)((head.biWidth * pcxHeader.BitsPerPixel + 7)>>3);\r
-       }\r
-\r
-    if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 1){\r
-               pcxHeader.ColorMap[0][0] = pcxHeader.ColorMap[0][1] = pcxHeader.ColorMap[0][2] = 0;\r
-               pcxHeader.ColorMap[1][0] = pcxHeader.ColorMap[1][1] = pcxHeader.ColorMap[1][2] = 255;\r
-       }\r
-       if (pcxHeader.BitsPerPixel == 1 && pcxHeader.ColorPlanes == 4){\r
-               RGBQUAD c;\r
-               for (int i = 0; i < 16; i++){\r
-                       c=GetPaletteColor(i);\r
-                       pcxHeader.ColorMap[i][0] = c.rgbRed;\r
-                       pcxHeader.ColorMap[i][1] = c.rgbGreen;\r
-                       pcxHeader.ColorMap[i][2] = c.rgbBlue;\r
-               }\r
-       }\r
-\r
-       pcxHeader.BytesPerLine = (pcxHeader.BytesPerLine + 1)&(~1);\r
-\r
-       PCX_toh(&pcxHeader);\r
-       if (hFile->Write(&pcxHeader, sizeof(pcxHeader), 1) == 0 )\r
-          cx_throw("cannot write PCX header");\r
-       PCX_toh(&pcxHeader);\r
-\r
-       CxMemFile buffer;\r
-       buffer.Open();\r
-\r
-       BYTE c,n;\r
-       long x,y;\r
-       if (head.biClrUsed==0){\r
-               for (y = head.biHeight-1; y >=0 ; y--){\r
-                       for (int p=0; p<pcxHeader.ColorPlanes; p++){\r
-                               c=n=0;\r
-                               for (x = 0; x<head.biWidth; x++){\r
-                                       if (p==0)\r
-                                               PCX_PackPixels(BlindGetPixelColor(x,y).rgbRed,c,n,buffer);\r
-                                       else if (p==1)\r
-                                               PCX_PackPixels(BlindGetPixelColor(x,y).rgbGreen,c,n,buffer);\r
-                                       else if (p==2)\r
-                                               PCX_PackPixels(BlindGetPixelColor(x,y).rgbBlue,c,n,buffer);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       else if (p==3)\r
-                                               PCX_PackPixels(BlindAlphaGet(x,y),c,n,buffer);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                               }\r
-                               PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer);\r
-                       }\r
-               }\r
-\r
-               hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1);\r
-\r
-       } else if (head.biBitCount==8) {\r
-\r
-               for (y = head.biHeight-1; y >=0 ; y--){\r
-                       c=n=0;\r
-                       for (x = 0; x<head.biWidth; x++){\r
-                               PCX_PackPixels(GetPixelIndex(x,y),c,n,buffer);\r
-                       }\r
-                       PCX_PackPixels(-1-(head.biWidth&0x1),c,n,buffer);\r
-               }\r
-\r
-               hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1);\r
-\r
-               if (head.biBitCount == 8){\r
-                       hFile->PutC(0x0C);\r
-                       BYTE* pal = (BYTE*)malloc(768);\r
-                       RGBQUAD c;\r
-                       for (int i=0;i<256;i++){\r
-                               c=GetPaletteColor(i);\r
-                               pal[3*i+0] = c.rgbRed;\r
-                               pal[3*i+1] = c.rgbGreen;\r
-                               pal[3*i+2] = c.rgbBlue;\r
-                       }\r
-                       hFile->Write(pal,768,1);\r
-                       free(pal);\r
-               }\r
-       } else { //(head.biBitCount==4) || (head.biBitCount==1)\r
-\r
-               RGBQUAD *rgb = GetPalette();\r
-               bool binvert = false;\r
-               if (CompareColors(&rgb[0],&rgb[1])>0) binvert=(head.biBitCount==1);\r
-               \r
-               BYTE* plane = (BYTE*)malloc(pcxHeader.BytesPerLine);\r
-               BYTE* raw = (BYTE*)malloc(head.biWidth);\r
-\r
-               for(y = head.biHeight-1; y >=0 ; y--) {\r
-\r
-                       for( x = 0; x < head.biWidth; x++)      raw[x] = (BYTE)GetPixelIndex(x,y);\r
-\r
-                       if (binvert) for( x = 0; x < head.biWidth; x++) raw[x] = 1-raw[x];\r
-\r
-                       for( x = 0; x < pcxHeader.ColorPlanes; x++ ) {\r
-                               PCX_PixelsToPlanes(raw, head.biWidth, plane, x);\r
-                               PCX_PackPlanes(plane, pcxHeader.BytesPerLine, buffer);\r
-                       }\r
-               }\r
-\r
-               free(plane);\r
-               free(raw);\r
-\r
-               hFile->Write(buffer.GetBuffer(false),buffer.Tell(),1);\r
-\r
-       }\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       return false;\r
-  }\r
-    return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Convert multi-plane format into 1 pixel per byte\r
-// from unpacked file data bitplanes[] into pixel row pixels[]\r
-// image Height rows, with each row having planes image planes each\r
-// bytesperline bytes\r
-bool CxImagePCX::PCX_PlanesToPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel)\r
-{\r
-       int i, j, npixels;\r
-       BYTE * p;\r
-       if (planes > 4) return false;\r
-       if (bitsperpixel != 1) return false;\r
-\r
-       // Clear the pixel buffer\r
-       npixels = (bytesperline * 8) / bitsperpixel;\r
-       p = pixels;\r
-       while (--npixels >= 0) *p++ = 0;\r
-\r
-       // Do the format conversion\r
-       for (i = 0; i < planes; i++){\r
-               int pixbit, bits, mask;\r
-               p = pixels;\r
-               pixbit = (1 << i);  // pixel bit for this plane\r
-               for (j = 0; j < bytesperline; j++){\r
-                       bits = *bitplanes++;\r
-                       for (mask = 0X80; mask != 0; mask >>= 1, p++)\r
-                               if (bits & mask) *p |= pixbit;\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// convert packed pixel format into 1 pixel per byte\r
-// from unpacked file data bitplanes[] into pixel row pixels[]\r
-// image Height rows, with each row having planes image planes each\r
-// bytesperline bytes\r
-bool CxImagePCX::PCX_UnpackPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel)\r
-{\r
-       register int bits;\r
-       if (planes != 1) return false;\r
-       \r
-       if (bitsperpixel == 8){  // 8 bits/pixels, no unpacking needed\r
-               while (bytesperline-- > 0) *pixels++ = *bitplanes++;\r
-       } else if (bitsperpixel == 4){  // 4 bits/pixel, two pixels per byte\r
-               while (bytesperline-- > 0){\r
-                       bits = *bitplanes++;\r
-                       *pixels++ = (BYTE)((bits >> 4) & 0X0F);\r
-                       *pixels++ = (BYTE)((bits) & 0X0F);\r
-               }\r
-       } else if (bitsperpixel == 2){  // 2 bits/pixel, four pixels per byte\r
-               while (bytesperline-- > 0){\r
-                       bits = *bitplanes++;\r
-                       *pixels++ = (BYTE)((bits >> 6) & 0X03);\r
-                       *pixels++ = (BYTE)((bits >> 4) & 0X03);\r
-                       *pixels++ = (BYTE)((bits >> 2) & 0X03);\r
-                       *pixels++ = (BYTE)((bits) & 0X03);\r
-               }\r
-       } else if (bitsperpixel == 1){  // 1 bits/pixel, 8 pixels per byte\r
-               while (bytesperline-- > 0){\r
-                       bits = *bitplanes++;\r
-                       *pixels++ = ((bits & 0X80) != 0);\r
-                       *pixels++ = ((bits & 0X40) != 0);\r
-                       *pixels++ = ((bits & 0X20) != 0);\r
-                       *pixels++ = ((bits & 0X10) != 0);\r
-                       *pixels++ = ((bits & 0X08) != 0);\r
-                       *pixels++ = ((bits & 0X04) != 0);\r
-                       *pixels++ = ((bits & 0X02) != 0);\r
-                       *pixels++ = ((bits & 0X01) != 0);\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/* PCX_PackPixels(const long p,BYTE &c, BYTE &n, long &l, CxFile &f)\r
- * p = current pixel (-1 ends the line -2 ends odd line)\r
- * c = previous pixel\r
- * n = number of consecutive pixels\r
- */\r
-void CxImagePCX::PCX_PackPixels(const long p,BYTE &c, BYTE &n, CxFile &f)\r
-{\r
-       if (p!=c && n){\r
-               if (n==1 && c<0xC0){\r
-                       f.PutC(c);\r
-               } else {\r
-                       f.PutC(0xC0|n);\r
-                       f.PutC(c);\r
-               }\r
-               n=0;\r
-       }\r
-       if (n==0x3F) {\r
-               f.PutC(0xFF);\r
-               f.PutC(c);\r
-               n=0;\r
-       }\r
-       if (p==-2) f.PutC(0);\r
-       c=(BYTE)p;\r
-       n++;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImagePCX::PCX_PackPlanes(BYTE* buff, const long size, CxFile &f)\r
-{\r
-    BYTE *start,*end;\r
-    BYTE c, previous, count;\r
-\r
-       start = buff;\r
-    end = buff + size;\r
-    previous = *start++;\r
-    count    = 1;\r
-\r
-    while (start < end) {\r
-        c = *start++;\r
-        if (c == previous && count < 63) {\r
-            ++count;\r
-            continue;\r
-        }\r
-\r
-        if (count > 1 || (previous & 0xc0) == 0xc0) {\r
-            f.PutC( count | 0xc0 );\r
-        }\r
-        f.PutC(previous);\r
-        previous = c;\r
-        count   = 1;\r
-    }\r
-\r
-    if (count > 1 || (previous & 0xc0) == 0xc0) {\r
-        count |= 0xc0;\r
-        f.PutC(count);\r
-    }\r
-    f.PutC(previous);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImagePCX::PCX_PixelsToPlanes(BYTE* raw, long width, BYTE* buf, long plane)\r
-{\r
-    int cbit, x, mask;\r
-    unsigned char *cp = buf-1;\r
-\r
-    mask = 1 << plane;\r
-    cbit = -1;\r
-    for( x = 0; x < width; x++ ) {\r
-        if( cbit < 0 ) {\r
-            cbit = 7;\r
-            *++cp = 0;\r
-        }\r
-        if( raw[x] & mask )\r
-            *cp |= (1<<cbit);\r
-        --cbit;\r
-    }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImagePCX::PCX_toh(PCXHEADER* p)\r
-{\r
-       p->Xmin = ntohs(p->Xmin);\r
-       p->Ymin = ntohs(p->Ymin);\r
-       p->Xmax = ntohs(p->Xmax);\r
-       p->Ymax = ntohs(p->Ymax);\r
-       p->Hres = ntohs(p->Hres);\r
-       p->Vres = ntohs(p->Vres);\r
-       p->BytesPerLine = ntohs(p->BytesPerLine);\r
-       p->PaletteType = ntohs(p->PaletteType);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_PCX\r
+/*
+ * File:       ximapcx.cpp
+ * Purpose:    Platform Independent PCX Image Class Loader and Writer
+ * 05/Jan/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ *
+ * 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;
+       int i, x, y, y2, nbytes, count, Height, Width;
+       BYTE c, ColorMap[PCX_MAXCOLORS][3];
+       BYTE *pcximage = NULL, *lpHead1 = NULL, *lpHead2 = NULL;
+       BYTE *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 = (BYTE*)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 (DWORD idx=0; idx<head.biClrUsed; idx++) SetPaletteColor((BYTE)idx,ColorMap[idx][0],ColorMap[idx][1],ColorMap[idx][2]);
+
+    lpHead2 = pcxpixels = (BYTE *)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 = (WORD)head.biWidth-1;
+       pcxHeader.Ymax = (WORD)head.biHeight-1;
+       pcxHeader.Hres = (WORD)info.xDPI;
+       pcxHeader.Vres = (WORD)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 = (WORD)head.biWidth;
+                       break;
+               }
+       default: //(4 1)
+               pcxHeader.BitsPerPixel = 1;
+               pcxHeader.ColorPlanes = head.biClrUsed==16 ? 4 : 1;
+               pcxHeader.BytesPerLine = (WORD)((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 (int 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();
+
+       BYTE c,n;
+       long x,y;
+       if (head.biClrUsed==0){
+               for (y = head.biHeight-1; y >=0 ; y--){
+                       for (int 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);
+                       BYTE* pal = (BYTE*)malloc(768);
+                       RGBQUAD c;
+                       for (int 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);
+               
+               BYTE* plane = (BYTE*)malloc(pcxHeader.BytesPerLine);
+               BYTE* raw = (BYTE*)malloc(head.biWidth);
+
+               for(y = head.biHeight-1; y >=0 ; y--) {
+
+                       for( x = 0; x < head.biWidth; x++)      raw[x] = (BYTE)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(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel)
+{
+       int i, j, npixels;
+       BYTE * 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++){
+               int 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(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel)
+{
+       register int 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++ = (BYTE)((bits >> 4) & 0X0F);
+                       *pixels++ = (BYTE)((bits) & 0X0F);
+               }
+       } else if (bitsperpixel == 2){  // 2 bits/pixel, four pixels per byte
+               while (bytesperline-- > 0){
+                       bits = *bitplanes++;
+                       *pixels++ = (BYTE)((bits >> 6) & 0X03);
+                       *pixels++ = (BYTE)((bits >> 4) & 0X03);
+                       *pixels++ = (BYTE)((bits >> 2) & 0X03);
+                       *pixels++ = (BYTE)((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 long p,BYTE &c, BYTE &n, long &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 long p,BYTE &c, BYTE &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=(BYTE)p;
+       n++;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImagePCX::PCX_PackPlanes(BYTE* buff, const long size, CxFile &f)
+{
+    BYTE *start,*end;
+    BYTE 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(BYTE* raw, long width, BYTE* buf, long plane)
+{
+    int cbit, x, mask;
+    unsigned char *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 = ntohs(p->Xmin);
+       p->Ymin = ntohs(p->Ymin);
+       p->Xmax = ntohs(p->Xmax);
+       p->Ymax = ntohs(p->Ymax);
+       p->Hres = ntohs(p->Hres);
+       p->Vres = ntohs(p->Vres);
+       p->BytesPerLine = ntohs(p->BytesPerLine);
+       p->PaletteType = ntohs(p->PaletteType);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_PCX
index 6e18f1561b1fe844f5b9e34bd1595847f2113884..271992c7fa9df4a1e1b41ae71c998773ac16da64 100644 (file)
@@ -1,64 +1,64 @@
-/*\r
- * File:       ximapcx.h\r
- * Purpose:    PCX Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImagePCX (c) 05/Jan/2002 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * Parts of the code come from Paintlib: Copyright (c) 1996-1998 Ulrich von Zadow\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaPCX_h)\r
-#define __ximaPCX_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_PCX\r
-\r
-class CxImagePCX: public CxImage\r
-{\r
-// PCX Image File\r
-#pragma pack(1)\r
-typedef struct tagPCXHEADER\r
-{\r
-  char Manufacturer;   // always 0X0A\r
-  char Version;                        // version number\r
-  char Encoding;               // always 1\r
-  char BitsPerPixel;   // color bits\r
-  WORD Xmin, Ymin;             // image origin\r
-  WORD Xmax, Ymax;             // image dimensions\r
-  WORD Hres, Vres;             // resolution values\r
-  BYTE ColorMap[16][3];        // color palette\r
-  char Reserved;\r
-  char ColorPlanes;            // color planes\r
-  WORD BytesPerLine;   // line buffer size\r
-  WORD PaletteType;            // grey or color palette\r
-  char Filter[58];\r
-} PCXHEADER;\r
-#pragma pack()\r
-\r
-public:\r
-       CxImagePCX(): CxImage(CXIMAGE_FORMAT_PCX) {}\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_PCX);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_PCX);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-protected:\r
-       bool PCX_PlanesToPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel);\r
-       bool PCX_UnpackPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel);\r
-       void PCX_PackPixels(const long p,BYTE &c, BYTE &n, CxFile &f);\r
-       void PCX_PackPlanes(BYTE* buff, const long size, CxFile &f);\r
-       void PCX_PixelsToPlanes(BYTE* raw, long width, BYTE* buf, long plane);\r
-       void PCX_toh(PCXHEADER* p);\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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
+  WORD Xmin, Ymin;             // image origin
+  WORD Xmax, Ymax;             // image dimensions
+  WORD Hres, Vres;             // resolution values
+  BYTE ColorMap[16][3];        // color palette
+  char Reserved;
+  char ColorPlanes;            // color planes
+  WORD BytesPerLine;   // line buffer size
+  WORD 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(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel);
+       bool PCX_UnpackPixels(BYTE * pixels, BYTE * bitplanes, short bytesperline, short planes, short bitsperpixel);
+       void PCX_PackPixels(const long p,BYTE &c, BYTE &n, CxFile &f);
+       void PCX_PackPlanes(BYTE* buff, const long size, CxFile &f);
+       void PCX_PixelsToPlanes(BYTE* raw, long width, BYTE* buf, long plane);
+       void PCX_toh(PCXHEADER* p);
+};
+
+#endif
+
+#endif
index f91bf27c7e34891992f1faa578e401c66f279a70..96b92573c701a0a9dc0ae32fec69ae6326cb80f4 100644 (file)
-/*\r
- * File:       ximapng.cpp\r
- * Purpose:    Platform Independent PNG Image Class Loader and Writer\r
- * 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximapng.h"\r
-\r
-#if CXIMAGE_SUPPORT_PNG\r
-\r
-#include "ximaiter.h"\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImagePNG::ima_png_error(png_struct *png_ptr, char *message)\r
-{\r
-       strcpy(info.szLastError,message);\r
-       longjmp(png_ptr->jmpbuf, 1);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImagePNG::expand2to4bpp(BYTE* prow)\r
-{\r
-       BYTE *psrc,*pdst;\r
-       BYTE pos,idx;\r
-       for(long x=head.biWidth-1;x>=0;x--){\r
-               psrc = prow + ((2*x)>>3);\r
-               pdst = prow + ((4*x)>>3);\r
-               pos = (BYTE)(2*(3-x%4));\r
-               idx = (BYTE)((*psrc & (0x03<<pos))>>pos);\r
-               pos = (BYTE)(4*(1-x%2));\r
-               *pdst &= ~(0x0F<<pos);\r
-               *pdst |= (idx & 0x0F)<<pos;\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImagePNG::Decode(CxFile *hFile)\r
-{\r
-       png_struct *png_ptr;\r
-       png_info *info_ptr;\r
-       BYTE *row_pointers=NULL;\r
-       CImageIterator iter(this);\r
-\r
-  cx_try\r
-  {\r
-    /* Create and initialize the png_struct with the desired error handler\r
-    * functions.  If you want to use the default stderr and longjump method,\r
-    * you can supply NULL for the last three parameters.  We also supply the\r
-    * the compiler header file version, so that we know if the application\r
-    * was compiled with a compatible version of the library.  REQUIRED    */\r
-       png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,(void *)NULL,NULL,NULL);\r
-       if (png_ptr == NULL)  cx_throw("Failed to create PNG structure");\r
-\r
-       /* Allocate/initialize the memory for image information.  REQUIRED. */\r
-       info_ptr = png_create_info_struct(png_ptr);\r
-       if (info_ptr == NULL) {\r
-               png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);\r
-               cx_throw("Failed to initialize PNG info structure");\r
-       }\r
-\r
-    /* Set error handling if you are using the setjmp/longjmp method (this is\r
-    * the normal method of doing things with libpng).  REQUIRED unless you\r
-    * set up your own error handlers in the png_create_read_struct() earlier. */\r
-       if (setjmp(png_ptr->jmpbuf)) {\r
-               /* Free all of the memory associated with the png_ptr and info_ptr */\r
-               delete [] row_pointers;\r
-               png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);\r
-               cx_throw("");\r
-       }\r
-\r
-       // use custom I/O functions\r
-    png_set_read_fn(png_ptr, hFile, /*(png_rw_ptr)*/user_read_data);\r
-       png_set_error_fn(png_ptr,info.szLastError,/*(png_error_ptr)*/user_error_fn,NULL);\r
-\r
-       /* read the file information */\r
-       png_read_info(png_ptr, info_ptr);\r
-\r
-       if (info.nEscape == -1){\r
-               head.biWidth = info_ptr->width;\r
-               head.biHeight= info_ptr->height;\r
-               info.dwType = CXIMAGE_FORMAT_PNG;\r
-               longjmp(png_ptr->jmpbuf, 1);\r
-       }\r
-\r
-       /* calculate new number of channels */\r
-       int channels=0;\r
-       switch(info_ptr->color_type){\r
-       case PNG_COLOR_TYPE_GRAY:\r
-       case PNG_COLOR_TYPE_PALETTE:\r
-               channels = 1;\r
-               break;\r
-       case PNG_COLOR_TYPE_GRAY_ALPHA:\r
-               channels = 2;\r
-               break;\r
-       case PNG_COLOR_TYPE_RGB:\r
-               channels = 3;\r
-               break;\r
-       case PNG_COLOR_TYPE_RGB_ALPHA:\r
-               channels = 4;\r
-               break;\r
-       default:\r
-               strcpy(info.szLastError,"unknown PNG color type");\r
-               longjmp(png_ptr->jmpbuf, 1);\r
-       }\r
-\r
-       //find the right pixel depth used for cximage\r
-       int pixel_depth = info_ptr->pixel_depth;\r
-       if (channels == 1 && pixel_depth>8) pixel_depth=8;\r
-       if (channels == 2) pixel_depth=8;\r
-       if (channels >= 3) pixel_depth=24;\r
-\r
-       if (!Create(info_ptr->width, info_ptr->height, pixel_depth, CXIMAGE_FORMAT_PNG)){\r
-               longjmp(png_ptr->jmpbuf, 1);\r
-       }\r
-\r
-       /* get metrics */\r
-       switch (info_ptr->phys_unit_type)\r
-       {\r
-       case PNG_RESOLUTION_UNKNOWN:\r
-               SetXDPI(info_ptr->x_pixels_per_unit);\r
-               SetYDPI(info_ptr->y_pixels_per_unit);\r
-               break;\r
-       case PNG_RESOLUTION_METER:\r
-               SetXDPI((long)floor(info_ptr->x_pixels_per_unit * 254.0 / 10000.0 + 0.5));\r
-               SetYDPI((long)floor(info_ptr->y_pixels_per_unit * 254.0 / 10000.0 + 0.5));\r
-               break;\r
-       }\r
-\r
-       if (info_ptr->num_palette>0){\r
-               SetPalette((rgb_color*)info_ptr->palette,info_ptr->num_palette);\r
-               SetClrImportant(info_ptr->num_palette);\r
-       } else if (info_ptr->bit_depth ==2) { //<DP> needed for 2 bpp grayscale PNGs\r
-               SetPaletteColor(0,0,0,0);\r
-               SetPaletteColor(1,85,85,85);\r
-               SetPaletteColor(2,170,170,170);\r
-               SetPaletteColor(3,255,255,255);\r
-       } else SetGrayPalette(); //<DP> needed for grayscale PNGs\r
-       \r
-       int nshift = max(0,(info_ptr->bit_depth>>3)-1)<<3;\r
-\r
-       if (info_ptr->num_trans!=0){ //palette transparency\r
-               if (info_ptr->num_trans==1){\r
-                       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE){\r
-                               info.nBkgndIndex = info_ptr->trans_values.index;\r
-                       } else{\r
-                               info.nBkgndIndex = info_ptr->trans_values.gray>>nshift;\r
-                       }\r
-               }\r
-               if (info_ptr->num_trans>1){\r
-                       RGBQUAD* pal=GetPalette();\r
-                       if (pal){\r
-                               DWORD ip;\r
-                               for (ip=0;ip<min(head.biClrUsed,(unsigned long)info_ptr->num_trans);ip++)\r
-                                       pal[ip].rgbReserved=info_ptr->trans[ip];\r
-                               for (ip=info_ptr->num_trans;ip<head.biClrUsed;ip++){\r
-                                       pal[ip].rgbReserved=255;\r
-                               }\r
-                               info.bAlphaPaletteEnabled=true;\r
-                       }\r
-               }\r
-       }\r
-\r
-       if (channels == 3){ //check RGB binary transparency\r
-               png_bytep trans;\r
-               int num_trans;\r
-               png_color_16 *image_background;\r
-               if (png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &image_background)){\r
-                       info.nBkgndColor.rgbRed   = (BYTE)(info_ptr->trans_values.red>>nshift);\r
-                       info.nBkgndColor.rgbGreen = (BYTE)(info_ptr->trans_values.green>>nshift);\r
-                       info.nBkgndColor.rgbBlue  = (BYTE)(info_ptr->trans_values.blue>>nshift);\r
-                       info.nBkgndColor.rgbReserved = 0;\r
-                       info.nBkgndIndex = 0;\r
-               }\r
-       }\r
-\r
-       int alpha_present = (channels - 1) % 2;\r
-       if (alpha_present){\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-               AlphaCreate();\r
-#else\r
-               png_set_strip_alpha(png_ptr);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       }\r
-\r
-       // <vho> - flip the RGB pixels to BGR (or RGBA to BGRA)\r
-       if (info_ptr->color_type & PNG_COLOR_MASK_COLOR){\r
-               png_set_bgr(png_ptr);\r
-       }\r
-\r
-       // <vho> - handle cancel\r
-       if (info.nEscape) longjmp(png_ptr->jmpbuf, 1);\r
-\r
-       // row_bytes is the width x number of channels x (bit-depth / 8)\r
-       row_pointers = new BYTE[info_ptr->rowbytes + 8];\r
-\r
-       // turn on interlace handling\r
-       int number_passes = png_set_interlace_handling(png_ptr);\r
-\r
-       if (number_passes>1){\r
-               SetCodecOption(1);\r
-       } else {\r
-               SetCodecOption(0);\r
-       }\r
-\r
-       int chan_offset = info_ptr->bit_depth >> 3;\r
-       int pixel_offset = info_ptr->pixel_depth >> 3;\r
-\r
-       for (int pass=0; pass < number_passes; pass++) {\r
-               iter.Upset();\r
-               int y=0;\r
-               do      {\r
-\r
-                       // <vho> - handle cancel\r
-                       if (info.nEscape) longjmp(png_ptr->jmpbuf, 1);\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-                       if (AlphaIsValid()) {\r
-\r
-                               //compute the correct position of the line\r
-                               long ax,ay;\r
-                               ay = head.biHeight-1-y;\r
-                               BYTE* prow= iter.GetRow(ay);\r
-\r
-                               //recover data from previous scan\r
-                               if (info_ptr->interlace_type && pass>0 && pass!=7){\r
-                                       for(ax=0;ax<head.biWidth;ax++){\r
-                                               long px = ax * pixel_offset;\r
-                                               if (channels == 2){\r
-                                                       row_pointers[px] = prow[ax];\r
-                                                       row_pointers[px+chan_offset]=AlphaGet(ax,ay);\r
-                                               } else {\r
-                                                       long qx = ax * 3;\r
-                                                       row_pointers[px]              =prow[qx];\r
-                                                       row_pointers[px+chan_offset]  =prow[qx+1];\r
-                                                       row_pointers[px+chan_offset*2]=prow[qx+2];\r
-                                                       row_pointers[px+chan_offset*3]=AlphaGet(ax,ay);\r
-                                               }\r
-                                       }\r
-                               }\r
-\r
-                               //read next row\r
-                               png_read_row(png_ptr, row_pointers, NULL);\r
-\r
-                               //RGBA -> RGB + A\r
-                               for(ax=0;ax<head.biWidth;ax++){\r
-                                       long px = ax * pixel_offset;\r
-                                       if (channels == 2){\r
-                                               prow[ax] = row_pointers[px];\r
-                                               AlphaSet(ax,ay,row_pointers[px+chan_offset]);\r
-                                       } else {\r
-                                               long qx = ax * 3;\r
-                                               prow[qx]  =row_pointers[px];\r
-                                               prow[qx+1]=row_pointers[px+chan_offset];\r
-                                               prow[qx+2]=row_pointers[px+chan_offset*2];\r
-                                               AlphaSet(ax,ay,row_pointers[px+chan_offset*3]);\r
-                                       }\r
-                               }\r
-                       } else\r
-#endif // CXIMAGE_SUPPORT_ALPHA                // vho\r
-                       {\r
-                               //recover data from previous scan\r
-                               if (info_ptr->interlace_type && pass>0){\r
-                                       iter.GetRow(row_pointers, info_ptr->rowbytes);\r
-                                       //re-expand buffer for images with bit depth > 8\r
-                                       if (info_ptr->bit_depth > 8){\r
-                                               for(long ax=(head.biWidth*channels-1);ax>=0;ax--)\r
-                                                       row_pointers[ax*chan_offset] = row_pointers[ax];\r
-                                       }\r
-                               }\r
-\r
-                               //read next row\r
-                               png_read_row(png_ptr, row_pointers, NULL);\r
-\r
-                               //shrink 16 bit depth images down to 8 bits\r
-                               if (info_ptr->bit_depth > 8){\r
-                                       for(long ax=0;ax<(head.biWidth*channels);ax++)\r
-                                               row_pointers[ax] = row_pointers[ax*chan_offset];\r
-                               }\r
-\r
-                               //copy the pixels\r
-                               iter.SetRow(row_pointers, info_ptr->rowbytes);\r
-                               //<DP> expand 2 bpp images only in the last pass\r
-                               if (info_ptr->bit_depth==2 && pass==(number_passes-1))\r
-                                       expand2to4bpp(iter.GetRow());\r
-\r
-                               //go on\r
-                               iter.PrevRow();\r
-                       }\r
-\r
-                       y++;\r
-               } while(y<head.biHeight);\r
-       }\r
-\r
-       delete [] row_pointers;\r
-\r
-       /* read the rest of the file, getting any additional chunks in info_ptr */\r
-       png_read_end(png_ptr, info_ptr);\r
-\r
-       /* clean up after the read, and free any memory allocated - REQUIRED */\r
-       png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_PNG) return true;\r
-       return false;\r
-  }\r
-       /* that's it */\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImagePNG::Encode(CxFile *hFile)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       CImageIterator iter(this);\r
-       BYTE trans[256];        //for transparency (don't move)\r
-       png_struct *png_ptr;\r
-       png_info *info_ptr;\r
-\r
-  cx_try\r
-  {\r
-   /* Create and initialize the png_struct with the desired error handler\r
-    * functions.  If you want to use the default stderr and longjump method,\r
-    * you can supply NULL for the last three parameters.  We also check that\r
-    * the library version is compatible with the one used at compile time,\r
-    * in case we are using dynamically linked libraries.  REQUIRED.\r
-    */\r
-       png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,(void *)NULL,NULL,NULL);\r
-       if (png_ptr == NULL) cx_throw("Failed to create PNG structure");\r
-\r
-       /* Allocate/initialize the image information data.  REQUIRED */\r
-       info_ptr = png_create_info_struct(png_ptr);\r
-       if (info_ptr == NULL){\r
-               png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);\r
-               cx_throw("Failed to initialize PNG info structure");\r
-       }\r
-\r
-   /* Set error handling.  REQUIRED if you aren't supplying your own\r
-    * error hadnling functions in the png_create_write_struct() call.\r
-    */\r
-       if (setjmp(png_ptr->jmpbuf)){\r
-               /* If we get here, we had a problem reading the file */\r
-               if (info_ptr->palette) free(info_ptr->palette);\r
-               png_destroy_write_struct(&png_ptr,  (png_infopp)&info_ptr);\r
-               cx_throw("Error saving PNG file");\r
-       }\r
-            \r
-       /* set up the output control */\r
-       //png_init_io(png_ptr, hFile);\r
-\r
-       // use custom I/O functions\r
-    png_set_write_fn(png_ptr,hFile,/*(png_rw_ptr)*/user_write_data,/*(png_flush_ptr)*/user_flush_data);\r
-\r
-       /* set the file information here */\r
-       info_ptr->width = GetWidth();\r
-       info_ptr->height = GetHeight();\r
-       info_ptr->pixel_depth = (BYTE)GetBpp();\r
-       info_ptr->channels = (GetBpp()>8) ? (BYTE)3: (BYTE)1;\r
-       info_ptr->bit_depth = (BYTE)(GetBpp()/info_ptr->channels);\r
-       info_ptr->compression_type = info_ptr->filter_type = 0;\r
-       info_ptr->valid = 0;\r
-\r
-       switch(GetCodecOption(CXIMAGE_FORMAT_PNG)){\r
-       case 1:\r
-               info_ptr->interlace_type = PNG_INTERLACE_ADAM7;\r
-               break;\r
-       default:\r
-               info_ptr->interlace_type = PNG_INTERLACE_NONE;\r
-       }\r
-\r
-       /* set compression level */\r
-       //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);\r
-\r
-       bool bGrayScale = IsGrayScale();\r
-\r
-       if (GetNumColors()){\r
-               if (bGrayScale){\r
-                       info_ptr->color_type = PNG_COLOR_TYPE_GRAY;\r
-               } else {\r
-                       info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;\r
-               }\r
-       } else {\r
-               info_ptr->color_type = PNG_COLOR_TYPE_RGB;\r
-       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()){\r
-               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;\r
-               info_ptr->channels++;\r
-               info_ptr->bit_depth = 8;\r
-               info_ptr->pixel_depth += 8;\r
-       }\r
-#endif\r
-\r
-       /* set background */\r
-       png_color_16 image_background={ 0, 255, 255, 255, 0 };\r
-       RGBQUAD tc = GetTransColor();\r
-       if (info.nBkgndIndex>=0) {\r
-               image_background.blue  = tc.rgbBlue;\r
-               image_background.green = tc.rgbGreen;\r
-               image_background.red   = tc.rgbRed;\r
-       }\r
-       png_set_bKGD(png_ptr, info_ptr, &image_background);\r
-\r
-       /* set metrics */\r
-       png_set_pHYs(png_ptr, info_ptr, head.biXPelsPerMeter, head.biYPelsPerMeter, PNG_RESOLUTION_METER);\r
-\r
-       png_set_IHDR(png_ptr, info_ptr, info_ptr->width, info_ptr->height, info_ptr->bit_depth,\r
-                               info_ptr->color_type, info_ptr->interlace_type,\r
-                               PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);\r
-\r
-       //<DP> simple transparency\r
-       if (info.nBkgndIndex >= 0){\r
-               info_ptr->num_trans = 1;\r
-               info_ptr->valid |= PNG_INFO_tRNS;\r
-               info_ptr->trans = trans;\r
-               info_ptr->trans_values.index = (BYTE)info.nBkgndIndex;\r
-               info_ptr->trans_values.red   = tc.rgbRed;\r
-               info_ptr->trans_values.green = tc.rgbGreen;\r
-               info_ptr->trans_values.blue  = tc.rgbBlue;\r
-               info_ptr->trans_values.gray  = info_ptr->trans_values.index;\r
-\r
-               // the transparency indexes start from 0 for non grayscale palette\r
-               if (!bGrayScale && head.biClrUsed && info.nBkgndIndex)\r
-                       SwapIndex(0,(BYTE)info.nBkgndIndex);\r
-       }\r
-\r
-       /* set the palette if there is one */\r
-       if (GetPalette()){\r
-               if (!bGrayScale){\r
-                       info_ptr->valid |= PNG_INFO_PLTE;\r
-               }\r
-\r
-               int nc = GetClrImportant();\r
-               if (nc==0) nc = GetNumColors();\r
-\r
-               if (info.bAlphaPaletteEnabled){\r
-                       for(WORD ip=0; ip<nc;ip++)\r
-                               trans[ip]=GetPaletteColor((BYTE)ip).rgbReserved;\r
-                       info_ptr->num_trans = (WORD)nc;\r
-                       info_ptr->valid |= PNG_INFO_tRNS;\r
-                       info_ptr->trans = trans;\r
-               }\r
-\r
-               // copy the palette colors\r
-               info_ptr->palette = new png_color[nc];\r
-               info_ptr->num_palette = (png_uint_16) nc;\r
-               for (int i=0; i<nc; i++)\r
-                       GetPaletteColor(i, &info_ptr->palette[i].red, &info_ptr->palette[i].green, &info_ptr->palette[i].blue);\r
-       }  \r
-\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-       //Merge the transparent color with the alpha channel\r
-       if (AlphaIsValid() && head.biBitCount==24 && info.nBkgndIndex>=0){\r
-               for(long y=0; y < head.biHeight; y++){\r
-                       for(long x=0; x < head.biWidth ; x++){\r
-                               RGBQUAD c=GetPixelColor(x,y,false);\r
-                               if (*(long*)&c==*(long*)&tc)\r
-                                       AlphaSet(x,y,0);\r
-       }       }       }\r
-#endif // CXIMAGE_SUPPORT_ALPHA        // <vho>\r
-\r
-       int row_size = max(info.dwEffWidth, info_ptr->width*info_ptr->channels*(info_ptr->bit_depth/8));\r
-       info_ptr->rowbytes = row_size;\r
-       BYTE *row_pointers = new BYTE[row_size];\r
-\r
-       /* write the file information */\r
-       png_write_info(png_ptr, info_ptr);\r
-\r
-       //interlace handling\r
-       int num_pass = png_set_interlace_handling(png_ptr);\r
-       for (int pass = 0; pass < num_pass; pass++){\r
-               //write image\r
-               iter.Upset();\r
-               long ay=head.biHeight-1;\r
-               RGBQUAD c;\r
-               do      {\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-                       if (AlphaIsValid()){\r
-                               for (long ax=head.biWidth-1; ax>=0;ax--){\r
-                                       c = BlindGetPixelColor(ax,ay);\r
-                                       int px = ax * info_ptr->channels;\r
-                                       if (!bGrayScale){\r
-                                               row_pointers[px++]=c.rgbRed;\r
-                                               row_pointers[px++]=c.rgbGreen;\r
-                                       }\r
-                                       row_pointers[px++]=c.rgbBlue;\r
-                                       row_pointers[px] = AlphaGet(ax,ay);\r
-                               }\r
-                               png_write_row(png_ptr, row_pointers);\r
-                               ay--;\r
-                       }\r
-                       else\r
-#endif //CXIMAGE_SUPPORT_ALPHA // <vho>\r
-                       {\r
-                               iter.GetRow(row_pointers, row_size);\r
-                               if (info_ptr->color_type == PNG_COLOR_TYPE_RGB) //HACK BY OP\r
-                                       RGBtoBGR(row_pointers, row_size);\r
-                               png_write_row(png_ptr, row_pointers);\r
-                       }\r
-               } while(iter.PrevRow());\r
-       }\r
-\r
-       delete [] row_pointers;\r
-\r
-       //if necessary, restore the original palette\r
-       if (!bGrayScale && head.biClrUsed && info.nBkgndIndex>0)\r
-               SwapIndex((BYTE)info.nBkgndIndex,0);\r
-\r
-       /* It is REQUIRED to call this to finish writing the rest of the file */\r
-       png_write_end(png_ptr, info_ptr);\r
-\r
-       /* if you malloced the palette, free it here */\r
-       if (info_ptr->palette){\r
-               delete [] (info_ptr->palette);\r
-               info_ptr->palette = NULL;\r
-       }\r
-\r
-       /* clean up after the write, and free any memory allocated */\r
-       png_destroy_write_struct(&png_ptr, (png_infopp)&info_ptr);\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       return FALSE;\r
-  }\r
-       /* that's it */\r
-       return TRUE;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_PNG\r
+/*
+ * File:       ximapng.cpp
+ * Purpose:    Platform Independent PNG Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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);
+       longjmp(png_ptr->jmpbuf, 1);
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+void CxImagePNG::expand2to4bpp(BYTE* prow)
+{
+       BYTE *psrc,*pdst;
+       BYTE pos,idx;
+       for(long x=head.biWidth-1;x>=0;x--){
+               psrc = prow + ((2*x)>>3);
+               pdst = prow + ((4*x)>>3);
+               pos = (BYTE)(2*(3-x%4));
+               idx = (BYTE)((*psrc & (0x03<<pos))>>pos);
+               pos = (BYTE)(4*(1-x%2));
+               *pdst &= ~(0x0F<<pos);
+               *pdst |= (idx & 0x0F)<<pos;
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImagePNG::Decode(CxFile *hFile)
+{
+       png_struct *png_ptr;
+       png_info *info_ptr;
+       BYTE *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 (setjmp(png_ptr->jmpbuf)) {
+               /* 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);
+
+       if (info.nEscape == -1){
+               head.biWidth = info_ptr->width;
+               head.biHeight= info_ptr->height;
+               info.dwType = CXIMAGE_FORMAT_PNG;
+               longjmp(png_ptr->jmpbuf, 1);
+       }
+
+       /* calculate new number of channels */
+       int channels=0;
+       switch(info_ptr->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");
+               longjmp(png_ptr->jmpbuf, 1);
+       }
+
+       //find the right pixel depth used for cximage
+       int pixel_depth = info_ptr->pixel_depth;
+       if (channels == 1 && pixel_depth>8) pixel_depth=8;
+       if (channels == 2) pixel_depth=8;
+       if (channels >= 3) pixel_depth=24;
+
+       if (!Create(info_ptr->width, info_ptr->height, pixel_depth, CXIMAGE_FORMAT_PNG)){
+               longjmp(png_ptr->jmpbuf, 1);
+       }
+
+       /* get metrics */
+       switch (info_ptr->phys_unit_type)
+       {
+       case PNG_RESOLUTION_UNKNOWN:
+               SetXDPI(info_ptr->x_pixels_per_unit);
+               SetYDPI(info_ptr->y_pixels_per_unit);
+               break;
+       case PNG_RESOLUTION_METER:
+               SetXDPI((long)floor(info_ptr->x_pixels_per_unit * 254.0 / 10000.0 + 0.5));
+               SetYDPI((long)floor(info_ptr->y_pixels_per_unit * 254.0 / 10000.0 + 0.5));
+               break;
+       }
+
+       if (info_ptr->num_palette>0){
+               SetPalette((rgb_color*)info_ptr->palette,info_ptr->num_palette);
+               SetClrImportant(info_ptr->num_palette);
+       } else if (info_ptr->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,(info_ptr->bit_depth>>3)-1)<<3;
+
+       if (info_ptr->num_trans!=0){ //palette transparency
+               if (info_ptr->num_trans==1){
+                       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE){
+                               info.nBkgndIndex = info_ptr->trans_values.index;
+                       } else{
+                               info.nBkgndIndex = info_ptr->trans_values.gray>>nshift;
+                       }
+               }
+               if (info_ptr->num_trans>1){
+                       RGBQUAD* pal=GetPalette();
+                       if (pal){
+                               DWORD ip;
+                               for (ip=0;ip<min(head.biClrUsed,(unsigned long)info_ptr->num_trans);ip++)
+                                       pal[ip].rgbReserved=info_ptr->trans[ip];
+                               for (ip=info_ptr->num_trans;ip<head.biClrUsed;ip++){
+                                       pal[ip].rgbReserved=255;
+                               }
+                               info.bAlphaPaletteEnabled=true;
+                       }
+               }
+       }
+
+       if (channels == 3){ //check RGB binary transparency
+               png_bytep trans;
+               int num_trans;
+               png_color_16 *image_background;
+               if (png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &image_background)){
+                       info.nBkgndColor.rgbRed   = (BYTE)(info_ptr->trans_values.red>>nshift);
+                       info.nBkgndColor.rgbGreen = (BYTE)(info_ptr->trans_values.green>>nshift);
+                       info.nBkgndColor.rgbBlue  = (BYTE)(info_ptr->trans_values.blue>>nshift);
+                       info.nBkgndColor.rgbReserved = 0;
+                       info.nBkgndIndex = 0;
+               }
+       }
+
+       int 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 (info_ptr->color_type & PNG_COLOR_MASK_COLOR){
+               png_set_bgr(png_ptr);
+       }
+
+       // <vho> - handle cancel
+       if (info.nEscape) longjmp(png_ptr->jmpbuf, 1);
+
+       // row_bytes is the width x number of channels x (bit-depth / 8)
+       row_pointers = new BYTE[info_ptr->rowbytes + 8];
+
+       // turn on interlace handling
+       int number_passes = png_set_interlace_handling(png_ptr);
+
+       if (number_passes>1){
+               SetCodecOption(1);
+       } else {
+               SetCodecOption(0);
+       }
+
+       int chan_offset = info_ptr->bit_depth >> 3;
+       int pixel_offset = info_ptr->pixel_depth >> 3;
+
+       for (int pass=0; pass < number_passes; pass++) {
+               iter.Upset();
+               int y=0;
+               do      {
+
+                       // <vho> - handle cancel
+                       if (info.nEscape) longjmp(png_ptr->jmpbuf, 1);
+
+#if CXIMAGE_SUPPORT_ALPHA      // <vho>
+                       if (AlphaIsValid()) {
+
+                               //compute the correct position of the line
+                               long ax,ay;
+                               ay = head.biHeight-1-y;
+                               BYTE* prow= iter.GetRow(ay);
+
+                               //recover data from previous scan
+                               if (info_ptr->interlace_type && pass>0 && pass!=7){
+                                       for(ax=0;ax<head.biWidth;ax++){
+                                               long px = ax * pixel_offset;
+                                               if (channels == 2){
+                                                       row_pointers[px] = prow[ax];
+                                                       row_pointers[px+chan_offset]=AlphaGet(ax,ay);
+                                               } else {
+                                                       long 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++){
+                                       long px = ax * pixel_offset;
+                                       if (channels == 2){
+                                               prow[ax] = row_pointers[px];
+                                               AlphaSet(ax,ay,row_pointers[px+chan_offset]);
+                                       } else {
+                                               long 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 (info_ptr->interlace_type && pass>0){
+                                       iter.GetRow(row_pointers, info_ptr->rowbytes);
+                                       //re-expand buffer for images with bit depth > 8
+                                       if (info_ptr->bit_depth > 8){
+                                               for(long 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 (info_ptr->bit_depth > 8){
+                                       for(long ax=0;ax<(head.biWidth*channels);ax++)
+                                               row_pointers[ax] = row_pointers[ax*chan_offset];
+                               }
+
+                               //copy the pixels
+                               iter.SetRow(row_pointers, info_ptr->rowbytes);
+                               //<DP> expand 2 bpp images only in the last pass
+                               if (info_ptr->bit_depth==2 && pass==(number_passes-1))
+                                       expand2to4bpp(iter.GetRow());
+
+                               //go on
+                               iter.PrevRow();
+                       }
+
+                       y++;
+               } while(y<head.biHeight);
+       }
+
+       delete [] row_pointers;
+
+       /* read the rest of the file, getting any additional chunks in info_ptr */
+       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);
+       BYTE 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 = (BYTE)GetBpp();
+       info_ptr->channels = (GetBpp()>8) ? (BYTE)3: (BYTE)1;
+       info_ptr->bit_depth = (BYTE)(GetBpp()/info_ptr->channels);
+       info_ptr->compression_type = info_ptr->filter_type = 0;
+       info_ptr->valid = 0;
+
+       switch(GetCodecOption(CXIMAGE_FORMAT_PNG)){
+       case 1:
+               info_ptr->interlace_type = PNG_INTERLACE_ADAM7;
+               break;
+       default:
+               info_ptr->interlace_type = PNG_INTERLACE_NONE;
+       }
+
+       /* set compression level */
+       //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+
+       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 = trans;
+               info_ptr->trans_values.index = (BYTE)info.nBkgndIndex;
+               info_ptr->trans_values.red   = tc.rgbRed;
+               info_ptr->trans_values.green = tc.rgbGreen;
+               info_ptr->trans_values.blue  = tc.rgbBlue;
+               info_ptr->trans_values.gray  = info_ptr->trans_values.index;
+
+               // the transparency indexes start from 0 for non grayscale palette
+               if (!bGrayScale && head.biClrUsed && info.nBkgndIndex)
+                       SwapIndex(0,(BYTE)info.nBkgndIndex);
+       }
+
+       /* set the palette if there is one */
+       if (GetPalette()){
+               if (!bGrayScale){
+                       info_ptr->valid |= PNG_INFO_PLTE;
+               }
+
+               int nc = GetClrImportant();
+               if (nc==0) nc = GetNumColors();
+
+               if (info.bAlphaPaletteEnabled){
+                       for(WORD ip=0; ip<nc;ip++)
+                               trans[ip]=GetPaletteColor((BYTE)ip).rgbReserved;
+                       info_ptr->num_trans = (WORD)nc;
+                       info_ptr->valid |= PNG_INFO_tRNS;
+                       info_ptr->trans = trans;
+               }
+
+               // copy the palette colors
+               info_ptr->palette = new png_color[nc];
+               info_ptr->num_palette = (png_uint_16) nc;
+               for (int 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(long y=0; y < head.biHeight; y++){
+                       for(long x=0; x < head.biWidth ; x++){
+                               RGBQUAD c=GetPixelColor(x,y,false);
+                               if (*(long*)&c==*(long*)&tc)
+                                       AlphaSet(x,y,0);
+       }       }       }
+#endif // CXIMAGE_SUPPORT_ALPHA        // <vho>
+
+       int row_size = max(info.dwEffWidth, info_ptr->width*info_ptr->channels*(info_ptr->bit_depth/8));
+       info_ptr->rowbytes = row_size;
+       BYTE *row_pointers = new BYTE[row_size];
+
+       /* write the file information */
+       png_write_info(png_ptr, info_ptr);
+
+       //interlace handling
+       int num_pass = png_set_interlace_handling(png_ptr);
+       for (int pass = 0; pass < num_pass; pass++){
+               //write image
+               iter.Upset();
+               long ay=head.biHeight-1;
+               RGBQUAD c;
+               do      {
+#if CXIMAGE_SUPPORT_ALPHA      // <vho>
+                       if (AlphaIsValid()){
+                               for (long ax=head.biWidth-1; ax>=0;ax--){
+                                       c = BlindGetPixelColor(ax,ay);
+                                       int 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;
+
+       //if necessary, restore the original palette
+       if (!bGrayScale && head.biClrUsed && info.nBkgndIndex>0)
+               SwapIndex((BYTE)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
index 3fddf5b64febe1a7459550530031a66aeb3a16d1..abfd80b8558f0ed87afa6cd49ec5cc839a8bad04 100644 (file)
@@ -1,74 +1,74 @@
-/*\r
- * File:       ximapng.h\r
- * Purpose:    PNG Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImagePNG (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes\r
- *\r
- * original CImagePNG  and CImageIterator implementation are:\r
- * Copyright:  (c) 1995, Alejandro Aguilar Sierra <asierra(at)servidor(dot)unam(dot)mx>\r
- *\r
- * libpng Copyright (c) 1998-2003 Glenn Randers-Pehrson\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaPNG_h)\r
-#define __ximaPNG_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_PNG\r
-\r
-extern "C" {\r
-#include "../png/png.h"\r
-}\r
-\r
-class CxImagePNG: public CxImage\r
-{\r
-public:\r
-       CxImagePNG(): CxImage(CXIMAGE_FORMAT_PNG) {}\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_PNG);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_PNG);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-\r
-protected:\r
-       void ima_png_error(png_struct *png_ptr, char *message);\r
-       void expand2to4bpp(BYTE* prow);\r
-\r
-       static void PNGAPI user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)\r
-       {\r
-               CxFile* hFile = (CxFile*)png_get_io_ptr(png_ptr);\r
-               if (hFile == NULL || hFile->Read(data,1,length) != length) png_error(png_ptr, "Read Error");\r
-       }\r
-\r
-       static void PNGAPI user_write_data(png_structp png_ptr, png_bytep data, png_size_t length)\r
-       {\r
-               CxFile* hFile = (CxFile*)png_get_io_ptr(png_ptr);\r
-               if (hFile == NULL || hFile->Write(data,1,length) != length) png_error(png_ptr, "Write Error");\r
-       }\r
-\r
-       static void PNGAPI user_flush_data(png_structp png_ptr)\r
-       {\r
-               CxFile* hFile = (CxFile*)png_get_io_ptr(png_ptr);\r
-               if (hFile == NULL || !hFile->Flush()) png_error(png_ptr, "Flush Error");\r
-       }\r
-\r
-    static void PNGAPI user_error_fn(png_structp png_ptr,png_const_charp error_msg)\r
-       {\r
-               strncpy((char*)png_ptr->error_ptr,error_msg,255);\r
-               longjmp(png_ptr->jmpbuf, 1);\r
-       }\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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" {
+#include "../png/png.h"
+}
+
+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
+
+protected:
+       void ima_png_error(png_struct *png_ptr, char *message);
+       void expand2to4bpp(BYTE* 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)
+       {
+               strncpy((char*)png_ptr->error_ptr,error_msg,255);
+               longjmp(png_ptr->jmpbuf, 1);
+       }
+};
+
+#endif
+
+#endif
index ca50750206e580faffaefd342979528d14993621..71dc772d655d022aab2bb2b3e0b70275b53c11e1 100644 (file)
-/*\r
- * File:       ximaraw.cpp\r
- * Purpose:    Platform Independent RAW Image Class Loader\r
- * 16/Dec/2007 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- * \r
- * CxImageRAW (c) May/2006 pdw63\r
- *\r
- * based on dcraw.c -- Dave Coffin's raw photo decoder\r
- * Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net\r
- */\r
-\r
-#include "ximaraw.h"\r
-\r
-#if CXIMAGE_SUPPORT_RAW\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageRAW::Decode(CxFile *hFile)\r
-{\r
-       if (hFile==NULL)\r
-               return false;\r
-\r
-       DCRAW  dcr;\r
-\r
-  cx_try\r
-  {\r
-       // initialization\r
-       dcr_init_dcraw(&dcr);\r
-\r
-       dcr.opt.user_qual = GetCodecOption(CXIMAGE_FORMAT_RAW) & 0x03;\r
-\r
-       // setup variables for debugging\r
-       char szClass[] = "CxImageRAW";\r
-       dcr.ifname = szClass;\r
-       dcr.sz_error = info.szLastError;\r
-\r
-       // setup library options, see dcr_print_manual for the available switches\r
-       // call dcr_parse_command_line_options(&dcr,0,0,0) to set default options\r
-       // if (dcr_parse_command_line_options(&dcr,argc,argv,&arg))\r
-       if (dcr_parse_command_line_options(&dcr,0,0,0)){\r
-               cx_throw("CxImageRAW: unknown option");\r
-       }\r
-\r
-       // set return point for error handling\r
-       if (setjmp (dcr.failure)) {\r
-               cx_throw("");\r
-       }\r
-\r
-       // install file manager\r
-       CxFileRaw src(hFile,&dcr);\r
-\r
-       // check file header\r
-       dcr_identify(&dcr);\r
-       \r
-       if(!dcr.is_raw){\r
-               cx_throw("CxImageRAW: not a raw image");\r
-       }\r
-\r
-       if (dcr.load_raw == NULL) {\r
-               cx_throw("CxImageRAW: missing raw decoder");\r
-       }\r
-\r
-       // verify special case\r
-       if (dcr.load_raw == dcr_kodak_ycbcr_load_raw) {\r
-               dcr.height += dcr.height & 1;\r
-               dcr.width  += dcr.width  & 1;\r
-       }\r
-\r
-       if (info.nEscape == -1){\r
-               head.biWidth = dcr.width;\r
-               head.biHeight= dcr.height;\r
-               info.dwType = CXIMAGE_FORMAT_RAW;\r
-               cx_throw("output dimensions returned");\r
-       }\r
-\r
-       // shrinked decoding available and requested?\r
-       dcr.shrink = dcr.filters && (dcr.opt.half_size || dcr.opt.threshold || dcr.opt.aber[0] != 1 || dcr.opt.aber[2] != 1);\r
-       dcr.iheight = (dcr.height + dcr.shrink) >> dcr.shrink;\r
-       dcr.iwidth  = (dcr.width  + dcr.shrink) >> dcr.shrink;\r
-\r
-       // install custom camera matrix\r
-       if (dcr.opt.use_camera_matrix && dcr.cmatrix[0][0] > 0.25) {\r
-               memcpy (dcr.rgb_cam, dcr.cmatrix, sizeof dcr.cmatrix);\r
-               dcr.raw_color = 0;\r
-       }\r
-\r
-       // allocate memory for the image\r
-       dcr.image = (ushort (*)[4]) calloc (dcr.iheight*dcr.iwidth, sizeof *dcr.image);\r
-       dcr_merror (&dcr, dcr.image, szClass);\r
-\r
-       if (dcr.meta_length) {\r
-               dcr.meta_data = (char *) malloc (dcr.meta_length);\r
-               dcr_merror (&dcr, dcr.meta_data, szClass);\r
-       }\r
-\r
-       // start image decoder\r
-       hFile->Seek(dcr.data_offset, SEEK_SET);\r
-       (*dcr.load_raw)(&dcr);\r
-\r
-       // post processing\r
-       if (dcr.zero_is_bad) dcr_remove_zeroes(&dcr);\r
-\r
-       dcr_bad_pixels(&dcr);\r
-\r
-       if (dcr.opt.dark_frame) dcr_subtract (&dcr,dcr.opt.dark_frame);\r
-\r
-       dcr.quality = 2 + !dcr.fuji_width;\r
-\r
-       if (dcr.opt.user_qual >= 0) dcr.quality = dcr.opt.user_qual;\r
-\r
-       if (dcr.opt.user_black >= 0) dcr.black = dcr.opt.user_black;\r
-\r
-#ifdef COLORCHECK\r
-       dcr_colorcheck(&dcr);\r
-#endif\r
-\r
-#if RESTRICTED\r
-       if (dcr.is_foveon && !dcr.opt.document_mode) dcr_foveon_interpolate(&dcr);\r
-#endif\r
-\r
-       if (!dcr.is_foveon && dcr.opt.document_mode < 2) dcr_scale_colors(&dcr);\r
-\r
-       // pixel interpolation and filters\r
-       dcr_pre_interpolate(&dcr);\r
-\r
-       if (dcr.filters && !dcr.opt.document_mode) {\r
-               if (dcr.quality == 0)\r
-                       dcr_lin_interpolate(&dcr);\r
-               else if (dcr.quality == 1 || dcr.colors > 3)\r
-                       dcr_vng_interpolate(&dcr);\r
-               else if (dcr.quality == 2)\r
-                       dcr_ppg_interpolate(&dcr);\r
-               else\r
-                       dcr_ahd_interpolate(&dcr);\r
-       }\r
-\r
-       if (dcr.mix_green) {\r
-               long i;\r
-               for (dcr.colors=3, i=0; i < dcr.height*dcr.width; i++) {\r
-                       dcr.image[i][1] = (dcr.image[i][1] + dcr.image[i][3]) >> 1;\r
-               }\r
-       }\r
-\r
-       if (!dcr.is_foveon && dcr.colors == 3) dcr_median_filter(&dcr);\r
-\r
-       if (!dcr.is_foveon && dcr.opt.highlight == 2) dcr_blend_highlights(&dcr);\r
-\r
-       if (!dcr.is_foveon && dcr.opt.highlight > 2) dcr_recover_highlights(&dcr);\r
-\r
-       if (dcr.opt.use_fuji_rotate) dcr_fuji_rotate(&dcr);\r
-\r
-#ifndef NO_LCMS\r
-       if (dcr.opt.cam_profile) dcr_apply_profile (dcr.opt.cam_profile, dcr.opt.out_profile);\r
-#endif\r
-\r
-       // final conversion\r
-       dcr_convert_to_rgb(&dcr);\r
-\r
-       if (dcr.opt.use_fuji_rotate) dcr_stretch(&dcr);\r
-\r
-       dcr.iheight = dcr.height;\r
-       dcr.iwidth  = dcr.width;\r
-       if (dcr.flip & 4) SWAP(dcr.height,dcr.width);\r
-\r
-       // ready to transfer data from dcr.image\r
-       if (!Create(dcr.width,dcr.height,24,CXIMAGE_FORMAT_RAW)){\r
-               cx_throw("");\r
-       }\r
-\r
-       uchar  *ppm = (uchar *) calloc (dcr.width, dcr.colors*dcr.opt.output_bps/8);\r
-       ushort *ppm2 = (ushort *) ppm;\r
-       dcr_merror (&dcr, ppm, szClass);\r
-\r
-       uchar lut[0x10000];\r
-       if (dcr.opt.output_bps == 8) dcr_gamma_lut (&dcr, lut);\r
-\r
-       long c, row, col, soff, rstep, cstep;\r
-       soff  = dcr_flip_index (&dcr, 0, 0);\r
-       cstep = dcr_flip_index (&dcr, 0, 1) - soff;\r
-       rstep = dcr_flip_index (&dcr, 1, 0) - dcr_flip_index (&dcr, 0, dcr.width);\r
-       for (row=0; row < dcr.height; row++, soff += rstep) {\r
-               for (col=0; col < dcr.width; col++, soff += cstep) {\r
-                       if (dcr.opt.output_bps == 8)\r
-                               for (c=0; c < dcr.colors; c++) ppm [col*dcr.colors+c] = lut[dcr.image[soff][c]];\r
-                       else\r
-                               for (c=0; c < dcr.colors; c++) ppm2[col*dcr.colors+c] = dcr.image[soff][c];\r
-               }\r
-               if (dcr.opt.output_bps == 16 && !dcr.opt.output_tiff && htons(0x55aa) != 0x55aa)\r
-                       _swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2);\r
-\r
-               DWORD size = dcr.width * (dcr.colors*dcr.opt.output_bps/8);\r
-               RGBtoBGR(ppm,size);\r
-               memcpy(GetBits(dcr.height - 1 - row), ppm, min(size,GetEffWidth()));\r
-       }\r
-       free (ppm);\r
-\r
-\r
-       dcr_cleanup_dcraw(&dcr);\r
-\r
-  } cx_catch {\r
-\r
-       dcr_cleanup_dcraw(&dcr);\r
-\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_RAW) return true;\r
-       return false;\r
-  }\r
-       /* that's it */\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageRAW::Encode(CxFile * hFile)\r
-{\r
-       if (hFile == NULL) return false;\r
-       strcpy(info.szLastError, "Save RAW not supported");\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_RAW\r
-\r
+/*
+ * File:       ximaraw.cpp
+ * Purpose:    Platform Independent RAW Image Class Loader
+ * 16/Dec/2007 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ * 
+ * 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;
+       }
+
+       // 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);
+
+       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;
+
+#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) {
+               long 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);
+
+       long 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)
+                       _swab ((char*)ppm2, (char*)ppm2, dcr.width*dcr.colors*2);
+
+               DWORD 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;
+}
+////////////////////////////////////////////////////////////////////////////////
+#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
+
index 15b938d85895fecde45ffe9b30ea415332f823ff..c99d1c4104b7cd0f27ca1fe1d20fb9d4ca5c669e 100644 (file)
-/*\r
- * File:       ximaraw.h\r
- * Purpose:    RAW Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageRAW (c) May/2006 pdw63\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- * Special thanks to David Coffin for dcraw without which this class would not exist\r
- *\r
- * libdcr (c) Dec/2007 Davide Pizzolato - www.xdp.it\r
- *\r
- * based on dcraw.c -- Dave Coffin's raw photo decoder\r
- * Copyright 1997-2007 by Dave Coffin, dcoffin a cybercom o net\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaRAW_h)\r
-#define __ximaRAW_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_RAW\r
-\r
-extern "C" {\r
- #include "../raw/libdcr.h"\r
-}\r
-\r
-class CxImageRAW: public CxImage\r
-{\r
-\r
-public:\r
-       CxImageRAW(): CxImage(CXIMAGE_FORMAT_RAW) {}\r
-\r
-//     bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_ICO);}\r
-//     bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_ICO);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-\r
-       enum CODEC_OPTION\r
-       {\r
-               DECODE_QUALITY_LIN = 0x00,\r
-               DECODE_QUALITY_VNG = 0x01,\r
-               DECODE_QUALITY_PPG = 0x02,\r
-               DECODE_QUALITY_AHD = 0x03,\r
-       }; \r
-\r
-protected:\r
-\r
-       class CxFileRaw\r
-       {\r
-       public:\r
-               CxFileRaw(CxFile* pFile,DCRAW *stream)\r
-               {\r
-                       stream->obj_ = pFile;\r
-\r
-                       ras_stream_CxFile.read_ = raw_sfile_read;\r
-                       ras_stream_CxFile.write_ = raw_sfile_write;\r
-                       ras_stream_CxFile.seek_ = raw_sfile_seek;\r
-                       ras_stream_CxFile.close_ = raw_sfile_close;\r
-                       ras_stream_CxFile.gets_ = raw_sfile_gets;\r
-                       ras_stream_CxFile.eof_ = raw_sfile_eof;\r
-                       ras_stream_CxFile.tell_ = raw_sfile_tell;\r
-                       ras_stream_CxFile.getc_ = raw_sfile_getc;\r
-                       ras_stream_CxFile.scanf_ = raw_sfile_scanf;\r
-\r
-                       stream->ops_ = &ras_stream_CxFile;\r
-\r
-               }\r
-\r
-               static int raw_sfile_read(dcr_stream_obj *obj, void *buf, int size, int cnt)\r
-               {       return ((CxFile*)obj)->Read(buf,size,cnt); }\r
-\r
-               static int raw_sfile_write(dcr_stream_obj *obj, void *buf, int size, int cnt)\r
-               {       return ((CxFile*)obj)->Write(buf,size,cnt); }\r
-\r
-               static long raw_sfile_seek(dcr_stream_obj *obj, long offset, int origin)\r
-               {       return ((CxFile*)obj)->Seek(offset,origin); }\r
-\r
-               static int raw_sfile_close(dcr_stream_obj *obj)\r
-               {       return 1; /*((CxFile*)obj)->Close();*/ }\r
-\r
-               static char* raw_sfile_gets(dcr_stream_obj *obj, char *string, int n)\r
-               {       return ((CxFile*)obj)->GetS(string,n); }\r
-\r
-               static int   raw_sfile_eof(dcr_stream_obj *obj)\r
-               {       return ((CxFile*)obj)->Eof(); }\r
-\r
-               static long  raw_sfile_tell(dcr_stream_obj *obj)\r
-               {       return ((CxFile*)obj)->Tell(); }\r
-\r
-               static int   raw_sfile_getc(dcr_stream_obj *obj)\r
-               {       return ((CxFile*)obj)->GetC(); }\r
-\r
-               static int   raw_sfile_scanf(dcr_stream_obj *obj,const char *format, void* output)\r
-               {       return ((CxFile*)obj)->Scanf(format, output); }\r
-\r
-       private:\r
-               dcr_stream_ops ras_stream_CxFile;\r
-       };\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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_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 int raw_sfile_read(dcr_stream_obj *obj, void *buf, int size, int cnt)
+               {       return ((CxFile*)obj)->Read(buf,size,cnt); }
+
+               static int raw_sfile_write(dcr_stream_obj *obj, void *buf, int size, int cnt)
+               {       return ((CxFile*)obj)->Write(buf,size,cnt); }
+
+               static long raw_sfile_seek(dcr_stream_obj *obj, long offset, int origin)
+               {       return ((CxFile*)obj)->Seek(offset,origin); }
+
+               static int raw_sfile_close(dcr_stream_obj *obj)
+               {       return 1; /*((CxFile*)obj)->Close();*/ }
+
+               static char* raw_sfile_gets(dcr_stream_obj *obj, char *string, int n)
+               {       return ((CxFile*)obj)->GetS(string,n); }
+
+               static int   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 int   raw_sfile_getc(dcr_stream_obj *obj)
+               {       return ((CxFile*)obj)->GetC(); }
+
+               static int   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
index bf61078ab425939a3d9f0f49a79e92c5e13ac4fd..3a7c9a1845be59b8e90f7a23c651ad48e5134060 100644 (file)
-// xImaSel.cpp : Selection functions\r
-/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if the image has a valid selection.\r
- */\r
-bool CxImage::SelectionIsValid()\r
-{\r
-       return pSelection!=0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Gets the smallest rectangle that contains the selection \r
- */\r
-void CxImage::SelectionGetBox(RECT& r)\r
-{\r
-       memcpy(&r,&info.rSelectionBox,sizeof(RECT));\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Empties the selection.\r
- */\r
-bool CxImage::SelectionClear(BYTE level)\r
-{\r
-       if (pSelection){\r
-               if (level==0){\r
-                       memset(pSelection,0,head.biWidth * head.biHeight);\r
-                       info.rSelectionBox.left = head.biWidth;\r
-                       info.rSelectionBox.bottom = head.biHeight;\r
-                       info.rSelectionBox.right = info.rSelectionBox.top = 0;\r
-               } else {\r
-                       memset(pSelection,level,head.biWidth * head.biHeight);\r
-                       info.rSelectionBox.right = head.biWidth;\r
-                       info.rSelectionBox.top = head.biHeight;\r
-                       info.rSelectionBox.left = info.rSelectionBox.bottom = 0;\r
-               }\r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Allocates an empty selection.\r
- */\r
-bool CxImage::SelectionCreate()\r
-{\r
-       SelectionDelete();\r
-       pSelection = (BYTE*)calloc(head.biWidth * head.biHeight, 1);\r
-       return (pSelection!=0);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Deallocates the selction.\r
- */\r
-bool CxImage::SelectionDelete()\r
-{\r
-       if (pSelection){\r
-               free(pSelection);\r
-               pSelection=NULL;\r
-       }\r
-       info.rSelectionBox.left = head.biWidth;\r
-       info.rSelectionBox.bottom = head.biHeight;\r
-       info.rSelectionBox.right = info.rSelectionBox.top = 0;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if the coordinates are inside the selection.\r
- */\r
-bool CxImage::SelectionIsInside(long x, long y)\r
-{\r
-       if (IsInside(x,y)){\r
-               if (pSelection==NULL) return true;\r
-               return pSelection[x+y*head.biWidth]!=0;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Checks if the coordinates are inside the selection.\r
- * "blind" version assumes that (x,y) is inside to the image.\r
- */\r
-bool CxImage::BlindSelectionIsInside(long x, long y)\r
-{\r
-#ifdef _DEBUG\r
-       if (!IsInside(x,y))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return 0;\r
-  #endif\r
-#endif\r
-       if (pSelection==NULL) return true;\r
-       return pSelection[x+y*head.biWidth]!=0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adds a rectangle to the existing selection.\r
- */\r
-bool CxImage::SelectionAddRect(RECT r, BYTE level)\r
-{\r
-       if (pSelection==NULL) SelectionCreate();\r
-       if (pSelection==NULL) return false;\r
-\r
-       RECT r2;\r
-       if (r.left<r.right) {r2.left=r.left; r2.right=r.right; } else {r2.left=r.right ; r2.right=r.left; }\r
-       if (r.bottom<r.top) {r2.bottom=r.bottom; r2.top=r.top; } else {r2.bottom=r.top ; r2.top=r.bottom; }\r
-\r
-       if (info.rSelectionBox.top <= r2.top) info.rSelectionBox.top = max(0L,min(head.biHeight,r2.top+1));\r
-       if (info.rSelectionBox.left > r2.left) info.rSelectionBox.left = max(0L,min(head.biWidth,r2.left));\r
-       if (info.rSelectionBox.right <= r2.right) info.rSelectionBox.right = max(0L,min(head.biWidth,r2.right+1));\r
-       if (info.rSelectionBox.bottom > r2.bottom) info.rSelectionBox.bottom = max(0L,min(head.biHeight,r2.bottom));\r
-\r
-       long ymin = max(0L,min(head.biHeight,r2.bottom));\r
-       long ymax = max(0L,min(head.biHeight,r2.top+1));\r
-       long xmin = max(0L,min(head.biWidth,r2.left));\r
-       long xmax = max(0L,min(head.biWidth,r2.right+1));\r
-\r
-       for (long y=ymin; y<ymax; y++)\r
-               memset(pSelection + xmin + y * head.biWidth, level, xmax-xmin);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adds an ellipse to the existing selection.\r
- */\r
-bool CxImage::SelectionAddEllipse(RECT r, BYTE level)\r
-{\r
-       if (pSelection==NULL) SelectionCreate();\r
-       if (pSelection==NULL) return false;\r
-\r
-       long xradius = abs(r.right - r.left)/2;\r
-       long yradius = abs(r.top - r.bottom)/2;\r
-       if (xradius==0 || yradius==0) return false;\r
-\r
-       long xcenter = (r.right + r.left)/2;\r
-       long ycenter = (r.top + r.bottom)/2;\r
-\r
-       if (info.rSelectionBox.left > (xcenter - xradius)) info.rSelectionBox.left = max(0L,min(head.biWidth,(xcenter - xradius)));\r
-       if (info.rSelectionBox.right <= (xcenter + xradius)) info.rSelectionBox.right = max(0L,min(head.biWidth,(xcenter + xradius + 1)));\r
-       if (info.rSelectionBox.bottom > (ycenter - yradius)) info.rSelectionBox.bottom = max(0L,min(head.biHeight,(ycenter - yradius)));\r
-       if (info.rSelectionBox.top <= (ycenter + yradius)) info.rSelectionBox.top = max(0L,min(head.biHeight,(ycenter + yradius + 1)));\r
-\r
-       long xmin = max(0L,min(head.biWidth,xcenter - xradius));\r
-       long xmax = max(0L,min(head.biWidth,xcenter + xradius + 1));\r
-       long ymin = max(0L,min(head.biHeight,ycenter - yradius));\r
-       long ymax = max(0L,min(head.biHeight,ycenter + yradius + 1));\r
-\r
-       long y,yo;\r
-       for (y=ymin; y<min(ycenter,ymax); y++){\r
-               for (long x=xmin; x<xmax; x++){\r
-                       yo = (long)(ycenter - yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2)));\r
-                       if (yo<y) pSelection[x + y * head.biWidth] = level;\r
-               }\r
-       }\r
-       for (y=ycenter; y<ymax; y++){\r
-               for (long x=xmin; x<xmax; x++){\r
-                       yo = (long)(ycenter + yradius * sqrt(1-pow((float)(x - xcenter)/(float)xradius,2)));\r
-                       if (yo>y) pSelection[x + y * head.biWidth] = level;\r
-               }\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Inverts the selection.\r
- * Note: the SelectionBox is set to "full image", call SelectionGetBox before (if necessary)\r
- */\r
-bool CxImage::SelectionInvert()\r
-{\r
-       if (pSelection) {\r
-               BYTE *iSrc=pSelection;\r
-               long n=head.biHeight*head.biWidth;\r
-               for(long i=0; i < n; i++){\r
-                       *iSrc=(BYTE)~(*(iSrc));\r
-                       iSrc++;\r
-               }\r
-\r
-               SelectionRebuildBox();\r
-\r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Imports an existing region from another image with the same width and height.\r
- */\r
-bool CxImage::SelectionCopy(CxImage &from)\r
-{\r
-       if (from.pSelection == NULL || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight) return false;\r
-       if (pSelection==NULL) pSelection = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-       if (pSelection==NULL) return false;\r
-       memcpy(pSelection,from.pSelection,head.biWidth * head.biHeight);\r
-       memcpy(&info.rSelectionBox,&from.info.rSelectionBox,sizeof(RECT));\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adds a polygonal region to the existing selection. points points to an array of POINT structures.\r
- * Each structure specifies the x-coordinate and y-coordinate of one vertex of the polygon.\r
- * npoints specifies the number of POINT structures in the array pointed to by points.\r
- */\r
-bool CxImage::SelectionAddPolygon(POINT *points, long npoints, BYTE level)\r
-{\r
-       if (points==NULL || npoints<3) return false;\r
-\r
-       if (pSelection==NULL) SelectionCreate();\r
-       if (pSelection==NULL) return false;\r
-\r
-       BYTE* plocal = (BYTE*)calloc(head.biWidth*head.biHeight, 1);\r
-       RECT localbox = {head.biWidth,0,0,head.biHeight};\r
-\r
-       long x,y,i=0;\r
-       POINT *current;\r
-       POINT *next = NULL;\r
-       POINT *start = NULL;\r
-       //trace contour\r
-       while (i < npoints){\r
-               current = &points[i];\r
-               if (current->x!=-1){\r
-                       if (i==0 || (i>0 && points[i-1].x==-1)) start = &points[i];\r
-\r
-                       if ((i+1)==npoints || points[i+1].x==-1)\r
-                               next = start;\r
-                       else\r
-                               next = &points[i+1];\r
-\r
-                       float beta;\r
-                       if (current->x != next->x){\r
-                               beta = (float)(next->y - current->y)/(float)(next->x - current->x);\r
-                               if (current->x < next->x){\r
-                                       for (x=current->x; x<=next->x; x++){\r
-                                               y = (long)(current->y + (x - current->x) * beta);\r
-                                               if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;\r
-                                       }\r
-                               } else {\r
-                                       for (x=current->x; x>=next->x; x--){\r
-                                               y = (long)(current->y + (x - current->x) * beta);\r
-                                               if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;\r
-                                       }\r
-                               }\r
-                       }\r
-                       if (current->y != next->y){\r
-                               beta = (float)(next->x - current->x)/(float)(next->y - current->y);\r
-                               if (current->y < next->y){\r
-                                       for (y=current->y; y<=next->y; y++){\r
-                                               x = (long)(current->x + (y - current->y) * beta);\r
-                                               if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;\r
-                                       }\r
-                               } else {\r
-                                       for (y=current->y; y>=next->y; y--){\r
-                                               x = (long)(current->x + (y - current->y) * beta);\r
-                                               if (IsInside(x,y)) plocal[x + y * head.biWidth] = 255;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-\r
-               RECT r2;\r
-               if (current->x < next->x) {r2.left=current->x; r2.right=next->x; } else {r2.left=next->x ; r2.right=current->x; }\r
-               if (current->y < next->y) {r2.bottom=current->y; r2.top=next->y; } else {r2.bottom=next->y ; r2.top=current->y; }\r
-               if (localbox.top < r2.top) localbox.top = max(0L,min(head.biHeight-1,r2.top+1));\r
-               if (localbox.left > r2.left) localbox.left = max(0L,min(head.biWidth-1,r2.left-1));\r
-               if (localbox.right < r2.right) localbox.right = max(0L,min(head.biWidth-1,r2.right+1));\r
-               if (localbox.bottom > r2.bottom) localbox.bottom = max(0L,min(head.biHeight-1,r2.bottom-1));\r
-\r
-               i++;\r
-       }\r
-\r
-       //fill the outer region\r
-       long npix=(localbox.right - localbox.left)*(localbox.top - localbox.bottom);\r
-       POINT* pix = (POINT*)calloc(npix,sizeof(POINT));\r
-       BYTE back=0, mark=1;\r
-       long fx, fy, fxx, fyy, first, last;\r
-       long xmin = 0;\r
-       long xmax = 0;\r
-       long ymin = 0;\r
-       long ymax = 0;\r
-\r
-       for (int side=0; side<4; side++){\r
-               switch(side){\r
-               case 0:\r
-                       xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.bottom+1;\r
-                       break;\r
-               case 1:\r
-                       xmin=localbox.right; xmax=localbox.right+1; ymin=localbox.bottom; ymax=localbox.top+1;\r
-                       break;\r
-               case 2:\r
-                       xmin=localbox.left; xmax=localbox.right+1; ymin=localbox.top; ymax=localbox.top+1;\r
-                       break;\r
-               case 3:\r
-                       xmin=localbox.left; xmax=localbox.left+1; ymin=localbox.bottom; ymax=localbox.top+1;\r
-                       break;\r
-               }\r
-               //fill from the border points\r
-               for(y=ymin;y<ymax;y++){\r
-                       for(x=xmin;x<xmax;x++){\r
-                               if (plocal[x+y*head.biWidth]==0){\r
-                                       // Subject: FLOOD FILL ROUTINE              Date: 12-23-97 (00:57)       \r
-                                       // Author:  Petter Holmberg                 Code: QB, QBasic, PDS        \r
-                                       // Origin:  petter.holmberg@usa.net         Packet: GRAPHICS.ABC\r
-                                       first=0;\r
-                                       last=1;\r
-                                       while(first!=last){\r
-                                               fx = pix[first].x;\r
-                                               fy = pix[first].y;\r
-                                               fxx = fx + x;\r
-                                               fyy = fy + y;\r
-                                               for(;;)\r
-                                               {\r
-                                                       if ((plocal[fxx + fyy*head.biWidth] == back) &&\r
-                                                               fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top )\r
-                                                       {\r
-                                                               plocal[fxx + fyy*head.biWidth] = mark;\r
-                                                               if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){\r
-                                                                       pix[last].x = fx;\r
-                                                                       pix[last].y = fy - 1;\r
-                                                                       last++;\r
-                                                                       if (last == npix) last = 0;\r
-                                                               }\r
-                                                               if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){\r
-                                                                       pix[last].x = fx;\r
-                                                                       pix[last].y = fy + 1;\r
-                                                                       last++;\r
-                                                                       if (last == npix) last = 0;\r
-                                                               }\r
-                                                       } else {\r
-                                                               break;\r
-                                                       }\r
-                                                       fx++;\r
-                                                       fxx++;\r
-                                               };\r
-\r
-                                               fx = pix[first].x - 1;\r
-                                               fy = pix[first].y;\r
-                                               fxx = fx + x;\r
-                                               fyy = fy + y;\r
-\r
-                                               for( ;; )\r
-                                               {\r
-                                                       if ((plocal[fxx + fyy*head.biWidth] == back) &&\r
-                                                               fxx>=localbox.left && fxx<=localbox.right && fyy>=localbox.bottom && fyy<=localbox.top )\r
-                                                       {\r
-                                                               plocal[fxx + (y + fy)*head.biWidth] = mark;\r
-                                                               if (fyy > 0 && plocal[fxx + (fyy - 1)*head.biWidth] == back){\r
-                                                                       pix[last].x = fx;\r
-                                                                       pix[last].y = fy - 1;\r
-                                                                       last++;\r
-                                                                       if (last == npix) last = 0;\r
-                                                               }\r
-                                                               if ((fyy + 1)<head.biHeight && plocal[fxx + (fyy + 1)*head.biWidth] == back){\r
-                                                                       pix[last].x = fx;\r
-                                                                       pix[last].y = fy + 1;\r
-                                                                       last++;\r
-                                                                       if (last == npix) last = 0;\r
-                                                               }\r
-                                                       } else {\r
-                                                               break;\r
-                                                       }\r
-                                                       fx--;\r
-                                                       fxx--;\r
-                                               }\r
-                                               \r
-                                               first++;\r
-                                               if (first == npix) first = 0;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       //transfer the region\r
-       long yoffset;\r
-       for (y=localbox.bottom; y<=localbox.top; y++){\r
-               yoffset = y * head.biWidth;\r
-               for (x=localbox.left; x<=localbox.right; x++)\r
-                       if (plocal[x + yoffset]!=1) pSelection[x + yoffset]=level;\r
-       }\r
-       if (info.rSelectionBox.top <= localbox.top) info.rSelectionBox.top = min(head.biHeight,localbox.top + 1);\r
-       if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = min(head.biWidth,localbox.left);\r
-       if (info.rSelectionBox.right <= localbox.right) info.rSelectionBox.right = min(head.biWidth,localbox.right + 1);\r
-       if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = min(head.biHeight,localbox.bottom);\r
-\r
-       free(plocal);\r
-       free(pix);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adds to the selection all the pixels matching the specified color.\r
- */\r
-bool CxImage::SelectionAddColor(RGBQUAD c, BYTE level)\r
-{\r
-    if (pSelection==NULL) SelectionCreate();\r
-       if (pSelection==NULL) return false;\r
-\r
-       RECT localbox = {head.biWidth,0,0,head.biHeight};\r
-\r
-    for (long y = 0; y < head.biHeight; y++){\r
-        for (long x = 0; x < head.biWidth; x++){\r
-            RGBQUAD color = BlindGetPixelColor(x, y);\r
-            if (color.rgbRed   == c.rgbRed &&\r
-                               color.rgbGreen == c.rgbGreen &&\r
-                color.rgbBlue  == c.rgbBlue)\r
-            {\r
-                pSelection[x + y * head.biWidth] = level;\r
-\r
-                               if (localbox.top < y) localbox.top = y;\r
-                               if (localbox.left > x) localbox.left = x;\r
-                               if (localbox.right < x) localbox.right = x;\r
-                               if (localbox.bottom > y) localbox.bottom = y;\r
-            }\r
-        }\r
-    }\r
-\r
-       if (info.rSelectionBox.top <= localbox.top) info.rSelectionBox.top = localbox.top + 1;\r
-       if (info.rSelectionBox.left > localbox.left) info.rSelectionBox.left = localbox.left;\r
-       if (info.rSelectionBox.right <= localbox.right) info.rSelectionBox.right = localbox.right + 1;\r
-       if (info.rSelectionBox.bottom > localbox.bottom) info.rSelectionBox.bottom = localbox.bottom;\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Adds a single pixel to the existing selection.\r
- */\r
-bool CxImage::SelectionAddPixel(long x, long y, BYTE level)\r
-{\r
-    if (pSelection==NULL) SelectionCreate();\r
-       if (pSelection==NULL) return false;\r
-\r
-    if (IsInside(x,y)) {\r
-        pSelection[x + y * head.biWidth] = level; // set the correct mask bit\r
-\r
-               if (info.rSelectionBox.top <= y) info.rSelectionBox.top = y+1;\r
-               if (info.rSelectionBox.left > x) info.rSelectionBox.left = x;\r
-               if (info.rSelectionBox.right <= x) info.rSelectionBox.right = x+1;\r
-               if (info.rSelectionBox.bottom > y) info.rSelectionBox.bottom = y;\r
-\r
-        return true;\r
-    }\r
-\r
-    return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Exports the selection channel in a 8bpp grayscale image.\r
- */\r
-bool CxImage::SelectionSplit(CxImage *dest)\r
-{\r
-       if (!pSelection || !dest) return false;\r
-\r
-       CxImage tmp(head.biWidth,head.biHeight,8);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       for(long y=0; y<head.biHeight; y++){\r
-               for(long x=0; x<head.biWidth; x++){\r
-                       tmp.BlindSetPixelIndex(x,y,pSelection[x+y*head.biWidth]);\r
-               }\r
-       }\r
-\r
-       tmp.SetGrayPalette();\r
-       dest->Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Creates the selection channel from a gray scale image.\r
- * black = unselected\r
- */\r
-bool CxImage::SelectionSet(CxImage &from)\r
-{\r
-       if (!from.IsGrayScale() || head.biWidth != from.head.biWidth || head.biHeight != from.head.biHeight){\r
-               strcpy(info.szLastError,"CxImage::SelectionSet: wrong width or height, or image is not gray scale");\r
-               return false;\r
-       }\r
-\r
-       if (pSelection==NULL) pSelection = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-\r
-       BYTE* src = from.info.pImage;\r
-       BYTE* dst = pSelection;\r
-       if (src==NULL || dst==NULL){\r
-               strcpy(info.szLastError,"CxImage::SelectionSet: null pointer");\r
-               return false;\r
-       }\r
-\r
-       for (long y=0; y<head.biHeight; y++){\r
-               memcpy(dst,src,head.biWidth);\r
-               dst += head.biWidth;\r
-               src += from.info.dwEffWidth;\r
-       }\r
-\r
-       SelectionRebuildBox();\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Sets the Selection level for a single pixel\r
- * internal use only: doesn't set SelectionBox. Use SelectionAddPixel\r
- */\r
-void CxImage::SelectionSet(const long x,const long y,const BYTE level)\r
-{\r
-       if (pSelection && IsInside(x,y)) pSelection[x+y*head.biWidth]=level;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Gets the Selection level for a single pixel \r
- */\r
-BYTE CxImage::SelectionGet(const long x,const long y)\r
-{\r
-       if (pSelection && IsInside(x,y)) return pSelection[x+y*head.biWidth];\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Rebuilds the SelectionBox \r
- */\r
-void CxImage::SelectionRebuildBox()\r
-{\r
-       info.rSelectionBox.left = head.biWidth;\r
-       info.rSelectionBox.bottom = head.biHeight;\r
-       info.rSelectionBox.right = info.rSelectionBox.top = 0;\r
-\r
-       if (!pSelection)\r
-               return;\r
-\r
-       long x,y;\r
-\r
-       for (y=0; y<head.biHeight; y++){\r
-               for (x=0; x<info.rSelectionBox.left; x++){\r
-                       if (pSelection[x+y*head.biWidth]){\r
-                               info.rSelectionBox.left = x;\r
-                               continue;\r
-                       }\r
-               }\r
-       }\r
-\r
-       for (y=0; y<head.biHeight; y++){\r
-               for (x=head.biWidth-1; x>=info.rSelectionBox.right; x--){\r
-                       if (pSelection[x+y*head.biWidth]){\r
-                               info.rSelectionBox.right = x+1;\r
-                               continue;\r
-                       }\r
-               }\r
-       }\r
-\r
-       for (x=0; x<head.biWidth; x++){\r
-               for (y=0; y<info.rSelectionBox.bottom; y++){\r
-                       if (pSelection[x+y*head.biWidth]){\r
-                               info.rSelectionBox.bottom = y;\r
-                               continue;\r
-                       }\r
-               }\r
-       }\r
-\r
-       for (x=0; x<head.biWidth; x++){\r
-               for (y=head.biHeight-1; y>=info.rSelectionBox.top; y--){\r
-                       if (pSelection[x+y*head.biWidth]){\r
-                               info.rSelectionBox.top = y+1;\r
-                               continue;\r
-                       }\r
-               }\r
-       }\r
-\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Gets the Selection level for a single pixel \r
- * "blind" version assumes that (x,y) is inside to the image.\r
- */\r
-BYTE CxImage::BlindSelectionGet(const long x,const long y)\r
-{\r
-#ifdef _DEBUG\r
-       if (!IsInside(x,y) || (pSelection==0))\r
-  #if CXIMAGE_SUPPORT_EXCEPTION_HANDLING\r
-               throw 0;\r
-  #else\r
-               return 0;\r
-  #endif\r
-#endif\r
-       return pSelection[x+y*head.biWidth];\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Returns pointer to selection data for pixel (x,y).\r
- */\r
-BYTE* CxImage::SelectionGetPointer(const long x,const long y)\r
-{\r
-       if (pSelection && IsInside(x,y)) return pSelection+x+y*head.biWidth;\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::SelectionFlip()\r
-{\r
-       if (!pSelection) return false;\r
-\r
-       BYTE *buff = (BYTE*)malloc(head.biWidth);\r
-       if (!buff) return false;\r
-\r
-       BYTE *iSrc,*iDst;\r
-       iSrc = pSelection + (head.biHeight-1)*head.biWidth;\r
-       iDst = pSelection;\r
-       for (long i=0; i<(head.biHeight/2); ++i)\r
-       {\r
-               memcpy(buff, iSrc, head.biWidth);\r
-               memcpy(iSrc, iDst, head.biWidth);\r
-               memcpy(iDst, buff, head.biWidth);\r
-               iSrc-=head.biWidth;\r
-               iDst+=head.biWidth;\r
-       }\r
-\r
-       free(buff);\r
-\r
-       long top = info.rSelectionBox.top;\r
-       info.rSelectionBox.top = head.biHeight - info.rSelectionBox.bottom;\r
-       info.rSelectionBox.bottom = head.biHeight - top;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::SelectionMirror()\r
-{\r
-       if (!pSelection) return false;\r
-       BYTE* pSelection2 = (BYTE*)malloc(head.biWidth * head.biHeight);\r
-       if (!pSelection2) return false;\r
-       \r
-       BYTE *iSrc,*iDst;\r
-       long wdt=head.biWidth-1;\r
-       iSrc=pSelection + wdt;\r
-       iDst=pSelection2;\r
-       for(long y=0; y < head.biHeight; y++){\r
-               for(long x=0; x <= wdt; x++)\r
-                       *(iDst+x)=*(iSrc-x);\r
-               iSrc+=head.biWidth;\r
-               iDst+=head.biWidth;\r
-       }\r
-       free(pSelection);\r
-       pSelection=pSelection2;\r
-       \r
-       long left = info.rSelectionBox.left;\r
-       info.rSelectionBox.left = head.biWidth - info.rSelectionBox.right;\r
-       info.rSelectionBox.right = head.biWidth - left;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_WINDOWS\r
-/**\r
- * Converts the selection in a HRGN object.\r
- */\r
-bool CxImage::SelectionToHRGN(HRGN& region)\r
-{\r
-       if (pSelection && region){           \r
-        for(int y = 0; y < head.biHeight; y++){\r
-            HRGN hTemp = NULL;\r
-            int iStart = -1;\r
-            int x = 0;\r
-                       for(; x < head.biWidth; x++){\r
-                if (pSelection[x + y * head.biWidth] != 0){\r
-                                       if (iStart == -1) iStart = x;\r
-                                       continue;\r
-                }else{\r
-                    if (iStart >= 0){\r
-                        hTemp = CreateRectRgn(iStart, y, x, y + 1);\r
-                        CombineRgn(region, hTemp, region, RGN_OR);\r
-                        DeleteObject(hTemp);\r
-                        iStart = -1;\r
-                    }\r
-                }\r
-            }\r
-            if (iStart >= 0){\r
-                hTemp = CreateRectRgn(iStart, y, x, y + 1);\r
-                CombineRgn(region, hTemp, region, RGN_OR);\r
-                DeleteObject(hTemp);\r
-                iStart = -1;\r
-            }\r
-        }\r
-               return true;\r
-    }\r
-       return false;\r
-}\r
-#endif //CXIMAGE_SUPPORT_WINDOWS\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
+// xImaSel.cpp : Selection functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximage.h"
+
+#if CXIMAGE_SUPPORT_SELECTION
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Checks if the image has a valid selection.
+ */
+bool CxImage::SelectionIsValid()
+{
+       return pSelection!=0;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * 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(BYTE 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 = (BYTE*)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(long x, long 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(long x, long 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, BYTE 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));
+
+       long ymin = max(0L,min(head.biHeight,r2.bottom));
+       long ymax = max(0L,min(head.biHeight,r2.top+1));
+       long xmin = max(0L,min(head.biWidth,r2.left));
+       long xmax = max(0L,min(head.biWidth,r2.right+1));
+
+       for (long 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, BYTE level)
+{
+       if (pSelection==NULL) SelectionCreate();
+       if (pSelection==NULL) return false;
+
+       long xradius = abs(r.right - r.left)/2;
+       long yradius = abs(r.top - r.bottom)/2;
+       if (xradius==0 || yradius==0) return false;
+
+       long xcenter = (r.right + r.left)/2;
+       long 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)));
+
+       long xmin = max(0L,min(head.biWidth,xcenter - xradius));
+       long xmax = max(0L,min(head.biWidth,xcenter + xradius + 1));
+       long ymin = max(0L,min(head.biHeight,ycenter - yradius));
+       long ymax = max(0L,min(head.biHeight,ycenter + yradius + 1));
+
+       long y,yo;
+       for (y=ymin; y<min(ycenter,ymax); y++){
+               for (long x=xmin; x<xmax; x++){
+                       yo = (long)(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 (long x=xmin; x<xmax; x++){
+                       yo = (long)(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) {
+               BYTE *iSrc=pSelection;
+               long n=head.biHeight*head.biWidth;
+               for(long i=0; i < n; i++){
+                       *iSrc=(BYTE)~(*(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 = (BYTE*)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, long npoints, BYTE level)
+{
+       if (points==NULL || npoints<3) return false;
+
+       if (pSelection==NULL) SelectionCreate();
+       if (pSelection==NULL) return false;
+
+       BYTE* plocal = (BYTE*)calloc(head.biWidth*head.biHeight, 1);
+       RECT localbox = {head.biWidth,0,0,head.biHeight};
+
+       long 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 = (long)(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 = (long)(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 = (long)(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 = (long)(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
+       long npix=(localbox.right - localbox.left)*(localbox.top - localbox.bottom);
+       POINT* pix = (POINT*)calloc(npix,sizeof(POINT));
+       BYTE back=0, mark=1;
+       long fx, fy, fxx, fyy, first, last;
+       long xmin = 0;
+       long xmax = 0;
+       long ymin = 0;
+       long ymax = 0;
+
+       for (int 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
+       long 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, BYTE level)
+{
+    if (pSelection==NULL) SelectionCreate();
+       if (pSelection==NULL) return false;
+
+       RECT localbox = {head.biWidth,0,0,head.biHeight};
+
+    for (long y = 0; y < head.biHeight; y++){
+        for (long 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(long x, long y, BYTE 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(long y=0; y<head.biHeight; y++){
+               for(long 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 = (BYTE*)malloc(head.biWidth * head.biHeight);
+
+       BYTE* src = from.info.pImage;
+       BYTE* dst = pSelection;
+       if (src==NULL || dst==NULL){
+               strcpy(info.szLastError,"CxImage::SelectionSet: null pointer");
+               return false;
+       }
+
+       for (long 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 long x,const long y,const BYTE level)
+{
+       if (pSelection && IsInside(x,y)) pSelection[x+y*head.biWidth]=level;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Gets the Selection level for a single pixel 
+ */
+BYTE CxImage::SelectionGet(const long x,const long 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;
+
+       long 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.
+ */
+BYTE CxImage::BlindSelectionGet(const long x,const long 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).
+ */
+BYTE* CxImage::SelectionGetPointer(const long x,const long y)
+{
+       if (pSelection && IsInside(x,y)) return pSelection+x+y*head.biWidth;
+       return 0;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::SelectionFlip()
+{
+       if (!pSelection) return false;
+
+       BYTE *buff = (BYTE*)malloc(head.biWidth);
+       if (!buff) return false;
+
+       BYTE *iSrc,*iDst;
+       iSrc = pSelection + (head.biHeight-1)*head.biWidth;
+       iDst = pSelection;
+       for (long 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);
+
+       long 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;
+       BYTE* pSelection2 = (BYTE*)malloc(head.biWidth * head.biHeight);
+       if (!pSelection2) return false;
+       
+       BYTE *iSrc,*iDst;
+       long wdt=head.biWidth-1;
+       iSrc=pSelection + wdt;
+       iDst=pSelection2;
+       for(long y=0; y < head.biHeight; y++){
+               for(long x=0; x <= wdt; x++)
+                       *(iDst+x)=*(iSrc-x);
+               iSrc+=head.biWidth;
+               iDst+=head.biWidth;
+       }
+       free(pSelection);
+       pSelection=pSelection2;
+       
+       long 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(int y = 0; y < head.biHeight; y++){
+            HRGN hTemp = NULL;
+            int iStart = -1;
+            int 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
index 1ecdf7f5a0b62ee33eee1d24ae35655039c77fdc..3248716cd6950e1ae72fb2d77a7b260a3bb658ac 100644 (file)
-/*\r
- * File:       ximaska.cpp\r
- * Purpose:    Platform Independent SKA Image Class Loader and Writer\r
- * 25/Sep/2007 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximaska.h"\r
-\r
-#if CXIMAGE_SUPPORT_SKA\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageSKA::Decode(CxFile *hFile)\r
-{\r
-       if (hFile==NULL)\r
-               return false;\r
-\r
-       // read the  header\r
-       SKAHEADER ska_header;\r
-       hFile->Read(&ska_header,sizeof(SKAHEADER),1);\r
-\r
-    ska_header.Width = ntohs(ska_header.Width);\r
-    ska_header.Height = ntohs(ska_header.Height);\r
-    ska_header.dwUnknown = ntohl(ska_header.dwUnknown);\r
-\r
-       // check header\r
-       if (ska_header.dwUnknown != 0x01000000 ||\r
-               ska_header.Width > 0x7FFF || ska_header.Height > 0x7FFF ||\r
-               ska_header.BppExp != 3)\r
-               return false;\r
-\r
-       if (info.nEscape == -1){\r
-               head.biWidth = ska_header.Width ;\r
-               head.biHeight= ska_header.Height;\r
-               info.dwType = CXIMAGE_FORMAT_SKA;\r
-               return true;\r
-       }\r
-\r
-       int bpp = 1<<ska_header.BppExp;\r
-\r
-       Create(ska_header.Width,ska_header.Height,bpp,CXIMAGE_FORMAT_SKA);\r
-       if (!IsValid())\r
-               return false;\r
-\r
-       // read the palette\r
-       int nColors = 1<<bpp;\r
-       rgb_color* ppal = (rgb_color*)malloc(nColors*sizeof(rgb_color));\r
-       if (!ppal) return false;\r
-       hFile->Read(ppal,nColors*sizeof(rgb_color),1);\r
-       SetPalette(ppal,nColors);\r
-       free(ppal);\r
-\r
-       //read the image\r
-       hFile->Read(GetBits(),ska_header.Width*ska_header.Height,1);\r
-\r
-       //reorder rows\r
-       if (GetEffWidth() != ska_header.Width){\r
-               BYTE *src,*dst;\r
-               src = GetBits() + ska_header.Width*(ska_header.Height-1);\r
-               dst = GetBits(ska_header.Height-1);\r
-               for(int y=0;y<ska_header.Height;y++){\r
-                       memcpy(dst,src,ska_header.Width);\r
-                       src -= ska_header.Width;\r
-                       dst -= GetEffWidth();\r
-               }\r
-       }\r
-\r
-       Flip();\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageSKA::Encode(CxFile * hFile)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       if(head.biBitCount > 8) {\r
-               strcpy(info.szLastError,"SKA Images must be 8 bit or less");\r
-               return false;\r
-       }\r
-\r
-       SKAHEADER ska_header;\r
-\r
-       ska_header.Width = (unsigned short)GetWidth();\r
-       ska_header.Height = (unsigned short)GetHeight();\r
-       ska_header.BppExp = 3;\r
-       ska_header.dwUnknown = 0x01000000;\r
-\r
-    ska_header.Width = ntohs(ska_header.Width);\r
-    ska_header.Height = ntohs(ska_header.Height);\r
-    ska_header.dwUnknown = ntohl(ska_header.dwUnknown);\r
-\r
-       hFile->Write(&ska_header,sizeof(SKAHEADER),1);\r
-\r
-    ska_header.Width = ntohs(ska_header.Width);\r
-    ska_header.Height = ntohs(ska_header.Height);\r
-    ska_header.dwUnknown = ntohl(ska_header.dwUnknown);\r
-\r
-       if (head.biBitCount<8) IncreaseBpp(8);\r
-\r
-       rgb_color pal[256];\r
-       for(int idx=0; idx<256; idx++){\r
-               GetPaletteColor(idx,&(pal[idx].r),&(pal[idx].g),&(pal[idx].b));\r
-       }\r
-\r
-       hFile->Write(pal,256*sizeof(rgb_color),1);\r
-\r
-       BYTE* src = GetBits(ska_header.Height-1);\r
-       for(int y=0;y<ska_header.Height;y++){\r
-               hFile->Write(src,ska_header.Width,1);\r
-               src -= GetEffWidth();\r
-       }\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_SKA\r
-\r
+/*
+ * File:       ximaska.cpp
+ * Purpose:    Platform Independent SKA Image Class Loader and Writer
+ * 25/Sep/2007 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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 = ntohs(ska_header.Width);
+    ska_header.Height = ntohs(ska_header.Height);
+    ska_header.dwUnknown = 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;
+       }
+
+       int bpp = 1<<ska_header.BppExp;
+
+       Create(ska_header.Width,ska_header.Height,bpp,CXIMAGE_FORMAT_SKA);
+       if (!IsValid())
+               return false;
+
+       // read the palette
+       int 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){
+               BYTE *src,*dst;
+               src = GetBits() + ska_header.Width*(ska_header.Height-1);
+               dst = GetBits(ska_header.Height-1);
+               for(int 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 = (unsigned short)GetWidth();
+       ska_header.Height = (unsigned short)GetHeight();
+       ska_header.BppExp = 3;
+       ska_header.dwUnknown = 0x01000000;
+
+    ska_header.Width = ntohs(ska_header.Width);
+    ska_header.Height = ntohs(ska_header.Height);
+    ska_header.dwUnknown = ntohl(ska_header.dwUnknown);
+
+       hFile->Write(&ska_header,sizeof(SKAHEADER),1);
+
+    ska_header.Width = ntohs(ska_header.Width);
+    ska_header.Height = ntohs(ska_header.Height);
+    ska_header.dwUnknown = ntohl(ska_header.dwUnknown);
+
+       if (head.biBitCount<8) IncreaseBpp(8);
+
+       rgb_color pal[256];
+       for(int idx=0; idx<256; idx++){
+               GetPaletteColor(idx,&(pal[idx].r),&(pal[idx].g),&(pal[idx].b));
+       }
+
+       hFile->Write(pal,256*sizeof(rgb_color),1);
+
+       BYTE* src = GetBits(ska_header.Height-1);
+       for(int 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
+
index f2facc900fb5bcccbd78f973eb5082a8fe1629f0..381acf58f23d9836d1aaf2f930f0487831dfba68 100644 (file)
@@ -1,44 +1,44 @@
-/*\r
- * File:       ximaska.h\r
- * Purpose:    SKA Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageSKA (c) 25/Sep/2007 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaSKA_h)\r
-#define __ximaSKA_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_SKA\r
-\r
-class CxImageSKA: public CxImage\r
-{\r
-#pragma pack(1)\r
-       typedef struct tagSkaHeader {\r
-    unsigned short  Width;\r
-    unsigned short  Height;\r
-    BYTE  BppExp;\r
-    DWORD dwUnknown;\r
-} SKAHEADER;\r
-#pragma pack()\r
-\r
-public:\r
-       CxImageSKA(): CxImage(CXIMAGE_FORMAT_SKA) {}\r
-\r
-//     bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_ICO);}\r
-//     bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_ICO);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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 {
+    unsigned short  Width;
+    unsigned short  Height;
+    BYTE  BppExp;
+    DWORD 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
index b137126c4d1d7c154206651278c09083ab7e08ce..d0842548813cd87b51cd2b4d864f835a0a2a08e4 100644 (file)
-/*\r
- * File:       ximatga.cpp\r
- * Purpose:    Platform Independent TGA Image Class Loader and Writer\r
- * 05/Jan/2001 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximatga.h"\r
-\r
-#if CXIMAGE_SUPPORT_TGA\r
-\r
-#include "ximaiter.h"\r
-\r
-// Definitions for image types.\r
-#define TGA_Null 0\r
-#define TGA_Map 1\r
-#define TGA_RGB 2\r
-#define TGA_Mono 3\r
-#define TGA_RLEMap 9\r
-#define TGA_RLERGB 10\r
-#define TGA_RLEMono 11\r
-#define TGA_CompMap 32\r
-#define TGA_CompMap4 33\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageTGA::Decode(CxFile *hFile)\r
-{\r
-       if (hFile == NULL) return false;\r
-\r
-       TGAHEADER tgaHead;\r
-\r
-  cx_try\r
-  {\r
-       if (hFile->Read(&tgaHead,sizeof(tgaHead),1)==0)\r
-               cx_throw("Not a TGA");\r
-\r
-       tga_toh(&tgaHead);\r
-\r
-       bool bCompressed;\r
-       switch (tgaHead.ImageType){\r
-       case TGA_Map:\r
-       case TGA_RGB:\r
-       case TGA_Mono:\r
-               bCompressed = false;\r
-               break;\r
-       case TGA_RLEMap:\r
-       case TGA_RLERGB:\r
-       case TGA_RLEMono:\r
-               bCompressed = true;\r
-               break;\r
-       default:\r
-               cx_throw("Unknown TGA image type");\r
-       }\r
-\r
-       if (tgaHead.ImageWidth==0 || tgaHead.ImageHeight==0 || tgaHead.PixelDepth==0 || tgaHead.CmapLength>256)\r
-               cx_throw("bad TGA header");\r
-\r
-       if (tgaHead.PixelDepth!=8 && tgaHead.PixelDepth!=15 && tgaHead.PixelDepth!=16 && tgaHead.PixelDepth!=24 && tgaHead.PixelDepth!=32)\r
-               cx_throw("bad TGA header");\r
-\r
-       if (info.nEscape == -1){\r
-               head.biWidth = tgaHead.ImageWidth ;\r
-               head.biHeight= tgaHead.ImageHeight;\r
-               info.dwType = CXIMAGE_FORMAT_TGA;\r
-               return true;\r
-       }\r
-\r
-       if (tgaHead.IdLength>0) hFile->Seek(tgaHead.IdLength,SEEK_CUR); //skip descriptor\r
-\r
-       Create(tgaHead.ImageWidth, tgaHead.ImageHeight, tgaHead.PixelDepth, CXIMAGE_FORMAT_TGA);\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-       if (tgaHead.PixelDepth==32) AlphaCreate(); // Image has alpha channel\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       if (!IsValid()) cx_throw("TGA Create failed");\r
-       \r
-       if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding\r
-\r
-       if (tgaHead.CmapType != 0){ // read the palette\r
-               rgb_color pal[256];\r
-               hFile->Read(pal,tgaHead.CmapLength*sizeof(rgb_color), 1);\r
-               for (int i=0;i<tgaHead.CmapLength; i++) SetPaletteColor((BYTE)i,pal[i].b,pal[i].g,pal[i].r);\r
-       }\r
-\r
-       if (tgaHead.ImageType == TGA_Mono || tgaHead.ImageType == TGA_RLEMono)\r
-               SetGrayPalette();\r
-\r
-       // Bits 4 & 5 of the Image Descriptor byte control the ordering of the pixels.\r
-       bool bXReversed = ((tgaHead.ImagDesc & 16) == 16);\r
-       bool bYReversed = ((tgaHead.ImagDesc & 32) == 32);\r
-\r
-    CImageIterator iter(this);\r
-       BYTE rleLeftover = 255; //for images with illegal packet boundary \r
-       BYTE* pDest;\r
-    for (int y=0; y < tgaHead.ImageHeight; y++){\r
-\r
-               if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding\r
-\r
-               if (hFile == NULL || hFile->Eof()) cx_throw("corrupted TGA");\r
-\r
-               if (bYReversed) pDest = iter.GetRow(tgaHead.ImageHeight-y-1);\r
-               else pDest = iter.GetRow(y);\r
-\r
-               if (bCompressed) rleLeftover = ExpandCompressedLine(pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,rleLeftover);\r
-               else ExpandUncompressedLine  (pDest,&tgaHead,hFile,tgaHead.ImageWidth,y,0);\r
-    }\r
-\r
-       if (bXReversed) Mirror();\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (bYReversed && tgaHead.PixelDepth==32) AlphaFlip(); //<lioucr>\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       return false;\r
-  }\r
-    return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageTGA::Encode(CxFile * hFile)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       if (head.biBitCount<8){\r
-               strcpy(info.szLastError,"Bit depth must be 8 or 24");\r
-               return false;\r
-       }\r
-\r
-       TGAHEADER tgaHead;\r
-\r
-    tgaHead.IdLength = 0;                              // Image ID Field Length\r
-    tgaHead.CmapType = GetPalette()!=0; // Color Map Type\r
-    tgaHead.ImageType = (head.biBitCount == 8) ? (BYTE)TGA_Map : (BYTE)TGA_RGB; // Image Type\r
-\r
-    tgaHead.CmapIndex=0;                               // First Entry Index\r
-    tgaHead.CmapLength=(head.biBitCount == 8) ? 256 : 0;   // Color Map Length\r
-    tgaHead.CmapEntrySize=(head.biBitCount == 8) ? (BYTE)24 : (BYTE)0; // Color Map Entry Size\r
-\r
-    tgaHead.X_Origin=0;                                        // X-origin of Image\r
-    tgaHead.Y_Origin=0;                                        // Y-origin of Image\r
-    tgaHead.ImageWidth=(WORD)head.biWidth;             // Image Width\r
-    tgaHead.ImageHeight=(WORD)head.biHeight;   // Image Height\r
-    tgaHead.PixelDepth=(BYTE)head.biBitCount;  // Pixel Depth\r
-    tgaHead.ImagDesc=0;                                        // Image Descriptor\r
-\r
-       if (pAlpha && head.biBitCount==24) tgaHead.PixelDepth=32; \r
-\r
-       tga_toh(&tgaHead);\r
-       hFile->Write(&tgaHead,sizeof(TGAHEADER),1);\r
-       tga_toh(&tgaHead);\r
-\r
-       if (head.biBitCount==8){\r
-               rgb_color pal[256];\r
-               RGBQUAD* ppal = GetPalette();\r
-               for (int i=0;i<256; i++){\r
-                       pal[i].r = ppal[i].rgbBlue;\r
-                       pal[i].g = ppal[i].rgbGreen;\r
-                       pal[i].b = ppal[i].rgbRed;\r
-               }\r
-               hFile->Write(&pal,256*sizeof(rgb_color),1);\r
-       }\r
-       \r
-       CImageIterator iter(this);\r
-       BYTE* pDest;\r
-       if (pAlpha==0 || head.biBitCount==8){\r
-               for (int y=0; y < tgaHead.ImageHeight; y++){\r
-                       pDest = iter.GetRow(y);\r
-                       hFile->Write(pDest,tgaHead.ImageWidth * (head.biBitCount >> 3),1);\r
-               }\r
-       } else {\r
-               pDest = (BYTE*)malloc(4*tgaHead.ImageWidth);\r
-               RGBQUAD c;\r
-               for (int y=0; y < tgaHead.ImageHeight; y++){\r
-                       for(int x=0, x4=0;x<tgaHead.ImageWidth;x++, x4+=4){\r
-                               c = BlindGetPixelColor(x,y);\r
-                               pDest[x4+0]=c.rgbBlue;\r
-                               pDest[x4+1]=c.rgbGreen;\r
-                               pDest[x4+2]=c.rgbRed;\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-                               pDest[x4+3]=AlphaGet(x,y);\r
-#else\r
-                               pDest[x4+3]=0;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       }\r
-                       hFile->Write(pDest,4*tgaHead.ImageWidth,1);\r
-               }\r
-               free(pDest);\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-BYTE CxImageTGA::ExpandCompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, BYTE rleLeftover)\r
-{\r
-       BYTE rle;\r
-       long filePos=0;\r
-       for (int x=0; x<width; ){\r
-               if (rleLeftover != 255){\r
-            rle = rleLeftover;\r
-            rleLeftover = 255;\r
-        } else {\r
-                       hFile->Read(&rle,1,1);\r
-               }\r
-               if (rle & 128) { // RLE-Encoded packet\r
-                       rle -= 127; // Calculate real repeat count.\r
-                       if ((x+rle)>width){\r
-                               rleLeftover = (BYTE)(128 + (rle - (width - x) - 1));\r
-                filePos = hFile->Tell();\r
-                               rle = (BYTE)(width - x);\r
-                       }\r
-                       switch (ptgaHead->PixelDepth)\r
-                       {\r
-                       case 32: {\r
-                               RGBQUAD color;\r
-                               hFile->Read(&color,4,1);\r
-                               for (int ix = 0; ix < rle; ix++){\r
-                                       memcpy(&pDest[3*ix],&color,3);\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-                                       AlphaSet(ix+x,y,color.rgbReserved);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                               }\r
-                               break;\r
-                                        } \r
-                       case 24: {\r
-                               rgb_color triple;\r
-                               hFile->Read(&triple,3,1);\r
-                               for (int ix = 0; ix < rle; ix++) memcpy(&pDest[3*ix],&triple,3);\r
-                               break;\r
-                                        }\r
-                       case 15:\r
-                       case 16: {\r
-                               WORD pixel;\r
-                               hFile->Read(&pixel,2,1);\r
-                               rgb_color triple;\r
-                               triple.r = (BYTE)(( pixel & 0x1F ) * 8);     // red\r
-                               triple.g = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green\r
-                               triple.b = (BYTE)(( pixel >> 7 ) & 0x0F8);   // blue\r
-                               for (int ix = 0; ix < rle; ix++){\r
-                                       memcpy(&pDest[3*ix],&triple,3);\r
-                               }\r
-                               break;\r
-                                        }\r
-                       case 8: {\r
-                               BYTE pixel;\r
-                               hFile->Read(&pixel,1,1);\r
-                               for (int ix = 0; ix < rle; ix++) pDest[ix] = pixel;\r
-                                       }\r
-                       }\r
-                       if (rleLeftover!=255) hFile->Seek(filePos, SEEK_SET);\r
-               } else { // Raw packet\r
-                       rle += 1; // Calculate real repeat count.\r
-                       if ((x+rle)>width){\r
-                rleLeftover = (BYTE)(rle - (width - x) - 1);\r
-                               rle = (BYTE)(width - x);\r
-                       }\r
-                       ExpandUncompressedLine(pDest,ptgaHead,hFile,rle,y,x);\r
-               }\r
-               if (head.biBitCount == 24)      pDest += rle*3; else pDest += rle;\r
-               x += rle;\r
-       }\r
-       return rleLeftover;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageTGA::ExpandUncompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, int xoffset)\r
-{\r
-       switch (ptgaHead->PixelDepth){\r
-       case 8:\r
-               hFile->Read(pDest,width,1);\r
-               break;\r
-       case 15:\r
-       case 16:{\r
-               BYTE* dst=pDest;\r
-               WORD pixel;\r
-               for (int x=0; x<width; x++){\r
-                       hFile->Read(&pixel,2,1);\r
-                       *dst++ = (BYTE)(( pixel & 0x1F ) * 8);     // blue\r
-                       *dst++ = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green\r
-                       *dst++ = (BYTE)(( pixel >> 7 ) & 0x0F8);   // red\r
-               }\r
-               break;\r
-                       }\r
-       case 24:\r
-               hFile->Read(pDest,3*width,1);\r
-               break;\r
-       case 32:{\r
-               BYTE* dst=pDest;\r
-               for (int x=0; x<width; x++){\r
-                       RGBQUAD pixel;\r
-                       hFile->Read(&pixel,4,1);\r
-                       *dst++ = pixel.rgbBlue;\r
-                       *dst++ = pixel.rgbGreen;\r
-                       *dst++ = pixel.rgbRed;\r
-#if CXIMAGE_SUPPORT_ALPHA      // <vho>\r
-                       AlphaSet(x+xoffset,y,pixel.rgbReserved); //alpha\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-               }\r
-               break;\r
-                       }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageTGA::tga_toh(TGAHEADER* p)\r
-{\r
-    p->CmapIndex = ntohs(p->CmapIndex);\r
-    p->CmapLength = ntohs(p->CmapLength);\r
-    p->X_Origin = ntohs(p->X_Origin);\r
-    p->Y_Origin = ntohs(p->Y_Origin);\r
-    p->ImageWidth = ntohs(p->ImageWidth);\r
-    p->ImageHeight = ntohs(p->ImageHeight);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif         // CXIMAGE_SUPPORT_TGA\r
-\r
+/*
+ * File:       ximatga.cpp
+ * Purpose:    Platform Independent TGA Image Class Loader and Writer
+ * 05/Jan/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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 (int i=0;i<tgaHead.CmapLength; i++) SetPaletteColor((BYTE)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);
+       BYTE rleLeftover = 255; //for images with illegal packet boundary 
+       BYTE* pDest;
+    for (int 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) ? (BYTE)TGA_Map : (BYTE)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) ? (BYTE)24 : (BYTE)0; // Color Map Entry Size
+
+    tgaHead.X_Origin=0;                                        // X-origin of Image
+    tgaHead.Y_Origin=0;                                        // Y-origin of Image
+    tgaHead.ImageWidth=(WORD)head.biWidth;             // Image Width
+    tgaHead.ImageHeight=(WORD)head.biHeight;   // Image Height
+    tgaHead.PixelDepth=(BYTE)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 (int 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);
+       BYTE* pDest;
+       if (pAlpha==0 || head.biBitCount==8){
+               for (int y=0; y < tgaHead.ImageHeight; y++){
+                       pDest = iter.GetRow(y);
+                       hFile->Write(pDest,tgaHead.ImageWidth * (head.biBitCount >> 3),1);
+               }
+       } else {
+               pDest = (BYTE*)malloc(4*tgaHead.ImageWidth);
+               RGBQUAD c;
+               for (int y=0; y < tgaHead.ImageHeight; y++){
+                       for(int 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
+////////////////////////////////////////////////////////////////////////////////
+BYTE CxImageTGA::ExpandCompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, BYTE rleLeftover)
+{
+       BYTE rle;
+       long filePos=0;
+       for (int 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 = (BYTE)(128 + (rle - (width - x) - 1));
+                filePos = hFile->Tell();
+                               rle = (BYTE)(width - x);
+                       }
+                       switch (ptgaHead->PixelDepth)
+                       {
+                       case 32: {
+                               RGBQUAD color;
+                               hFile->Read(&color,4,1);
+                               for (int 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 (int ix = 0; ix < rle; ix++) memcpy(&pDest[3*ix],&triple,3);
+                               break;
+                                        }
+                       case 15:
+                       case 16: {
+                               WORD pixel;
+                               hFile->Read(&pixel,2,1);
+                               rgb_color triple;
+                               triple.r = (BYTE)(( pixel & 0x1F ) * 8);     // red
+                               triple.g = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green
+                               triple.b = (BYTE)(( pixel >> 7 ) & 0x0F8);   // blue
+                               for (int ix = 0; ix < rle; ix++){
+                                       memcpy(&pDest[3*ix],&triple,3);
+                               }
+                               break;
+                                        }
+                       case 8: {
+                               BYTE pixel;
+                               hFile->Read(&pixel,1,1);
+                               for (int 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 = (BYTE)(rle - (width - x) - 1);
+                               rle = (BYTE)(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(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, int xoffset)
+{
+       switch (ptgaHead->PixelDepth){
+       case 8:
+               hFile->Read(pDest,width,1);
+               break;
+       case 15:
+       case 16:{
+               BYTE* dst=pDest;
+               WORD pixel;
+               for (int x=0; x<width; x++){
+                       hFile->Read(&pixel,2,1);
+                       *dst++ = (BYTE)(( pixel & 0x1F ) * 8);     // blue
+                       *dst++ = (BYTE)(( pixel >> 2 ) & 0x0F8);   // green
+                       *dst++ = (BYTE)(( pixel >> 7 ) & 0x0F8);   // red
+               }
+               break;
+                       }
+       case 24:
+               hFile->Read(pDest,3*width,1);
+               break;
+       case 32:{
+               BYTE* dst=pDest;
+               for (int 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 = ntohs(p->CmapIndex);
+    p->CmapLength = ntohs(p->CmapLength);
+    p->X_Origin = ntohs(p->X_Origin);
+    p->Y_Origin = ntohs(p->Y_Origin);
+    p->ImageWidth = ntohs(p->ImageWidth);
+    p->ImageHeight = ntohs(p->ImageHeight);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif         // CXIMAGE_SUPPORT_TGA
+
index da572e6da3b3229222358cf470eedc9d1d590a01..300eb721f1671347ba1c9332026f71d2ed8d594e 100644 (file)
@@ -1,61 +1,61 @@
-/*\r
- * File:       ximatga.h\r
- * Purpose:    TARGA Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageTGA (c) 05/Jan/2002 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * Parts of the code come from Paintlib : Copyright (c) 1996-1998 Ulrich von Zadow\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaTGA_h)\r
-#define __ximaTGA_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_TGA\r
-\r
-class CxImageTGA: public CxImage\r
-{\r
-#pragma pack(1)\r
-typedef struct tagTgaHeader\r
-{\r
-    BYTE   IdLength;            // Image ID Field Length\r
-    BYTE   CmapType;            // Color Map Type\r
-    BYTE   ImageType;           // Image Type\r
-\r
-    WORD   CmapIndex;           // First Entry Index\r
-    WORD   CmapLength;          // Color Map Length\r
-    BYTE   CmapEntrySize;       // Color Map Entry Size\r
-\r
-    WORD   X_Origin;            // X-origin of Image\r
-    WORD   Y_Origin;            // Y-origin of Image\r
-    WORD   ImageWidth;          // Image Width\r
-    WORD   ImageHeight;         // Image Height\r
-    BYTE   PixelDepth;          // Pixel Depth\r
-    BYTE   ImagDesc;            // Image Descriptor\r
-} TGAHEADER;\r
-#pragma pack()\r
-\r
-public:\r
-       CxImageTGA(): CxImage(CXIMAGE_FORMAT_TGA) {}\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_TGA);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_TGA);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-protected:\r
-       BYTE ExpandCompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, BYTE rleLeftover);\r
-       void ExpandUncompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, int xoffset);\r
-       void tga_toh(TGAHEADER* p);\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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
+{
+    BYTE   IdLength;            // Image ID Field Length
+    BYTE   CmapType;            // Color Map Type
+    BYTE   ImageType;           // Image Type
+
+    WORD   CmapIndex;           // First Entry Index
+    WORD   CmapLength;          // Color Map Length
+    BYTE   CmapEntrySize;       // Color Map Entry Size
+
+    WORD   X_Origin;            // X-origin of Image
+    WORD   Y_Origin;            // Y-origin of Image
+    WORD   ImageWidth;          // Image Width
+    WORD   ImageHeight;         // Image Height
+    BYTE   PixelDepth;          // Pixel Depth
+    BYTE   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:
+       BYTE ExpandCompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, BYTE rleLeftover);
+       void ExpandUncompressedLine(BYTE* pDest,TGAHEADER* ptgaHead,CxFile *hFile,int width, int y, int xoffset);
+       void tga_toh(TGAHEADER* p);
+};
+
+#endif
+
+#endif
index 017518445dbf7aed601fd444299eaf769a9f5440..37533e2280c0e6c0f4227d4a9ee467e0179b6ee2 100644 (file)
@@ -1,97 +1,97 @@
-#include "ximage.h"\r
-#include "ximath.h"\r
-#include <math.h>\r
-\r
-//this module should contain some classes for geometrical transformations\r
-//usable with selections, etc... once it's done, that is. :)\r
-\r
-CxPoint2::CxPoint2()\r
-{\r
-  x=y=0.0f;\r
-}\r
-\r
-CxPoint2::CxPoint2(float const x_, float const y_)\r
-{\r
-  x=x_;\r
-  y=y_;\r
-}\r
-\r
-CxPoint2::CxPoint2(CxPoint2 const &p)\r
-{\r
-  x=p.x;\r
-  y=p.y;\r
-}\r
-\r
-float CxPoint2::Distance(CxPoint2 const p2)\r
-{\r
-  return (float)sqrt((x-p2.x)*(x-p2.x)+(y-p2.y)*(y-p2.y));\r
-}\r
-\r
-float CxPoint2::Distance(float const x_, float const y_)\r
-{\r
-  return (float)sqrt((x-x_)*(x-x_)+(y-y_)*(y-y_));\r
-}\r
-\r
-CxRect2::CxRect2()\r
-{\r
-}\r
-\r
-CxRect2::CxRect2(float const x1_, float const y1_, float const x2_, float const y2_)\r
-{\r
-  botLeft.x=x1_;\r
-  botLeft.y=y1_;\r
-  topRight.x=x2_;\r
-  topRight.y=y2_;\r
-}\r
-\r
-CxRect2::CxRect2(CxRect2 const &p)\r
-{\r
-  botLeft=p.botLeft;\r
-  topRight=p.topRight;\r
-}\r
-\r
-float CxRect2::Surface() const\r
-/*\r
- * Returns the surface of rectangle.\r
- */\r
-{\r
-  return (topRight.x-botLeft.x)*(topRight.y-botLeft.y);\r
-}\r
-\r
-CxRect2 CxRect2::CrossSection(CxRect2 const &r2) const\r
-/*\r
- * Returns crossection with another rectangle.\r
- */\r
-{\r
-  CxRect2 cs;\r
-  cs.botLeft.x=max(botLeft.x, r2.botLeft.x);\r
-  cs.botLeft.y=max(botLeft.y, r2.botLeft.y);\r
-  cs.topRight.x=min(topRight.x, r2.topRight.x);\r
-  cs.topRight.y=min(topRight.y, r2.topRight.y);\r
-  if (cs.botLeft.x<=cs.topRight.x && cs.botLeft.y<=cs.topRight.y) {\r
-    return cs;\r
-  } else {\r
-    return CxRect2(0,0,0,0);\r
-  }//if\r
-}\r
-\r
-CxPoint2 CxRect2::Center() const\r
-/*\r
- * Returns the center point of rectangle.\r
- */\r
-{\r
-  return CxPoint2((topRight.x+botLeft.x)/2.0f, (topRight.y+botLeft.y)/2.0f);\r
-}\r
-\r
-float CxRect2::Width() const\r
-//returns rectangle width\r
-{\r
-  return topRight.x-botLeft.x;\r
-}\r
-\r
-float CxRect2::Height() const\r
-//returns rectangle height\r
-{\r
-  return topRight.y-botLeft.y;\r
-}\r
-\r
+#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;
+}
+
index 014c14b80ee932d81143856bda1d3f143ceca0c6..10b98984e4f925fefac91cf50deff1591695ad76 100644 (file)
@@ -1,39 +1,39 @@
-#if !defined(__ximath_h)\r
-#define __ximath_h\r
-\r
-#include "ximadef.h"\r
-\r
-//***bd*** simple floating point point\r
-class DLL_EXP CxPoint2\r
-{\r
-public:\r
-  CxPoint2();\r
-  CxPoint2(float const x_, float const y_);\r
-  CxPoint2(CxPoint2 const &p);\r
-\r
-  float Distance(CxPoint2 const p2);\r
-  float Distance(float const x_, float const y_);\r
-\r
-  float x,y;\r
-};\r
-\r
-//and simple rectangle\r
-class DLL_EXP CxRect2\r
-{\r
-public:\r
-  CxRect2();\r
-  CxRect2(float const x1_, float const y1_, float const x2_, float const y2_);\r
-  CxRect2(CxPoint2 const &bl, CxPoint2 const &tr);\r
-  CxRect2(CxRect2 const &p);\r
-\r
-  float Surface() const;\r
-  CxRect2 CrossSection(CxRect2 const &r2) const;\r
-  CxPoint2 Center() const;\r
-  float Width() const;\r
-  float Height() const;\r
-\r
-  CxPoint2 botLeft;\r
-  CxPoint2 topRight;\r
-};\r
-\r
-#endif\r
+#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
index b7415ed1da5d8079b3a62e726051c3e7ca182a7d..6b4e7ad6c8749d2edc782b68260228a95c2251b0 100644 (file)
-/*\r
- * File:       ximatif.cpp\r
- * Purpose:    Platform Independent TIFF Image Class Loader and Writer\r
- * 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximatif.h"\r
-\r
-#if CXIMAGE_SUPPORT_TIF\r
-\r
-#define FIX_16BPP_DARKIMG // + VK: if uncomment, dark 16bpp images are fixed\r
-\r
-#include "../tiff/tiffio.h"\r
-\r
-#define CVT(x)                 (((x) * 255L) / ((1L<<16)-1))\r
-#define        SCALE(x)                (((x)*((1L<<16)-1))/255)\r
-#define CalculateLine(width,bitdepth)  (((width * bitdepth) + 7) / 8)\r
-#define CalculatePitch(line)   (line + 3 & ~3)\r
-\r
-extern "C" TIFF* _TIFFOpenEx(CxFile* stream, const char* mode);\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-CxImageTIF::~CxImageTIF()\r
-{\r
-       if (m_tif2) TIFFClose(m_tif2);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageTIF::Decode(CxFile * hFile)\r
-{\r
-       //Comment this line if you need more information on errors\r
-       // TIFFSetErrorHandler(NULL);   //<Patrick Hoffmann>\r
-\r
-       //Open file and fill the TIFF structure\r
-       // m_tif = TIFFOpen(imageFileName,"rb");\r
-       TIFF* m_tif = _TIFFOpenEx(hFile, "rb");\r
-\r
-       uint32 height=0;\r
-       uint32 width=0;\r
-       uint16 bitspersample=1;\r
-       uint16 samplesperpixel=1;\r
-       uint32 rowsperstrip=(DWORD)-1;\r
-       uint16 photometric=0;\r
-       uint16 compression=1;\r
-       uint16 orientation=ORIENTATION_TOPLEFT; //<vho>\r
-       uint16 res_unit; //<Trifon>\r
-       uint32 x, y;\r
-       float resolution, offset;\r
-       BOOL isRGB;\r
-       BYTE *bits;             //pointer to source data\r
-       BYTE *bits2;    //pointer to destination data\r
-\r
-  cx_try\r
-  {\r
-       //check if it's a tiff file\r
-       if (!m_tif)\r
-               cx_throw("Error encountered while opening TIFF file");\r
-\r
-       // <Robert Abram> - 12/2002 : get NumFrames directly, instead of looping\r
-       // info.nNumFrames=0;\r
-       // while(TIFFSetDirectory(m_tif,(uint16)info.nNumFrames)) info.nNumFrames++;\r
-       info.nNumFrames = TIFFNumberOfDirectories(m_tif);\r
-\r
-       if (!TIFFSetDirectory(m_tif, (uint16)info.nFrame))\r
-               cx_throw("Error: page not present in TIFF file");                       \r
-\r
-       //get image info\r
-       TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width);\r
-       TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height);\r
-       TIFFGetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);\r
-       TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);\r
-       TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);   \r
-       TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &photometric);\r
-       TIFFGetField(m_tif, TIFFTAG_ORIENTATION, &orientation);\r
-\r
-       if (info.nEscape == -1) {\r
-               // Return output dimensions only\r
-               head.biWidth = width;\r
-               head.biHeight = height;\r
-               info.dwType = CXIMAGE_FORMAT_TIF;\r
-               cx_throw("output dimensions returned");\r
-       }\r
-\r
-       TIFFGetFieldDefaulted(m_tif, TIFFTAG_RESOLUTIONUNIT, &res_unit);\r
-       if (TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &resolution))\r
-       {\r
-               if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);\r
-               SetXDPI((long)resolution);\r
-       }\r
-       if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution))\r
-       {\r
-               if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);\r
-               SetYDPI((long)resolution);\r
-       }\r
-\r
-       if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset))    info.xOffset = (long)offset;\r
-       if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset))    info.yOffset = (long)offset;\r
-\r
-       head.biClrUsed=0;\r
-       info.nBkgndIndex =-1;\r
-\r
-       if (rowsperstrip>height){\r
-               rowsperstrip=height;\r
-               TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);\r
-       }\r
-\r
-       isRGB = /*(bitspersample >= 8) && (VK: it is possible so for RGB to have < 8 bpp!)*/\r
-               (photometric == PHOTOMETRIC_RGB) ||\r
-               (photometric == PHOTOMETRIC_YCBCR) ||\r
-               (photometric == PHOTOMETRIC_SEPARATED) ||\r
-               (photometric == PHOTOMETRIC_LOGL) ||\r
-               (photometric == PHOTOMETRIC_LOGLUV);\r
-\r
-       if (isRGB){\r
-               head.biBitCount=24;\r
-       }else{\r
-               if ((photometric==PHOTOMETRIC_MINISBLACK)||(photometric==PHOTOMETRIC_MINISWHITE)||(photometric==PHOTOMETRIC_PALETTE)){\r
-                       if      (bitspersample == 1){\r
-                               head.biBitCount=1;              //B&W image\r
-                               head.biClrUsed =2;\r
-                       } else if (bitspersample == 4) {\r
-                               head.biBitCount=4;              //16 colors gray scale\r
-                               head.biClrUsed =16;\r
-                       } else {\r
-                               head.biBitCount=8;              //gray scale\r
-                               head.biClrUsed =256;\r
-                       }\r
-               } else if (bitspersample == 4) {\r
-                       head.biBitCount=4;                      // 16 colors\r
-                       head.biClrUsed=16;\r
-               } else {\r
-                       head.biBitCount=8;                      //256 colors\r
-                       head.biClrUsed=256;\r
-               }\r
-\r
-               if ((bitspersample > 8) && (photometric==PHOTOMETRIC_PALETTE))  // + VK + (BIG palette! => convert to RGB)\r
-               {       head.biBitCount=24;\r
-                       head.biClrUsed =0;\r
-               }\r
-       }\r
-\r
-       if (info.nEscape) cx_throw("Cancelled"); // <vho> - cancel decoding\r
-\r
-       Create(width,height,head.biBitCount,CXIMAGE_FORMAT_TIF);        //image creation\r
-       if (!pDib) cx_throw("CxImageTIF can't create image");\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (samplesperpixel==4) AlphaCreate();  //add alpha support for 32bpp tiffs\r
-       if (samplesperpixel==2 && bitspersample==8) AlphaCreate();      //add alpha support for 8bpp + alpha\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       TIFFGetField(m_tif, TIFFTAG_COMPRESSION, &compression);\r
-       SetCodecOption(compression); // <DPR> save original compression type\r
-\r
-       if (isRGB) {\r
-               // Read the whole image into one big RGBA buffer using\r
-               // the traditional TIFFReadRGBAImage() API that we trust.\r
-               uint32* raster;         // retrieve RGBA image\r
-               uint32 *row;\r
-\r
-               raster = (uint32*)_TIFFmalloc(width * height * sizeof (uint32));\r
-               if (raster == NULL) cx_throw("No space for raster buffer");\r
-                       \r
-               // Read the image in one chunk into an RGBA array\r
-               if(!TIFFReadRGBAImage(m_tif, width, height, raster, 1)) {\r
-                               _TIFFfree(raster);\r
-                               cx_throw("Corrupted TIFF file!");\r
-               }\r
-\r
-               // read the raster lines and save them in the DIB\r
-               // with RGB mode, we have to change the order of the 3 samples RGB\r
-               row = &raster[0];\r
-               bits2 = info.pImage;\r
-               for (y = 0; y < height; y++) {\r
-\r
-                       if (info.nEscape){ // <vho> - cancel decoding\r
-                               _TIFFfree(raster);\r
-                               cx_throw("Cancelled");\r
-                       }\r
-\r
-                       bits = bits2;\r
-                       for (x = 0; x < width; x++) {\r
-                               *bits++ = (BYTE)TIFFGetB(row[x]);\r
-                               *bits++ = (BYTE)TIFFGetG(row[x]);\r
-                               *bits++ = (BYTE)TIFFGetR(row[x]);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               if (samplesperpixel==4) AlphaSet(x,y,(BYTE)TIFFGetA(row[x]));\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       }\r
-                       row += width;\r
-                       bits2 += info.dwEffWidth;\r
-               }\r
-               _TIFFfree(raster);\r
-       } else {\r
-               int BIG_palette = (bitspersample > 8) &&        // + VK\r
-                                                 (photometric==PHOTOMETRIC_PALETTE);           \r
-               if (BIG_palette && (bitspersample > 24))        // + VK\r
-                       cx_throw("Too big palette to handle");          // + VK\r
-\r
-               RGBQUAD *pal;\r
-               pal=(RGBQUAD*)calloc(BIG_palette ? 1<<bitspersample : 256,sizeof(RGBQUAD)); \r
-                       // ! VK: it coasts nothing but more correct to use 256 as temp palette storage\r
-                       // ! VK: but for case of BIG palette it just copied\r
-               if (pal==NULL) cx_throw("Unable to allocate TIFF palette");\r
-\r
-               int bpp = bitspersample <= 8 ? bitspersample : 8; // + VK (to use instead of bitspersample for case of > 8)\r
-\r
-               // set up the colormap based on photometric     \r
-               switch(photometric) {\r
-                       case PHOTOMETRIC_MINISBLACK:    // bitmap and greyscale image types\r
-                       case PHOTOMETRIC_MINISWHITE:\r
-                               if (bitspersample == 1) {       // Monochrome image\r
-                                       if (photometric == PHOTOMETRIC_MINISBLACK) {\r
-                                               pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;\r
-                                       } else {\r
-                                               pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;\r
-                                       }\r
-                               } else {                // need to build the scale for greyscale images\r
-                                       if (photometric == PHOTOMETRIC_MINISBLACK) {\r
-                                               for (int i=0; i<(1<<bpp); i++){\r
-                                                       pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(i*(255/((1<<bpp)-1)));\r
-                                               }\r
-                                       } else {\r
-                                               for (int i=0; i<(1<<bpp); i++){\r
-                                                       pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(255-i*(255/((1<<bpp)-1)));\r
-                                               }\r
-                                       }\r
-                               }\r
-                               break;\r
-                       case PHOTOMETRIC_PALETTE:       // color map indexed\r
-                               uint16 *red;\r
-                               uint16 *green;\r
-                               uint16 *blue;\r
-                               TIFFGetField(m_tif, TIFFTAG_COLORMAP, &red, &green, &blue); \r
-\r
-                               // Is the palette 16 or 8 bits ?\r
-                               BOOL Palette16Bits = /*FALSE*/ BIG_palette;\r
-                               if (!BIG_palette) {\r
-                                       int n= 1<<bpp;\r
-                                       while (n-- > 0) {\r
-                                               if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256) {\r
-                                                       Palette16Bits=TRUE;\r
-                                                       break;\r
-                                               }\r
-                                       }\r
-                               }\r
-\r
-                               // load the palette in the DIB\r
-                               for (int i = (1 << ( BIG_palette ? bitspersample : bpp )) - 1; i >= 0; i--) {\r
-                                       if (Palette16Bits) {\r
-                                               pal[i].rgbRed =(BYTE) CVT(red[i]);\r
-                                               pal[i].rgbGreen = (BYTE) CVT(green[i]);\r
-                                               pal[i].rgbBlue = (BYTE) CVT(blue[i]);           \r
-                                       } else {\r
-                                               pal[i].rgbRed = (BYTE) red[i];\r
-                                               pal[i].rgbGreen = (BYTE) green[i];\r
-                                               pal[i].rgbBlue = (BYTE) blue[i];        \r
-                                       }\r
-                               }\r
-                               break;\r
-               }\r
-               if (!BIG_palette) { // + VK (BIG palette is stored until image is ready)\r
-                       SetPalette(pal,/*head.biClrUsed*/ 1<<bpp);      //palette assign // * VK\r
-                       free(pal); \r
-                       pal = NULL; \r
-               }\r
-\r
-               // read the tiff lines and save them in the DIB\r
-               uint32 nrow;\r
-               uint32 ys;\r
-               int line = CalculateLine(width, bitspersample * samplesperpixel);\r
-               \r
-               long bitsize = TIFFStripSize(m_tif);\r
-               //verify bitsize: could be wrong if StripByteCounts is missing.\r
-               if (bitsize<(long)(head.biSizeImage*samplesperpixel))\r
-                       bitsize = head.biSizeImage*samplesperpixel;\r
-\r
-               if ((bitspersample > 8) && (bitspersample != 16))       // + VK (for bitspersample == 9..15,17..32..64\r
-                       bitsize *= (bitspersample + 7)/8; \r
-\r
-               int tiled_image = TIFFIsTiled(m_tif);\r
-               uint32 tw=0, tl=0;\r
-               BYTE* tilebuf=NULL;\r
-               if (tiled_image){\r
-                       TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw);\r
-                       TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl);\r
-                       rowsperstrip = tl;\r
-                       bitsize = TIFFTileSize(m_tif) * (int)(1+width/tw);\r
-                       tilebuf = (BYTE*)malloc(TIFFTileSize(m_tif));\r
-               }\r
-               \r
-               bits = (BYTE*)malloc(bitspersample==16? bitsize*2 : bitsize); // * VK\r
-               BYTE * bits16 = NULL;                                                                             // + VK\r
-               int line16    = 0;                                                                                        // + VK\r
-\r
-               if (!tiled_image && bitspersample==16) {                                          // + VK +\r
-                       line16 = line;\r
-                       line   = CalculateLine(width, 8 * samplesperpixel);\r
-                       bits16 = bits;\r
-                       bits   = (BYTE*)malloc(bitsize);\r
-               }\r
-\r
-               if (bits==NULL){\r
-                       if (bits16) free(bits16);                                                                 // + VK\r
-                       if (pal)        free(pal);                                                                        // + VK\r
-                       if (tilebuf)free(tilebuf);                                                                // + VK       \r
-                       cx_throw("CxImageTIF can't allocate memory");\r
-               }\r
-\r
-#ifdef FIX_16BPP_DARKIMG // + VK: for each line, store shift count bits used to fix it\r
-               BYTE* row_shifts = NULL;\r
-               if (bits16) row_shifts = (BYTE*)malloc(height); \r
-#endif\r
-\r
-               for (ys = 0; ys < height; ys += rowsperstrip) {\r
-\r
-                       if (info.nEscape){ // <vho> - cancel decoding\r
-                               free(bits);\r
-                               cx_throw("Cancelled");\r
-                       }\r
-\r
-                       nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip);\r
-\r
-                       if (tiled_image){\r
-                               uint32 imagew = TIFFScanlineSize(m_tif);\r
-                               uint32 tilew  = TIFFTileRowSize(m_tif);\r
-                               int iskew = imagew - tilew;\r
-                               uint8* bufp = (uint8*) bits;\r
-\r
-                               uint32 colb = 0;\r
-                               for (uint32 col = 0; col < width; col += tw) {\r
-                                       if (TIFFReadTile(m_tif, tilebuf, col, ys, 0, 0) < 0){\r
-                                               free(tilebuf);\r
-                                               free(bits);\r
-                                               cx_throw("Corrupted tiled TIFF file!");\r
-                                       }\r
-\r
-                                       if (colb + tw > imagew) {\r
-                                               uint32 owidth = imagew - colb;\r
-                                               uint32 oskew = tilew - owidth;\r
-                                               TileToStrip(bufp + colb, tilebuf, nrow, owidth, oskew + iskew, oskew );\r
-                                       } else {\r
-                                               TileToStrip(bufp + colb, tilebuf, nrow, tilew, iskew, 0);\r
-                                       }\r
-                                       colb += tilew;\r
-                               }\r
-\r
-                       } else {\r
-                               if (TIFFReadEncodedStrip(m_tif, TIFFComputeStrip(m_tif, ys, 0), \r
-                                       (bits16? bits16 : bits), nrow * (bits16 ? line16 : line)) == -1) { // * VK\r
-\r
-#ifdef NOT_IGNORE_CORRUPTED\r
-                                       free(bits);\r
-                                       if (bits16) free(bits16);  // + VK\r
-                                       cx_throw("Corrupted TIFF file!");\r
-#else\r
-                                       break;\r
-#endif\r
-                               }\r
-                       }\r
-\r
-                       for (y = 0; y < nrow; y++) {\r
-                               long offset=(nrow-y-1)*line;\r
-                               if ((bitspersample==16) && !BIG_palette) {      // * VK\r
-                                       long offset16 = (nrow-y-1)*line16;              // + VK\r
-                                       if (bits16)     {                                                       // + VK +\r
-#ifdef FIX_16BPP_DARKIMG\r
-                                               int the_shift;\r
-                                               BYTE hi_byte, hi_max=0;\r
-                                               DWORD xi;\r
-                                               for (xi=0;xi<(uint32)line;xi++) {\r
-                                                       hi_byte = bits16[xi*2+offset16+1];\r
-                                                       if(hi_byte>hi_max)\r
-                                                               hi_max = hi_byte;\r
-                                               }\r
-                                               the_shift = (hi_max == 0) ? 8 : 0;\r
-                                               if (!the_shift)\r
-                                                       while( ! (hi_max & 0x80) ) {\r
-                                                               the_shift++;\r
-                                                               hi_max <<= 1;\r
-                                                       }\r
-                                               row_shifts[height-ys-nrow+y] = the_shift;\r
-                                               the_shift = 8 - the_shift;\r
-                                               for (xi=0;xi<(uint32)line;xi++) \r
-                                                       bits[xi+offset]= ((bits16[xi*2+offset16+1]<<8) | bits16[xi*2+offset16]) >> the_shift;\r
-#else\r
-                                               for (DWORD xi=0;xi<(uint32)line;xi++) \r
-                                                       bits[xi+offset]=bits16[xi*2+offset16+1];\r
-#endif\r
-                                       } else {\r
-                                               for (DWORD xi=0;xi<width;xi++)\r
-                                                       bits[xi+offset]=bits[xi*2+offset+1];\r
-                                                       }\r
-                               }\r
-                               if (samplesperpixel==1) { \r
-                                       if (BIG_palette)\r
-                                               if (bits16) {\r
-                                                       long offset16 = (nrow-y-1)*line16;              // + VK\r
-                                                       MoveBitsPal( info.pImage + info.dwEffWidth * (height-ys-nrow+y),\r
-                                                                        bits16 + offset16, width, bitspersample, pal );\r
-                                               } else\r
-                                                       MoveBitsPal( info.pImage + info.dwEffWidth * (height-ys-nrow+y),\r
-                                                                        bits + offset, width, bitspersample, pal );\r
-                                       else if ((bitspersample == head.biBitCount) || \r
-                                               (bitspersample == 16))  //simple 8bpp, 4bpp image or 16bpp\r
-                                               memcpy(info.pImage+info.dwEffWidth*(height-ys-nrow+y),bits+offset,info.dwEffWidth);\r
-                                       else\r
-                                               MoveBits( info.pImage + info.dwEffWidth * (height-ys-nrow+y),\r
-                                                                 bits + offset, width, bitspersample );\r
-                               } else if (samplesperpixel==2) { //8bpp image with alpha layer\r
-                                       int xi=0;\r
-                                       int ii=0;\r
-                                       int yi=height-ys-nrow+y;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       if (!pAlpha) AlphaCreate();                     // + VK\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                                       while (ii<line){\r
-                                               SetPixelIndex(xi,yi,bits[ii+offset]);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                               AlphaSet(xi,yi,bits[ii+offset+1]);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                                               ii+=2;\r
-                                               xi++;\r
-                                               if (xi>=(int)width){\r
-                                                       yi--;\r
-                                                       xi=0;\r
-                                               }\r
-                                       }\r
-                               } else { //photometric==PHOTOMETRIC_CIELAB\r
-                                       if (head.biBitCount!=24){ //fix image\r
-                                               Create(width,height,24,CXIMAGE_FORMAT_TIF);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                               if (samplesperpixel==4) AlphaCreate();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                                       }\r
-\r
-                                       int xi=0;\r
-                                       uint32 ii=0;\r
-                                       int yi=height-ys-nrow+y;\r
-                                       RGBQUAD c;\r
-                                       int l,a,b,bitsoffset;\r
-                                       double p,cx,cy,cz,cr,cg,cb;\r
-                                       while (ii</*line*/width){               // * VK\r
-                                               bitsoffset = ii*samplesperpixel+offset;\r
-                                               l=bits[bitsoffset];\r
-                                               a=bits[bitsoffset+1];\r
-                                               b=bits[bitsoffset+2];\r
-                                               if (a>127) a-=256;\r
-                                               if (b>127) b-=256;\r
-                                               // lab to xyz\r
-                                               p = (l/2.55 + 16) / 116.0;\r
-                                               cx = pow( p + a * 0.002, 3);\r
-                                               cy = pow( p, 3);\r
-                                               cz = pow( p - b * 0.005, 3);\r
-                                               // white point\r
-                                               cx*=0.95047;\r
-                                               //cy*=1.000;\r
-                                               cz*=1.0883;\r
-                                               // xyz to rgb\r
-                                               cr =  3.240479 * cx - 1.537150 * cy - 0.498535 * cz;\r
-                                               cg = -0.969256 * cx + 1.875992 * cy + 0.041556 * cz;\r
-                                               cb =  0.055648 * cx - 0.204043 * cy + 1.057311 * cz;\r
-\r
-                                               if ( cr > 0.00304 ) cr = 1.055 * pow(cr,0.41667) - 0.055;\r
-                                                       else            cr = 12.92 * cr;\r
-                                               if ( cg > 0.00304 ) cg = 1.055 * pow(cg,0.41667) - 0.055;\r
-                                                       else            cg = 12.92 * cg;\r
-                                               if ( cb > 0.00304 ) cb = 1.055 * pow(cb,0.41667) - 0.055;\r
-                                                       else            cb = 12.92 * cb;\r
-\r
-                                               c.rgbRed  =(BYTE)max(0,min(255,(int)(cr*255)));\r
-                                               c.rgbGreen=(BYTE)max(0,min(255,(int)(cg*255)));\r
-                                               c.rgbBlue =(BYTE)max(0,min(255,(int)(cb*255)));\r
-\r
-                                               SetPixelColor(xi,yi,c);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                               if (samplesperpixel==4) AlphaSet(xi,yi,bits[bitsoffset+3]);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                                               ii++;\r
-                                               xi++;\r
-                                               if (xi>=(int)width){\r
-                                                       yi--;\r
-                                                       xi=0;\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               free(bits);\r
-               if (bits16) free(bits16);\r
-\r
-#ifdef FIX_16BPP_DARKIMG\r
-               if (row_shifts && (samplesperpixel == 1) && (bitspersample==16) && !BIG_palette) {\r
-                       // 1. calculate maximum necessary shift\r
-                       int min_row_shift = 8;\r
-                       for( y=0; y<height; y++ ) {\r
-                               if (min_row_shift > row_shifts[y]) min_row_shift = row_shifts[y];\r
-                       }\r
-                       // 2. for rows having less shift value, correct such rows:\r
-                       for( y=0; y<height; y++ ) {\r
-                               if (min_row_shift < row_shifts[y]) {\r
-                                       int need_shift = row_shifts[y] - min_row_shift;\r
-                                       BYTE* data = info.pImage + info.dwEffWidth * y;\r
-                                       for( x=0; x<width; x++, data++ )\r
-                                               *data >>= need_shift;\r
-                               }\r
-                       }\r
-               }\r
-               if (row_shifts) free( row_shifts );\r
-#endif\r
-\r
-               if (tiled_image) free(tilebuf);\r
-               if (pal)                 free(pal);\r
-\r
-               switch(orientation){\r
-               case ORIENTATION_TOPRIGHT: /* row 0 top, col 0 rhs */\r
-                       Mirror();\r
-                       break;\r
-               case ORIENTATION_BOTRIGHT: /* row 0 bottom, col 0 rhs */\r
-                       Flip();\r
-                       Mirror();\r
-                       break;\r
-               case ORIENTATION_BOTLEFT: /* row 0 bottom, col 0 lhs */\r
-                       Flip();\r
-                       break;\r
-               case ORIENTATION_LEFTTOP: /* row 0 lhs, col 0 top */\r
-                       RotateRight();\r
-                       Mirror();\r
-                       break;\r
-               case ORIENTATION_RIGHTTOP: /* row 0 rhs, col 0 top */\r
-                       RotateLeft();\r
-                       break;\r
-               case ORIENTATION_RIGHTBOT: /* row 0 rhs, col 0 bottom */\r
-                       RotateLeft();\r
-                       Mirror();\r
-                       break;\r
-               case ORIENTATION_LEFTBOT: /* row 0 lhs, col 0 bottom */\r
-                       RotateRight();\r
-                       break;\r
-               }\r
-\r
-       }\r
-  } cx_catch {\r
-         if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-         if (m_tif) TIFFClose(m_tif);\r
-         if (info.nEscape == -1 && info.dwType == CXIMAGE_FORMAT_TIF) return true;\r
-         return false;\r
-  }\r
-       TIFFClose(m_tif);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageTIF::Encode(CxFile * hFile, bool bAppend)\r
-{\r
-  cx_try\r
-  {\r
-       if (hFile==NULL) cx_throw(CXIMAGE_ERR_NOFILE);\r
-       if (pDib==NULL) cx_throw(CXIMAGE_ERR_NOIMAGE);\r
-\r
-       // <RJ> replaced "w+b" with "a", to append an image directly on an existing file\r
-       if (m_tif2==NULL) m_tif2=_TIFFOpenEx(hFile, "a");\r
-       if (m_tif2==NULL) cx_throw("initialization fail");\r
-\r
-       if (bAppend || m_pages) m_multipage=true;\r
-       m_pages++;\r
-\r
-       if (!EncodeBody(m_tif2,m_multipage,m_pages,m_pages)) cx_throw("Error saving TIFF file");\r
-       if (bAppend) {\r
-               if (!TIFFWriteDirectory(m_tif2)) cx_throw("Error saving TIFF directory");\r
-       }\r
-  } cx_catch {\r
-         if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-         if (m_tif2){\r
-                 TIFFClose(m_tif2);\r
-                 m_tif2=NULL;\r
-                 m_multipage=false;\r
-                 m_pages=0;\r
-         }\r
-         return false;\r
-  }\r
-       if (!bAppend){\r
-               TIFFClose(m_tif2);\r
-               m_tif2=NULL;\r
-               m_multipage=false;\r
-               m_pages=0;\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Thanks to Abe <God(dot)bless(at)marihuana(dot)com>\r
-bool CxImageTIF::Encode(CxFile * hFile, CxImage ** pImages, int pagecount)\r
-{\r
-  cx_try\r
-  {\r
-       if (hFile==NULL) cx_throw("invalid file pointer");\r
-       if (pImages==NULL || pagecount<=0) cx_throw("multipage TIFF, no images!");\r
-\r
-       int i;\r
-       for (i=0; i<pagecount; i++){\r
-               if (pImages[i]==NULL)\r
-                       cx_throw("Bad image pointer");\r
-               if (!(pImages[i]->IsValid()))\r
-                       cx_throw("Empty image");\r
-       }\r
-\r
-       CxImageTIF ghost;\r
-       for (i=0; i<pagecount; i++){\r
-               ghost.Ghost(pImages[i]);\r
-               if (!ghost.Encode(hFile,true)) cx_throw("Error saving TIFF file");\r
-       }\r
-  } cx_catch {\r
-         if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-         return false;\r
-  }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageTIF::EncodeBody(TIFF *m_tif, bool multipage, int page, int pagecount)\r
-{\r
-       uint32 height=head.biHeight;\r
-       uint32 width=head.biWidth;\r
-       uint16 bitcount=head.biBitCount;\r
-       uint16 bitspersample;\r
-       uint16 samplesperpixel;\r
-       uint16 photometric=0;\r
-       uint16 compression;\r
-//     uint16 pitch;\r
-//     int line;\r
-       uint32 x, y;\r
-\r
-       samplesperpixel = ((bitcount == 24) || (bitcount == 32)) ? (BYTE)3 : (BYTE)1;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (bitcount==24 && AlphaIsValid()) { bitcount=32; samplesperpixel=4; }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       bitspersample = bitcount / samplesperpixel;\r
-\r
-       //set the PHOTOMETRIC tag\r
-       RGBQUAD *rgb = GetPalette();\r
-       switch (bitcount) {\r
-               case 1:\r
-                       if (CompareColors(&rgb[0],&rgb[1])<0) {\r
-                               /* <abe> some viewers do not handle PHOTOMETRIC_MINISBLACK:\r
-                                * let's transform the image in PHOTOMETRIC_MINISWHITE\r
-                                */\r
-                               //invert the colors\r
-                               RGBQUAD tempRGB=GetPaletteColor(0);\r
-                               SetPaletteColor(0,GetPaletteColor(1));\r
-                               SetPaletteColor(1,tempRGB);\r
-                               //invert the pixels\r
-                               BYTE *iSrc=info.pImage;\r
-                               for (unsigned long i=0;i<head.biSizeImage;i++){\r
-                                       *iSrc=(BYTE)~(*(iSrc));\r
-                                       iSrc++;\r
-                               }\r
-                               photometric = PHOTOMETRIC_MINISWHITE;\r
-                               //photometric = PHOTOMETRIC_MINISBLACK;\r
-                       } else {\r
-                               photometric = PHOTOMETRIC_MINISWHITE;\r
-                       }\r
-                       break;\r
-               case 4: // Check if the DIB has a color or a greyscale palette\r
-               case 8:\r
-                       photometric = PHOTOMETRIC_MINISBLACK; //default to gray scale\r
-                       for (x = 0; x < head.biClrUsed; x++) {\r
-                               if ((rgb->rgbRed != x)||(rgb->rgbRed != rgb->rgbGreen)||(rgb->rgbRed != rgb->rgbBlue)){\r
-                                       photometric = PHOTOMETRIC_PALETTE;\r
-                                       break;\r
-                               }\r
-                               rgb++;\r
-                       }\r
-                       break;\r
-               case 24:\r
-               case 32:\r
-                       photometric = PHOTOMETRIC_RGB;                  \r
-                       break;\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid() && bitcount==8) samplesperpixel=2; //8bpp + alpha layer\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-//     line = CalculateLine(width, bitspersample * samplesperpixel);\r
-//     pitch = (uint16)CalculatePitch(line);\r
-\r
-       //prepare the palette struct\r
-       RGBQUAD pal[256];\r
-       if (GetPalette()){\r
-               BYTE b;\r
-               memcpy(pal,GetPalette(),GetPaletteSize());\r
-               for(WORD a=0;a<head.biClrUsed;a++){     //swap blue and red components\r
-                       b=pal[a].rgbBlue; pal[a].rgbBlue=pal[a].rgbRed; pal[a].rgbRed=b;\r
-               }\r
-       }\r
-\r
-       // handle standard width/height/bpp stuff\r
-       TIFFSetField(m_tif, TIFFTAG_IMAGEWIDTH, width);\r
-       TIFFSetField(m_tif, TIFFTAG_IMAGELENGTH, height);\r
-       TIFFSetField(m_tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);\r
-       TIFFSetField(m_tif, TIFFTAG_BITSPERSAMPLE, bitspersample);\r
-       TIFFSetField(m_tif, TIFFTAG_PHOTOMETRIC, photometric);\r
-       TIFFSetField(m_tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // single image plane \r
-       TIFFSetField(m_tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);\r
-\r
-       uint32 rowsperstrip = TIFFDefaultStripSize(m_tif, (uint32) -1);  //<REC> gives better compression\r
-       TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);\r
-\r
-       // handle metrics\r
-       TIFFSetField(m_tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);\r
-       TIFFSetField(m_tif, TIFFTAG_XRESOLUTION, (float)info.xDPI);\r
-       TIFFSetField(m_tif, TIFFTAG_YRESOLUTION, (float)info.yDPI);\r
-//     TIFFSetField(m_tif, TIFFTAG_XPOSITION, (float)info.xOffset);\r
-//     TIFFSetField(m_tif, TIFFTAG_YPOSITION, (float)info.yOffset);\r
-\r
-       // multi-paging - Thanks to Abe <God(dot)bless(at)marihuana(dot)com>\r
-       if (multipage)\r
-       {\r
-               char page_number[20];\r
-               sprintf(page_number, "Page %d", page);\r
-\r
-               TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);\r
-               TIFFSetField(m_tif, TIFFTAG_PAGENUMBER, page,pagecount);\r
-               TIFFSetField(m_tif, TIFFTAG_PAGENAME, page_number);\r
-       } else {\r
-               TIFFSetField(m_tif, TIFFTAG_SUBFILETYPE, 0);\r
-       }\r
-\r
-       // palettes (image colormaps are automatically scaled to 16-bits)\r
-       if (photometric == PHOTOMETRIC_PALETTE) {\r
-               uint16 *r, *g, *b;\r
-               r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * 256);\r
-               g = r + 256;\r
-               b = g + 256;\r
-\r
-               for (int i = 255; i >= 0; i--) {\r
-                       b[i] = (uint16)SCALE((uint16)pal[i].rgbRed);\r
-                       g[i] = (uint16)SCALE((uint16)pal[i].rgbGreen);\r
-                       r[i] = (uint16)SCALE((uint16)pal[i].rgbBlue);\r
-               }\r
-\r
-               TIFFSetField(m_tif, TIFFTAG_COLORMAP, r, g, b);\r
-               _TIFFfree(r);\r
-       }\r
-\r
-       // compression\r
-       if (GetCodecOption(CXIMAGE_FORMAT_TIF)) {\r
-               compression = (WORD)GetCodecOption(CXIMAGE_FORMAT_TIF);\r
-       } else {\r
-               switch (bitcount) {\r
-                       case 1 :\r
-                               compression = COMPRESSION_CCITTFAX4;\r
-                               break;\r
-                       case 4 :\r
-                       case 8 :\r
-                               compression = COMPRESSION_LZW;\r
-                               break;\r
-                       case 24 :\r
-                       case 32 :\r
-                               compression = COMPRESSION_JPEG;\r
-                               break;\r
-                       default :\r
-                               compression = COMPRESSION_NONE;\r
-                               break;\r
-               }\r
-       }\r
-       TIFFSetField(m_tif, TIFFTAG_COMPRESSION, compression);\r
-\r
-       switch (compression) {\r
-       case COMPRESSION_JPEG:\r
-               TIFFSetField(m_tif, TIFFTAG_JPEGQUALITY, GetJpegQuality());\r
-               TIFFSetField(m_tif, TIFFTAG_ROWSPERSTRIP, ((7+rowsperstrip)>>3)<<3);\r
-               break;\r
-       case COMPRESSION_LZW:\r
-               if (bitcount>=8) TIFFSetField(m_tif, TIFFTAG_PREDICTOR, 2);\r
-               break;\r
-       }\r
-\r
-       // read the DIB lines from bottom to top and save them in the TIF\r
-\r
-       BYTE *bits;\r
-       switch(bitcount) {                              \r
-               case 1 :\r
-               case 4 :\r
-               case 8 :\r
-               {\r
-                       if (samplesperpixel==1){\r
-                               bits = (BYTE*)malloc(info.dwEffWidth);\r
-                               if (!bits) return false;\r
-                               for (y = 0; y < height; y++) {\r
-                                       memcpy(bits,info.pImage + (height - y - 1)*info.dwEffWidth,info.dwEffWidth);\r
-                                       if (TIFFWriteScanline(m_tif,bits, y, 0)==-1){\r
-                                               free(bits);\r
-                                               return false;\r
-                                       }\r
-                               }\r
-                               free(bits);\r
-                       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       else { //8bpp + alpha layer\r
-                               bits = (BYTE*)malloc(2*width);\r
-                               if (!bits) return false;\r
-                               for (y = 0; y < height; y++) {\r
-                                       for (x=0;x<width;x++){\r
-                                               bits[2*x]=BlindGetPixelIndex(x,height - y - 1);\r
-                                               bits[2*x+1]=AlphaGet(x,height - y - 1);\r
-                                       }\r
-                                       if (TIFFWriteScanline(m_tif,bits, y, 0)==-1) {\r
-                                               free(bits);\r
-                                               return false;\r
-                                       }\r
-                               }\r
-                               free(bits);\r
-                       }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       break;\r
-               }                               \r
-               case 24:\r
-               {\r
-                       BYTE *buffer = (BYTE *)malloc(info.dwEffWidth);\r
-                       if (!buffer) return false;\r
-                       for (y = 0; y < height; y++) {\r
-                               // get a pointer to the scanline\r
-                               memcpy(buffer, info.pImage + (height - y - 1)*info.dwEffWidth, info.dwEffWidth);\r
-                               // TIFFs store color data RGB instead of BGR\r
-                               BYTE *pBuf = buffer;\r
-                               for (x = 0; x < width; x++) {\r
-                                       BYTE tmp = pBuf[0];\r
-                                       pBuf[0] = pBuf[2];\r
-                                       pBuf[2] = tmp;\r
-                                       pBuf += 3;\r
-                               }\r
-                               // write the scanline to disc\r
-                               if (TIFFWriteScanline(m_tif, buffer, y, 0)==-1){\r
-                                       free(buffer);\r
-                                       return false;\r
-                               }\r
-                       }\r
-                       free(buffer);\r
-                       break;\r
-               }                               \r
-               case 32 :\r
-               {\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       BYTE *buffer = (BYTE *)malloc((info.dwEffWidth*4)/3);\r
-                       if (!buffer) return false;\r
-                       for (y = 0; y < height; y++) {\r
-                               // get a pointer to the scanline\r
-                               memcpy(buffer, info.pImage + (height - y - 1)*info.dwEffWidth, info.dwEffWidth);\r
-                               // TIFFs store color data RGB instead of BGR\r
-                               BYTE *pSrc = buffer + 3 * width;\r
-                               BYTE *pDst = buffer + 4 * width;\r
-                               for (x = 0; x < width; x++) {\r
-                                       pDst-=4;\r
-                                       pSrc-=3;\r
-                                       pDst[3] = AlphaGet(width-x-1,height-y-1);\r
-                                       pDst[2] = pSrc[0];\r
-                                       pDst[1] = pSrc[1];\r
-                                       pDst[0] = pSrc[2];\r
-                               }\r
-                               // write the scanline to disc\r
-                               if (TIFFWriteScanline(m_tif, buffer, y, 0)==-1){\r
-                                       free(buffer);\r
-                                       return false;\r
-                               }\r
-                       }\r
-                       free(buffer);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       break;\r
-               }                               \r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageTIF::TileToStrip(uint8* out, uint8* in,    uint32 rows, uint32 cols, int outskew, int inskew)\r
-{\r
-       while (rows-- > 0) {\r
-               uint32 j = cols;\r
-               while (j-- > 0)\r
-                       *out++ = *in++;\r
-               out += outskew;\r
-               in += inskew;\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-TIFF* CxImageTIF::TIFFOpenEx(CxFile * hFile)\r
-{\r
-       if (hFile) return _TIFFOpenEx(hFile, "rb");\r
-       return NULL;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageTIF::TIFFCloseEx(TIFF* tif)\r
-{\r
-       if (tif) TIFFClose(tif);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageTIF::MoveBits( BYTE* dest, BYTE* from, int count, int bpp )\r
-{      int offbits = 0;\r
-       uint16 w;\r
-       uint32 d;\r
-       if (bpp <= 8) {\r
-               while (count-- > 0) {\r
-                       if (offbits + bpp <= 8)\r
-                               w = *from >> (8 - offbits - bpp);\r
-                       else {\r
-                       w = *from++ << (offbits + bpp - 8);\r
-                               w |= *from >> (16 - offbits - bpp);\r
-                       }\r
-                       offbits += bpp;\r
-                       if (offbits >= 8) {\r
-                               offbits -= 8;\r
-                       if (offbits == 0) from++;\r
-                       }       \r
-                       *dest++ = (BYTE)w & ((1 << bpp)-1);\r
-               }\r
-       } else if (bpp < 16) {\r
-               while (count-- > 0) {\r
-                       d = (*from << 24) | (from[1]<<16) | (from[2]<<8) | from[3];\r
-                       d >>= (24 - offbits);\r
-                       *dest++ = (BYTE) ( d );\r
-                       offbits += bpp;\r
-                       while (offbits >= 8) {\r
-                               from++;\r
-                               offbits -= 8;\r
-                       }\r
-               }\r
-       } else if (bpp < 32) {\r
-               while (count-- > 0) {\r
-                       d = (*from << 24) | (from[1]<<16) | (from[2]<<8) | from[3];\r
-                       //d = *(uint32*)from;\r
-                       *dest++ = (BYTE) ( d >> (offbits + bpp - 8) );\r
-                       offbits += bpp;\r
-                       while (offbits >= 8) {\r
-                               from++;\r
-                               offbits -= 8;\r
-                       }\r
-               }\r
-       } else {\r
-               while (count-- > 0) {\r
-                       d = *(uint32*)from;\r
-                       *dest++ = (BYTE) (d >> 24);\r
-                       from += 4;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-void CxImageTIF::MoveBitsPal( BYTE* dest, BYTE*from, int count, int bpp, RGBQUAD* pal )\r
-{      int offbits = 0;\r
-       uint32 d;\r
-       uint16 palidx;\r
-       while (count-- > 0) {\r
-               d = (*from << 24) | ( *( from + 1 ) << 16 )\r
-                                                 | ( *( from + 2 ) << 8 )\r
-                                                 | ( *( from + 3 ) );\r
-               palidx = (uint16) (d >> (32 - offbits - bpp));\r
-               if (bpp < 16) {\r
-                       palidx <<= 16-bpp;\r
-                       palidx = (palidx >> 8) | (palidx <<8);\r
-                       palidx >>= 16-bpp;\r
-               } else palidx = (palidx >> 8) | (palidx << 8);\r
-               *dest++ = pal[palidx].rgbBlue;\r
-               *dest++ = pal[palidx].rgbGreen;\r
-               *dest++ = pal[palidx].rgbRed;\r
-               offbits += bpp;\r
-               while (offbits >= 8) {\r
-                       from++;\r
-                       offbits -= 8;\r
-               }\r
-       }\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-#endif // CXIMAGE_SUPPORT_TIF\r
+/*
+ * File:       ximatif.cpp
+ * Purpose:    Platform Independent TIFF Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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=(DWORD)-1;
+       uint16 photometric=0;
+       uint16 compression=1;
+       uint16 orientation=ORIENTATION_TOPLEFT; //<vho>
+       uint16 res_unit; //<Trifon>
+       uint32 x, y;
+       float resolution, offset;
+       BOOL isRGB;
+       BYTE *bits;             //pointer to source data
+       BYTE *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((long)resolution);
+       }
+       if (TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &resolution))
+       {
+               if (res_unit == RESUNIT_CENTIMETER) resolution = (float)(resolution*2.54f + 0.5f);
+               SetYDPI((long)resolution);
+       }
+
+       if (TIFFGetField(m_tif, TIFFTAG_XPOSITION, &offset))    info.xOffset = (long)offset;
+       if (TIFFGetField(m_tif, TIFFTAG_YPOSITION, &offset))    info.yOffset = (long)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++ = (BYTE)TIFFGetB(row[x]);
+                               *bits++ = (BYTE)TIFFGetG(row[x]);
+                               *bits++ = (BYTE)TIFFGetR(row[x]);
+#if CXIMAGE_SUPPORT_ALPHA
+                               if (samplesperpixel==4) AlphaSet(x,y,(BYTE)TIFFGetA(row[x]));
+#endif //CXIMAGE_SUPPORT_ALPHA
+                       }
+                       row += width;
+                       bits2 += info.dwEffWidth;
+               }
+               _TIFFfree(raster);
+       } else {
+               int 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");
+
+               int 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 (int i=0; i<(1<<bpp); i++){
+                                                       pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(i*(255/((1<<bpp)-1)));
+                                               }
+                                       } else {
+                                               for (int i=0; i<(1<<bpp); i++){
+                                                       pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)(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) {
+                                       int 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 (int i = (1 << ( BIG_palette ? bitspersample : bpp )) - 1; i >= 0; i--) {
+                                       if (Palette16Bits) {
+                                               pal[i].rgbRed =(BYTE) CVT(red[i]);
+                                               pal[i].rgbGreen = (BYTE) CVT(green[i]);
+                                               pal[i].rgbBlue = (BYTE) CVT(blue[i]);           
+                                       } else {
+                                               pal[i].rgbRed = (BYTE) red[i];
+                                               pal[i].rgbGreen = (BYTE) green[i];
+                                               pal[i].rgbBlue = (BYTE) 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;
+               int line = CalculateLine(width, bitspersample * samplesperpixel);
+               
+               long bitsize = TIFFStripSize(m_tif);
+               //verify bitsize: could be wrong if StripByteCounts is missing.
+               if (bitsize<(long)(head.biSizeImage*samplesperpixel))
+                       bitsize = head.biSizeImage*samplesperpixel;
+
+               if ((bitspersample > 8) && (bitspersample != 16))       // + VK (for bitspersample == 9..15,17..32..64
+                       bitsize *= (bitspersample + 7)/8; 
+
+               int tiled_image = TIFFIsTiled(m_tif);
+               uint32 tw=0, tl=0;
+               BYTE* tilebuf=NULL;
+               if (tiled_image){
+                       TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &tw);
+                       TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &tl);
+                       rowsperstrip = tl;
+                       bitsize = TIFFTileSize(m_tif) * (int)(1+width/tw);
+                       tilebuf = (BYTE*)malloc(TIFFTileSize(m_tif));
+               }
+               
+               bits = (BYTE*)malloc(bitspersample==16? bitsize*2 : bitsize); // * VK
+               BYTE * bits16 = NULL;                                                                             // + VK
+               int line16    = 0;                                                                                        // + VK
+
+               if (!tiled_image && bitspersample==16) {                                          // + VK +
+                       line16 = line;
+                       line   = CalculateLine(width, 8 * samplesperpixel);
+                       bits16 = bits;
+                       bits   = (BYTE*)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
+               BYTE* row_shifts = NULL;
+               if (bits16) row_shifts = (BYTE*)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);
+                               int 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++) {
+                               long offset=(nrow-y-1)*line;
+                               if ((bitspersample==16) && !BIG_palette) {      // * VK
+                                       long offset16 = (nrow-y-1)*line16;              // + VK
+                                       if (bits16)     {                                                       // + VK +
+#ifdef FIX_16BPP_DARKIMG
+                                               int the_shift;
+                                               BYTE hi_byte, hi_max=0;
+                                               DWORD 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 (DWORD xi=0;xi<(uint32)line;xi++) 
+                                                       bits[xi+offset]=bits16[xi*2+offset16+1];
+#endif
+                                       } else {
+                                               for (DWORD xi=0;xi<width;xi++)
+                                                       bits[xi+offset]=bits[xi*2+offset+1];
+                                                       }
+                               }
+                               if (samplesperpixel==1) { 
+                                       if (BIG_palette)
+                                               if (bits16) {
+                                                       long 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,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
+                                       int xi=0;
+                                       int ii=0;
+                                       int 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>=(int)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
+                                       }
+
+                                       int xi=0;
+                                       uint32 ii=0;
+                                       int yi=height-ys-nrow+y;
+                                       RGBQUAD c;
+                                       int 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  =(BYTE)max(0,min(255,(int)(cr*255)));
+                                               c.rgbGreen=(BYTE)max(0,min(255,(int)(cg*255)));
+                                               c.rgbBlue =(BYTE)max(0,min(255,(int)(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>=(int)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
+                       int 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]) {
+                                       int need_shift = row_shifts[y] - min_row_shift;
+                                       BYTE* 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, int pagecount)
+{
+  cx_try
+  {
+       if (hFile==NULL) cx_throw("invalid file pointer");
+       if (pImages==NULL || pagecount<=0) cx_throw("multipage TIFF, no images!");
+
+       int 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, int page, int pagecount)
+{
+       uint32 height=head.biHeight;
+       uint32 width=head.biWidth;
+       uint16 bitcount=head.biBitCount;
+       uint16 bitspersample;
+       uint16 samplesperpixel;
+       uint16 photometric=0;
+       uint16 compression;
+//     uint16 pitch;
+//     int line;
+       uint32 x, y;
+
+       samplesperpixel = ((bitcount == 24) || (bitcount == 32)) ? (BYTE)3 : (BYTE)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
+                               BYTE *iSrc=info.pImage;
+                               for (unsigned long i=0;i<head.biSizeImage;i++){
+                                       *iSrc=(BYTE)~(*(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()){
+               BYTE b;
+               memcpy(pal,GetPalette(),GetPaletteSize());
+               for(WORD 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 (int 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 = (WORD)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
+
+       BYTE *bits;
+       switch(bitcount) {                              
+               case 1 :
+               case 4 :
+               case 8 :
+               {
+                       if (samplesperpixel==1){
+                               bits = (BYTE*)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 = (BYTE*)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:
+               {
+                       BYTE *buffer = (BYTE *)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
+                               BYTE *pBuf = buffer;
+                               for (x = 0; x < width; x++) {
+                                       BYTE 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
+                       BYTE *buffer = (BYTE *)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
+                               BYTE *pSrc = buffer + 3 * width;
+                               BYTE *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, int outskew, int 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( BYTE* dest, BYTE* from, int count, int bpp )
+{      int 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++ = (BYTE)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++ = (BYTE) ( 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++ = (BYTE) ( d >> (offbits + bpp - 8) );
+                       offbits += bpp;
+                       while (offbits >= 8) {
+                               from++;
+                               offbits -= 8;
+                       }
+               }
+       } else {
+               while (count-- > 0) {
+                       d = *(uint32*)from;
+                       *dest++ = (BYTE) (d >> 24);
+                       from += 4;
+               }
+       }
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImageTIF::MoveBitsPal( BYTE* dest, BYTE*from, int count, int bpp, RGBQUAD* pal )
+{      int 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
index e12443074c36074249fdc7f3d6c7053b14e45da1..8886316cd7a753fd094d01dc71beb5a0a20e9702 100644 (file)
@@ -1,62 +1,62 @@
-/*\r
- * File:       ximatif.h\r
- * Purpose:    TIFF Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageTIF (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- *\r
- * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes\r
- *\r
- * Special thanks to Abe <God(dot)bless(at)marihuana(dot)com> for MultiPageTIFF code.\r
- *\r
- * LibTIFF is:\r
- * Copyright (c) 1988-1997 Sam Leffler\r
- * Copyright (c) 1991-1997 Silicon Graphics, Inc.\r
- * ==========================================================\r
- */\r
-\r
-#if !defined(__ximatif_h)\r
-#define __ximatif_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_TIF\r
-\r
-#include "../tiff/tiffio.h"\r
-\r
-class DLL_EXP CxImageTIF: public CxImage\r
-{\r
-public:\r
-       CxImageTIF(): CxImage(CXIMAGE_FORMAT_TIF) {m_tif2=NULL; m_multipage=false; m_pages=0;}\r
-       ~CxImageTIF();\r
-\r
-       TIFF* TIFFOpenEx(CxFile * hFile);\r
-       void  TIFFCloseEx(TIFF* tif);\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_TIF);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_TIF);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile, bool bAppend=false);\r
-       bool Encode(CxFile * hFile, CxImage ** pImages, int pagecount);\r
-       bool Encode(FILE *hFile, bool bAppend=false) { CxIOFile file(hFile); return Encode(&file,bAppend); }\r
-       bool Encode(FILE *hFile, CxImage ** pImages, int pagecount)\r
-                               { CxIOFile file(hFile); return Encode(&file, pImages, pagecount); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-\r
-protected:\r
-       void TileToStrip(uint8* out, uint8* in, uint32 rows, uint32 cols, int outskew, int inskew);\r
-       bool EncodeBody(TIFF *m_tif, bool multipage=false, int page=0, int pagecount=0);\r
-       TIFF *m_tif2;\r
-       bool m_multipage;\r
-       int  m_pages;\r
-       void MoveBits( BYTE* dest, BYTE* from, int count, int bpp );\r
-       void MoveBitsPal( BYTE* dest, BYTE*from, int count, int bpp, RGBQUAD* pal );\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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, int pagecount);
+       bool Encode(FILE *hFile, bool bAppend=false) { CxIOFile file(hFile); return Encode(&file,bAppend); }
+       bool Encode(FILE *hFile, CxImage ** pImages, int pagecount)
+                               { CxIOFile file(hFile); return Encode(&file, pImages, pagecount); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+
+protected:
+       void TileToStrip(uint8* out, uint8* in, uint32 rows, uint32 cols, int outskew, int inskew);
+       bool EncodeBody(TIFF *m_tif, bool multipage=false, int page=0, int pagecount=0);
+       TIFF *m_tif2;
+       bool m_multipage;
+       int  m_pages;
+       void MoveBits( BYTE* dest, BYTE* from, int count, int bpp );
+       void MoveBitsPal( BYTE* dest, BYTE*from, int count, int bpp, RGBQUAD* pal );
+};
+
+#endif
+
+#endif
index 9f136a05d69ff48d8fc91237e5258727863e9309..d3aac0182ae0e0532080d1c4c72e4abcf7c110e7 100644 (file)
-// xImaTran.cpp : Transformation functions\r
-/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-#include "ximath.h"\r
-\r
-#if CXIMAGE_SUPPORT_BASICTRANSFORMATIONS\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::GrayScale()\r
-{\r
-       if (!pDib) return false;\r
-       if (head.biBitCount<=8){\r
-               RGBQUAD* ppal=GetPalette();\r
-               int gray;\r
-               //converts the colors to gray, use the blue channel only\r
-               for(DWORD i=0;i<head.biClrUsed;i++){\r
-                       gray=(int)RGB2GRAY(ppal[i].rgbRed,ppal[i].rgbGreen,ppal[i].rgbBlue);\r
-                       ppal[i].rgbBlue = (BYTE)gray;\r
-               }\r
-               // preserve transparency\r
-               if (info.nBkgndIndex >= 0) info.nBkgndIndex = ppal[info.nBkgndIndex].rgbBlue;\r
-               //create a "real" 8 bit gray scale image\r
-               if (head.biBitCount==8){\r
-                       BYTE *img=info.pImage;\r
-                       for(DWORD i=0;i<head.biSizeImage;i++) img[i]=ppal[img[i]].rgbBlue;\r
-                       SetGrayPalette();\r
-               }\r
-               //transform to 8 bit gray scale\r
-               if (head.biBitCount==4 || head.biBitCount==1){\r
-                       CxImage ima;\r
-                       ima.CopyInfo(*this);\r
-                       if (!ima.Create(head.biWidth,head.biHeight,8,info.dwType)) return false;\r
-                       ima.SetGrayPalette();\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       ima.SelectionCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       ima.AlphaCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       for (long y=0;y<head.biHeight;y++){\r
-                               BYTE *iDst = ima.GetBits(y);\r
-                               BYTE *iSrc = GetBits(y);\r
-                               for (long x=0;x<head.biWidth; x++){\r
-                                       //iDst[x]=ppal[BlindGetPixelIndex(x,y)].rgbBlue;\r
-                                       if (head.biBitCount==4){\r
-                                               BYTE pos = (BYTE)(4*(1-x%2));\r
-                                               iDst[x]= ppal[(BYTE)((iSrc[x >> 1]&((BYTE)0x0F<<pos)) >> pos)].rgbBlue;\r
-                                       } else {\r
-                                               BYTE pos = (BYTE)(7-x%8);\r
-                                               iDst[x]= ppal[(BYTE)((iSrc[x >> 3]&((BYTE)0x01<<pos)) >> pos)].rgbBlue;\r
-                                       }\r
-                               }\r
-                       }\r
-                       Transfer(ima);\r
-               }\r
-       } else { //from RGB to 8 bit gray scale\r
-               BYTE *iSrc=info.pImage;\r
-               CxImage ima;\r
-               ima.CopyInfo(*this);\r
-               if (!ima.Create(head.biWidth,head.biHeight,8,info.dwType)) return false;\r
-               ima.SetGrayPalette();\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-               ima.SelectionCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               ima.AlphaCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-               BYTE *img=ima.GetBits();\r
-               long l8=ima.GetEffWidth();\r
-               long l=head.biWidth * 3;\r
-               for(long y=0; y < head.biHeight; y++) {\r
-                       for(long x=0,x8=0; x < l; x+=3,x8++) {\r
-                               img[x8+y*l8]=(BYTE)RGB2GRAY(*(iSrc+x+2),*(iSrc+x+1),*(iSrc+x+0));\r
-                       }\r
-                       iSrc+=info.dwEffWidth;\r
-               }\r
-               Transfer(ima);\r
-       }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa Mirror\r
- * \author [qhbo]\r
- */\r
-bool CxImage::Flip(bool bFlipSelection, bool bFlipAlpha)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       BYTE *buff = (BYTE*)malloc(info.dwEffWidth);\r
-       if (!buff) return false;\r
-\r
-       BYTE *iSrc,*iDst;\r
-       iSrc = GetBits(head.biHeight-1);\r
-       iDst = GetBits(0);\r
-       for (long i=0; i<(head.biHeight/2); ++i)\r
-       {\r
-               memcpy(buff, iSrc, info.dwEffWidth);\r
-               memcpy(iSrc, iDst, info.dwEffWidth);\r
-               memcpy(iDst, buff, info.dwEffWidth);\r
-               iSrc-=info.dwEffWidth;\r
-               iDst+=info.dwEffWidth;\r
-       }\r
-\r
-       free(buff);\r
-\r
-       if (bFlipSelection){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-               SelectionFlip();\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-       }\r
-\r
-       if (bFlipAlpha){\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               AlphaFlip();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       }\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \sa Flip\r
- */\r
-bool CxImage::Mirror(bool bMirrorSelection, bool bMirrorAlpha)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       CxImage* imatmp = new CxImage(*this,false,true,true);\r
-       if (!imatmp) return false;\r
-       if (!imatmp->IsValid()){\r
-               delete imatmp;\r
-               return false;\r
-       }\r
-\r
-       BYTE *iSrc,*iDst;\r
-       long wdt=(head.biWidth-1) * (head.biBitCount==24 ? 3:1);\r
-       iSrc=info.pImage + wdt;\r
-       iDst=imatmp->info.pImage;\r
-       long x,y;\r
-       switch (head.biBitCount){\r
-       case 24:\r
-               for(y=0; y < head.biHeight; y++){\r
-                       for(x=0; x <= wdt; x+=3){\r
-                               *(iDst+x)=*(iSrc-x);\r
-                               *(iDst+x+1)=*(iSrc-x+1);\r
-                               *(iDst+x+2)=*(iSrc-x+2);\r
-                       }\r
-                       iSrc+=info.dwEffWidth;\r
-                       iDst+=info.dwEffWidth;\r
-               }\r
-               break;\r
-       case 8:\r
-               for(y=0; y < head.biHeight; y++){\r
-                       for(x=0; x <= wdt; x++)\r
-                               *(iDst+x)=*(iSrc-x);\r
-                       iSrc+=info.dwEffWidth;\r
-                       iDst+=info.dwEffWidth;\r
-               }\r
-               break;\r
-       default:\r
-               for(y=0; y < head.biHeight; y++){\r
-                       for(x=0; x <= wdt; x++)\r
-                               imatmp->SetPixelIndex(x,y,GetPixelIndex(wdt-x,y));\r
-               }\r
-       }\r
-\r
-       if (bMirrorSelection){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-               imatmp->SelectionMirror();\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-       }\r
-\r
-       if (bMirrorAlpha){\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               imatmp->AlphaMirror();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       }\r
-\r
-       Transfer(*imatmp);\r
-       delete imatmp;\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#define RBLOCK 64\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::RotateLeft(CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long newWidth = GetHeight();\r
-       long newHeight = GetWidth();\r
-\r
-       CxImage imgDest;\r
-       imgDest.CopyInfo(*this);\r
-       imgDest.Create(newWidth,newHeight,GetBpp(),GetType());\r
-       imgDest.SetPalette(GetPalette());\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()) imgDest.AlphaCreate();\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       if (SelectionIsValid()) imgDest.SelectionCreate();\r
-#endif\r
-\r
-       long x,x2,y,dlineup;\r
-       \r
-       // Speedy rotate for BW images <Robert Abram>\r
-       if (head.biBitCount == 1) {\r
-       \r
-               BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp;\r
-               ldiv_t div_r;\r
-\r
-               BYTE *bsrc = GetBits(), *bdest = imgDest.GetBits();\r
-               dbitsmax = bdest + imgDest.head.biSizeImage - 1;\r
-               dlineup = 8 * imgDest.info.dwEffWidth - imgDest.head.biWidth;\r
-\r
-               imgDest.Clear(0);\r
-               for (y = 0; y < head.biHeight; y++) {\r
-                       // Figure out the Column we are going to be copying to\r
-                       div_r = ldiv(y + dlineup, (long)8);\r
-                       // set bit pos of src column byte                               \r
-                       bitpos = (BYTE)(1 << div_r.rem);\r
-                       srcdisp = bsrc + y * info.dwEffWidth;\r
-                       for (x = 0; x < (long)info.dwEffWidth; x++) {\r
-                               // Get Source Bits\r
-                               sbits = srcdisp + x;\r
-                               // Get destination column\r
-                               nrow = bdest + (x * 8) * imgDest.info.dwEffWidth + imgDest.info.dwEffWidth - 1 - div_r.quot;\r
-                               for (long z = 0; z < 8; z++) {\r
-                                  // Get Destination Byte\r
-                                       dbits = nrow + z * imgDest.info.dwEffWidth;\r
-                                       if ((dbits < bdest) || (dbits > dbitsmax)) break;\r
-                                       if (*sbits & (128 >> z)) *dbits |= bitpos;\r
-                               }\r
-                       }\r
-               }//for y\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               if (AlphaIsValid()) {\r
-                       for (x = 0; x < newWidth; x++){\r
-                               x2=newWidth-x-1;\r
-                               for (y = 0; y < newHeight; y++){\r
-                                       imgDest.AlphaSet(x,y,BlindAlphaGet(y, x2));\r
-                               }//for y\r
-                       }//for x\r
-               }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-               if (SelectionIsValid()) {\r
-                       imgDest.info.rSelectionBox.left = newWidth-info.rSelectionBox.top;\r
-                       imgDest.info.rSelectionBox.right = newWidth-info.rSelectionBox.bottom;\r
-                       imgDest.info.rSelectionBox.bottom = info.rSelectionBox.left;\r
-                       imgDest.info.rSelectionBox.top = info.rSelectionBox.right;\r
-                       for (x = 0; x < newWidth; x++){\r
-                               x2=newWidth-x-1;\r
-                               for (y = 0; y < newHeight; y++){\r
-                                       imgDest.SelectionSet(x,y,BlindSelectionGet(y, x2));\r
-                               }//for y\r
-                       }//for x\r
-               }\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-       } else {\r
-       //anything other than BW:\r
-       //bd, 10. 2004: This optimized version of rotation rotates image by smaller blocks. It is quite\r
-       //a bit faster than obvious algorithm, because it produces much less CPU cache misses.\r
-       //This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current\r
-       //CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase\r
-       //speed somehow, but once you drop out of CPU's cache, things will slow down drastically.\r
-       //For older CPUs with less cache, lower value would yield better results.\r
-               \r
-               BYTE *srcPtr, *dstPtr;                        //source and destionation for 24-bit version\r
-               int xs, ys;                                   //x-segment and y-segment\r
-               for (xs = 0; xs < newWidth; xs+=RBLOCK) {       //for all image blocks of RBLOCK*RBLOCK pixels\r
-                       for (ys = 0; ys < newHeight; ys+=RBLOCK) {\r
-                               if (head.biBitCount==24) {\r
-                                       //RGB24 optimized pixel access:\r
-                                       for (x = xs; x < min(newWidth, xs+RBLOCK); x++){    //do rotation\r
-                                               info.nProgress = (long)(100*x/newWidth);\r
-                                               x2=newWidth-x-1;\r
-                                               dstPtr = (BYTE*) imgDest.BlindGetPixelPointer(x,ys);\r
-                                               srcPtr = (BYTE*) BlindGetPixelPointer(ys, x2);\r
-                                               for (y = ys; y < min(newHeight, ys+RBLOCK); y++){\r
-                                                       //imgDest.SetPixelColor(x, y, GetPixelColor(y, x2));\r
-                                                       *(dstPtr) = *(srcPtr);\r
-                                                       *(dstPtr+1) = *(srcPtr+1);\r
-                                                       *(dstPtr+2) = *(srcPtr+2);\r
-                                                       srcPtr += 3;\r
-                                                       dstPtr += imgDest.info.dwEffWidth;\r
-                                               }//for y\r
-                                       }//for x\r
-                               } else {\r
-                                       //anything else than 24bpp (and 1bpp): palette\r
-                                       for (x = xs; x < min(newWidth, xs+RBLOCK); x++){\r
-                                               info.nProgress = (long)(100*x/newWidth); //<Anatoly Ivasyuk>\r
-                                               x2=newWidth-x-1;\r
-                                               for (y = ys; y < min(newHeight, ys+RBLOCK); y++){\r
-                                                       imgDest.SetPixelIndex(x, y, BlindGetPixelIndex(y, x2));\r
-                                               }//for y\r
-                                       }//for x\r
-                               }//if (version selection)\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               if (AlphaIsValid()) {\r
-                                       for (x = xs; x < min(newWidth, xs+RBLOCK); x++){\r
-                                               x2=newWidth-x-1;\r
-                                               for (y = ys; y < min(newHeight, ys+RBLOCK); y++){\r
-                                                       imgDest.AlphaSet(x,y,BlindAlphaGet(y, x2));\r
-                                               }//for y\r
-                                       }//for x\r
-                               }//if (alpha channel)\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                               if (SelectionIsValid()) {\r
-                                       imgDest.info.rSelectionBox.left = newWidth-info.rSelectionBox.top;\r
-                                       imgDest.info.rSelectionBox.right = newWidth-info.rSelectionBox.bottom;\r
-                                       imgDest.info.rSelectionBox.bottom = info.rSelectionBox.left;\r
-                                       imgDest.info.rSelectionBox.top = info.rSelectionBox.right;\r
-                                       for (x = xs; x < min(newWidth, xs+RBLOCK); x++){\r
-                                               x2=newWidth-x-1;\r
-                                               for (y = ys; y < min(newHeight, ys+RBLOCK); y++){\r
-                                                       imgDest.SelectionSet(x,y,BlindSelectionGet(y, x2));\r
-                                               }//for y\r
-                                       }//for x\r
-                               }//if (selection)\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       }//for ys\r
-               }//for xs\r
-       }//if\r
-\r
-       //select the destination\r
-       if (iDst) iDst->Transfer(imgDest);\r
-       else Transfer(imgDest);\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::RotateRight(CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long newWidth = GetHeight();\r
-       long newHeight = GetWidth();\r
-\r
-       CxImage imgDest;\r
-       imgDest.CopyInfo(*this);\r
-       imgDest.Create(newWidth,newHeight,GetBpp(),GetType());\r
-       imgDest.SetPalette(GetPalette());\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()) imgDest.AlphaCreate();\r
-#endif\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       if (SelectionIsValid()) imgDest.SelectionCreate();\r
-#endif\r
-\r
-       long x,y,y2;\r
-       // Speedy rotate for BW images <Robert Abram>\r
-       if (head.biBitCount == 1) {\r
-       \r
-               BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp;\r
-               ldiv_t div_r;\r
-\r
-               BYTE *bsrc = GetBits(), *bdest = imgDest.GetBits();\r
-               dbitsmax = bdest + imgDest.head.biSizeImage - 1;\r
-\r
-               imgDest.Clear(0);\r
-               for (y = 0; y < head.biHeight; y++) {\r
-                       // Figure out the Column we are going to be copying to\r
-                       div_r = ldiv(y, (long)8);\r
-                       // set bit pos of src column byte                               \r
-                       bitpos = (BYTE)(128 >> div_r.rem);\r
-                       srcdisp = bsrc + y * info.dwEffWidth;\r
-                       for (x = 0; x < (long)info.dwEffWidth; x++) {\r
-                               // Get Source Bits\r
-                               sbits = srcdisp + x;\r
-                               // Get destination column\r
-                               nrow = bdest + (imgDest.head.biHeight-1-(x*8)) * imgDest.info.dwEffWidth + div_r.quot;\r
-                               for (long z = 0; z < 8; z++) {\r
-                                  // Get Destination Byte\r
-                                       dbits = nrow - z * imgDest.info.dwEffWidth;\r
-                                       if ((dbits < bdest) || (dbits > dbitsmax)) break;\r
-                                       if (*sbits & (128 >> z)) *dbits |= bitpos;\r
-                               }\r
-                       }\r
-               }\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               if (AlphaIsValid()){\r
-                       for (y = 0; y < newHeight; y++){\r
-                               y2=newHeight-y-1;\r
-                               for (x = 0; x < newWidth; x++){\r
-                                       imgDest.AlphaSet(x,y,BlindAlphaGet(y2, x));\r
-                               }\r
-                       }\r
-               }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-               if (SelectionIsValid()){\r
-                       imgDest.info.rSelectionBox.left = info.rSelectionBox.bottom;\r
-                       imgDest.info.rSelectionBox.right = info.rSelectionBox.top;\r
-                       imgDest.info.rSelectionBox.bottom = newHeight-info.rSelectionBox.right;\r
-                       imgDest.info.rSelectionBox.top = newHeight-info.rSelectionBox.left;\r
-                       for (y = 0; y < newHeight; y++){\r
-                               y2=newHeight-y-1;\r
-                               for (x = 0; x < newWidth; x++){\r
-                                       imgDest.SelectionSet(x,y,BlindSelectionGet(y2, x));\r
-                               }\r
-                       }\r
-               }\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-       } else {\r
-               //anything else but BW\r
-               BYTE *srcPtr, *dstPtr;                        //source and destionation for 24-bit version\r
-               int xs, ys;                                   //x-segment and y-segment\r
-               for (xs = 0; xs < newWidth; xs+=RBLOCK) {\r
-                       for (ys = 0; ys < newHeight; ys+=RBLOCK) {\r
-                               if (head.biBitCount==24) {\r
-                                       //RGB24 optimized pixel access:\r
-                                       for (y = ys; y < min(newHeight, ys+RBLOCK); y++){\r
-                                               info.nProgress = (long)(100*y/newHeight); //<Anatoly Ivasyuk>\r
-                                               y2=newHeight-y-1;\r
-                                               dstPtr = (BYTE*) imgDest.BlindGetPixelPointer(xs,y);\r
-                                               srcPtr = (BYTE*) BlindGetPixelPointer(y2, xs);\r
-                                               for (x = xs; x < min(newWidth, xs+RBLOCK); x++){\r
-                                                       //imgDest.SetPixelColor(x, y, GetPixelColor(y2, x));\r
-                                                       *(dstPtr) = *(srcPtr);\r
-                                                       *(dstPtr+1) = *(srcPtr+1);\r
-                                                       *(dstPtr+2) = *(srcPtr+2);\r
-                                                       dstPtr += 3;\r
-                                                       srcPtr += info.dwEffWidth;\r
-                                               }//for x\r
-                                       }//for y\r
-                               } else {\r
-                                       //anything else than BW & RGB24: palette\r
-                                       for (y = ys; y < min(newHeight, ys+RBLOCK); y++){\r
-                                               info.nProgress = (long)(100*y/newHeight); //<Anatoly Ivasyuk>\r
-                                               y2=newHeight-y-1;\r
-                                               for (x = xs; x < min(newWidth, xs+RBLOCK); x++){\r
-                                                       imgDest.SetPixelIndex(x, y, BlindGetPixelIndex(y2, x));\r
-                                               }//for x\r
-                                       }//for y\r
-                               }//if\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               if (AlphaIsValid()){\r
-                                       for (y = ys; y < min(newHeight, ys+RBLOCK); y++){\r
-                                               y2=newHeight-y-1;\r
-                                               for (x = xs; x < min(newWidth, xs+RBLOCK); x++){\r
-                                                       imgDest.AlphaSet(x,y,BlindAlphaGet(y2, x));\r
-                                               }//for x\r
-                                       }//for y\r
-                               }//if (has alpha)\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                               if (SelectionIsValid()){\r
-                                       imgDest.info.rSelectionBox.left = info.rSelectionBox.bottom;\r
-                                       imgDest.info.rSelectionBox.right = info.rSelectionBox.top;\r
-                                       imgDest.info.rSelectionBox.bottom = newHeight-info.rSelectionBox.right;\r
-                                       imgDest.info.rSelectionBox.top = newHeight-info.rSelectionBox.left;\r
-                                       for (y = ys; y < min(newHeight, ys+RBLOCK); y++){\r
-                                               y2=newHeight-y-1;\r
-                                               for (x = xs; x < min(newWidth, xs+RBLOCK); x++){\r
-                                                       imgDest.SelectionSet(x,y,BlindSelectionGet(y2, x));\r
-                                               }//for x\r
-                                       }//for y\r
-                               }//if (has alpha)\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       }//for ys\r
-               }//for xs\r
-       }//if\r
-\r
-       //select the destination\r
-       if (iDst) iDst->Transfer(imgDest);\r
-       else Transfer(imgDest);\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::Negative()\r
-{\r
-       if (!pDib) return false;\r
-\r
-       if (head.biBitCount<=8){\r
-               if (IsGrayScale()){ //GRAYSCALE, selection\r
-                       if (pSelection){\r
-                               for(long y=info.rSelectionBox.bottom; y<info.rSelectionBox.top; y++){\r
-                                       for(long x=info.rSelectionBox.left; x<info.rSelectionBox.right; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                                               if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                                               {\r
-                                                       BlindSetPixelIndex(x,y,(BYTE)(255-BlindGetPixelIndex(x,y)));\r
-                                               }\r
-                                       }\r
-                               }\r
-                       } else {\r
-                               BYTE *iSrc=info.pImage;\r
-                               for(unsigned long i=0; i < head.biSizeImage; i++){\r
-                                       *iSrc=(BYTE)~(*(iSrc));\r
-                                       iSrc++;\r
-                               }\r
-                       }\r
-               } else { //PALETTE, full image\r
-                       RGBQUAD* ppal=GetPalette();\r
-                       for(DWORD i=0;i<head.biClrUsed;i++){\r
-                               ppal[i].rgbBlue =(BYTE)(255-ppal[i].rgbBlue);\r
-                               ppal[i].rgbGreen =(BYTE)(255-ppal[i].rgbGreen);\r
-                               ppal[i].rgbRed =(BYTE)(255-ppal[i].rgbRed);\r
-                       }\r
-               }\r
-       } else {\r
-               if (pSelection==NULL){ //RGB, full image\r
-                       BYTE *iSrc=info.pImage;\r
-                       for(unsigned long i=0; i < head.biSizeImage; i++){\r
-                               *iSrc=(BYTE)~(*(iSrc));\r
-                               iSrc++;\r
-                       }\r
-               } else { // RGB with selection\r
-                       RGBQUAD color;\r
-                       for(long y=info.rSelectionBox.bottom; y<info.rSelectionBox.top; y++){\r
-                               for(long x=info.rSelectionBox.left; x<info.rSelectionBox.right; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                                       {\r
-                                               color = BlindGetPixelColor(x,y);\r
-                                               color.rgbRed = (BYTE)(255-color.rgbRed);\r
-                                               color.rgbGreen = (BYTE)(255-color.rgbGreen);\r
-                                               color.rgbBlue = (BYTE)(255-color.rgbBlue);\r
-                                               BlindSetPixelColor(x,y,color);\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               //<DP> invert transparent color too\r
-               info.nBkgndColor.rgbBlue = (BYTE)(255-info.nBkgndColor.rgbBlue);\r
-               info.nBkgndColor.rgbGreen = (BYTE)(255-info.nBkgndColor.rgbGreen);\r
-               info.nBkgndColor.rgbRed = (BYTE)(255-info.nBkgndColor.rgbRed);\r
-       }\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_BASICTRANSFORMATIONS\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_TRANSFORMATION\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::Rotate(float angle, CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       //  Copyright (c) 1996-1998 Ulrich von Zadow\r
-\r
-       // Negative the angle, because the y-axis is negative.\r
-       double ang = -angle*acos((float)0)/90;\r
-       int newWidth, newHeight;\r
-       int nWidth = GetWidth();\r
-       int nHeight= GetHeight();\r
-       double cos_angle = cos(ang);\r
-       double sin_angle = sin(ang);\r
-\r
-       // Calculate the size of the new bitmap\r
-       POINT p1={0,0};\r
-       POINT p2={nWidth,0};\r
-       POINT p3={0,nHeight};\r
-       POINT p4={nWidth,nHeight};\r
-       CxPoint2 newP1,newP2,newP3,newP4, leftTop, rightTop, leftBottom, rightBottom;\r
-\r
-       newP1.x = (float)p1.x;\r
-       newP1.y = (float)p1.y;\r
-       newP2.x = (float)(p2.x*cos_angle - p2.y*sin_angle);\r
-       newP2.y = (float)(p2.x*sin_angle + p2.y*cos_angle);\r
-       newP3.x = (float)(p3.x*cos_angle - p3.y*sin_angle);\r
-       newP3.y = (float)(p3.x*sin_angle + p3.y*cos_angle);\r
-       newP4.x = (float)(p4.x*cos_angle - p4.y*sin_angle);\r
-       newP4.y = (float)(p4.x*sin_angle + p4.y*cos_angle);\r
-\r
-       leftTop.x = min(min(newP1.x,newP2.x),min(newP3.x,newP4.x));\r
-       leftTop.y = min(min(newP1.y,newP2.y),min(newP3.y,newP4.y));\r
-       rightBottom.x = max(max(newP1.x,newP2.x),max(newP3.x,newP4.x));\r
-       rightBottom.y = max(max(newP1.y,newP2.y),max(newP3.y,newP4.y));\r
-       leftBottom.x = leftTop.x;\r
-       leftBottom.y = rightBottom.y;\r
-       rightTop.x = rightBottom.x;\r
-       rightTop.y = leftTop.y;\r
-\r
-       newWidth = (int) floor(0.5f + rightTop.x - leftTop.x);\r
-       newHeight= (int) floor(0.5f + leftBottom.y - leftTop.y);\r
-       CxImage imgDest;\r
-       imgDest.CopyInfo(*this);\r
-       imgDest.Create(newWidth,newHeight,GetBpp(),GetType());\r
-       imgDest.SetPalette(GetPalette());\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if(AlphaIsValid())      //MTA: Fix for rotation problem when the image has an alpha channel\r
-       {\r
-               imgDest.AlphaCreate();\r
-               imgDest.AlphaClear();\r
-       }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       int x,y,newX,newY,oldX,oldY;\r
-\r
-       if (head.biClrUsed==0){ //RGB\r
-               for (y = (int)leftTop.y, newY = 0; y<=(int)leftBottom.y; y++,newY++){\r
-                       info.nProgress = (long)(100*newY/newHeight);\r
-                       if (info.nEscape) break;\r
-                       for (x = (int)leftTop.x, newX = 0; x<=(int)rightTop.x; x++,newX++){\r
-                               oldX = (long)(x*cos_angle + y*sin_angle + 0.5);\r
-                               oldY = (long)(y*cos_angle - x*sin_angle + 0.5);\r
-                               imgDest.SetPixelColor(newX,newY,GetPixelColor(oldX,oldY));\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               imgDest.AlphaSet(newX,newY,AlphaGet(oldX,oldY));                                //MTA: copy the alpha value\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       }\r
-               }\r
-       } else { //PALETTE\r
-               for (y = (int)leftTop.y, newY = 0; y<=(int)leftBottom.y; y++,newY++){\r
-                       info.nProgress = (long)(100*newY/newHeight);\r
-                       if (info.nEscape) break;\r
-                       for (x = (int)leftTop.x, newX = 0; x<=(int)rightTop.x; x++,newX++){\r
-                               oldX = (long)(x*cos_angle + y*sin_angle + 0.5);\r
-                               oldY = (long)(y*cos_angle - x*sin_angle + 0.5);\r
-                               imgDest.SetPixelIndex(newX,newY,GetPixelIndex(oldX,oldY));\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               imgDest.AlphaSet(newX,newY,AlphaGet(oldX,oldY));                                //MTA: copy the alpha value\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       }\r
-               }\r
-       }\r
-       //select the destination\r
-       if (iDst) iDst->Transfer(imgDest);\r
-       else Transfer(imgDest);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Rotates image around it's center.\r
- * Method can use interpolation with paletted images, but does not change pallete, so results vary.\r
- * (If you have only four colours in a palette, there's not much room for interpolation.)\r
- * \r
- * \param  angle - angle in degrees (positive values rotate clockwise)\r
- * \param  *iDst - destination image (if null, this image is changed)\r
- * \param  inMethod - interpolation method used\r
- *              (IM_NEAREST_NEIGHBOUR produces aliasing (fast), IM_BILINEAR softens picture a bit (slower)\r
- *               IM_SHARPBICUBIC is slower and produces some halos...)\r
- * \param  ofMethod - overflow method (how to choose colour of pixels that have no source)\r
- * \param  replColor - replacement colour to use (OM_COLOR, OM_BACKGROUND with no background colour...)\r
- * \param  optimizeRightAngles - call faster methods for 90, 180, and 270 degree rotations. Faster methods\r
- *                         are called for angles, where error (in location of corner pixels) is less\r
- *                         than 0.25 pixels.\r
- * \param  bKeepOriginalSize - rotates the image without resizing.\r
- *\r
- * \author ***bd*** 2.2004\r
- */\r
-bool CxImage::Rotate2(float angle, \r
-                       CxImage *iDst, \r
-                       InterpolationMethod inMethod, \r
-                       OverflowMethod ofMethod, \r
-                       RGBQUAD *replColor,\r
-                       bool const optimizeRightAngles,\r
-                                          bool const bKeepOriginalSize)\r
-{\r
-       if (!pDib) return false;                                        //no dib no go\r
-       \r
-       double ang = -angle*acos(0.0f)/90.0f;           //convert angle to radians and invert (positive angle performs clockwise rotation)\r
-       float cos_angle = (float) cos(ang);                     //these two are needed later (to rotate)\r
-       float sin_angle = (float) sin(ang);\r
-       \r
-       //Calculate the size of the new bitmap (rotate corners of image)\r
-       CxPoint2 p[4];                                                          //original corners of the image\r
-       p[0]=CxPoint2(-0.5f,-0.5f);\r
-       p[1]=CxPoint2(GetWidth()-0.5f,-0.5f);\r
-       p[2]=CxPoint2(-0.5f,GetHeight()-0.5f);\r
-       p[3]=CxPoint2(GetWidth()-0.5f,GetHeight()-0.5f);\r
-       CxPoint2 newp[4];                                                               //rotated positions of corners\r
-       //(rotate corners)\r
-       if (bKeepOriginalSize){\r
-               for (int i=0; i<4; i++) {\r
-                       newp[i].x = p[i].x;\r
-                       newp[i].y = p[i].y;\r
-               }//for\r
-       } else {\r
-               for (int i=0; i<4; i++) {\r
-                       newp[i].x = (p[i].x*cos_angle - p[i].y*sin_angle);\r
-                       newp[i].y = (p[i].x*sin_angle + p[i].y*cos_angle);\r
-               }//for i\r
-               \r
-               if (optimizeRightAngles) { \r
-                       //For rotations of 90, -90 or 180 or 0 degrees, call faster routines\r
-                       if (newp[3].Distance(CxPoint2(GetHeight()-0.5f, 0.5f-GetWidth())) < 0.25) \r
-                               //rotation right for circa 90 degrees (diagonal pixels less than 0.25 pixel away from 90 degree rotation destination)\r
-                               return RotateRight(iDst);\r
-                       if (newp[3].Distance(CxPoint2(0.5f-GetHeight(), -0.5f+GetWidth())) < 0.25) \r
-                               //rotation left for ~90 degrees\r
-                               return RotateLeft(iDst);\r
-                       if (newp[3].Distance(CxPoint2(0.5f-GetWidth(), 0.5f-GetHeight())) < 0.25) \r
-                               //rotation left for ~180 degrees\r
-                               return Rotate180(iDst);\r
-                       if (newp[3].Distance(p[3]) < 0.25) {\r
-                               //rotation not significant\r
-                               if (iDst) iDst->Copy(*this);            //copy image to iDst, if required\r
-                               return true;                                            //and we're done\r
-                       }//if\r
-               }//if\r
-       }//if\r
-\r
-       //(read new dimensions from location of corners)\r
-       float minx = (float) min(min(newp[0].x,newp[1].x),min(newp[2].x,newp[3].x));\r
-       float miny = (float) min(min(newp[0].y,newp[1].y),min(newp[2].y,newp[3].y));\r
-       float maxx = (float) max(max(newp[0].x,newp[1].x),max(newp[2].x,newp[3].x));\r
-       float maxy = (float) max(max(newp[0].y,newp[1].y),max(newp[2].y,newp[3].y));\r
-       int newWidth = (int) floor(maxx-minx+0.5f);\r
-       int newHeight= (int) floor(maxy-miny+0.5f);\r
-       float ssx=((maxx+minx)- ((float) newWidth-1))/2.0f;   //start for x\r
-       float ssy=((maxy+miny)- ((float) newHeight-1))/2.0f;  //start for y\r
-\r
-       float newxcenteroffset = 0.5f * newWidth;\r
-       float newycenteroffset = 0.5f * newHeight;\r
-       if (bKeepOriginalSize){\r
-               ssx -= 0.5f * GetWidth();\r
-               ssy -= 0.5f * GetHeight();\r
-       }\r
-\r
-       //create destination image\r
-       CxImage imgDest;\r
-       imgDest.CopyInfo(*this);\r
-       imgDest.Create(newWidth,newHeight,GetBpp(),GetType());\r
-       imgDest.SetPalette(GetPalette());\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if(AlphaIsValid()) imgDest.AlphaCreate(); //MTA: Fix for rotation problem when the image has an alpha channel\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-       \r
-       RGBQUAD rgb;                    //pixel colour\r
-       RGBQUAD rc;\r
-       if (replColor!=0) \r
-               rc=*replColor; \r
-       else {\r
-               rc.rgbRed=255; rc.rgbGreen=255; rc.rgbBlue=255; rc.rgbReserved=0;\r
-       }//if\r
-       float x,y;              //destination location (float, with proper offset)\r
-       float origx, origy;     //origin location\r
-       int destx, desty;       //destination location\r
-       \r
-       y=ssy;                  //initialize y\r
-       if (!IsIndexed()){ //RGB24\r
-               //optimized RGB24 implementation (direct write to destination):\r
-               BYTE *pxptr;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               BYTE *pxptra=0;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-               for (desty=0; desty<newHeight; desty++) {\r
-                       info.nProgress = (long)(100*desty/newHeight);\r
-                       if (info.nEscape) break;\r
-                       //initialize x\r
-                       x=ssx;\r
-                       //calculate pointer to first byte in row\r
-                       pxptr=(BYTE *)imgDest.BlindGetPixelPointer(0, desty);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       //calculate pointer to first byte in row\r
-                       if (AlphaIsValid()) pxptra=imgDest.AlphaGetPointer(0, desty);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       for (destx=0; destx<newWidth; destx++) {\r
-                               //get source pixel coordinate for current destination point\r
-                               //origx = (cos_angle*(x-head.biWidth/2)+sin_angle*(y-head.biHeight/2))+newWidth/2;\r
-                               //origy = (cos_angle*(y-head.biHeight/2)-sin_angle*(x-head.biWidth/2))+newHeight/2;\r
-                               origx = cos_angle*x+sin_angle*y;\r
-                               origy = cos_angle*y-sin_angle*x;\r
-                               if (bKeepOriginalSize){\r
-                                       origx += newxcenteroffset;\r
-                                       origy += newycenteroffset;\r
-                               }\r
-                               rgb = GetPixelColorInterpolated(origx, origy, inMethod, ofMethod, &rc);   //get interpolated colour value\r
-                               //copy alpha and colour value to destination\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               if (pxptra) *pxptra++ = rgb.rgbReserved;\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                               *pxptr++ = rgb.rgbBlue;\r
-                               *pxptr++ = rgb.rgbGreen;\r
-                               *pxptr++ = rgb.rgbRed;\r
-                               x++;\r
-                       }//for destx\r
-                       y++;\r
-               }//for desty\r
-       } else { \r
-               //non-optimized implementation for paletted images\r
-               for (desty=0; desty<newHeight; desty++) {\r
-                       info.nProgress = (long)(100*desty/newHeight);\r
-                       if (info.nEscape) break;\r
-                       x=ssx;\r
-                       for (destx=0; destx<newWidth; destx++) {\r
-                               //get source pixel coordinate for current destination point\r
-                               origx=(cos_angle*x+sin_angle*y);\r
-                               origy=(cos_angle*y-sin_angle*x);\r
-                               if (bKeepOriginalSize){\r
-                                       origx += newxcenteroffset;\r
-                                       origy += newycenteroffset;\r
-                               }\r
-                               rgb = GetPixelColorInterpolated(origx, origy, inMethod, ofMethod, &rc);\r
-                               //***!*** SetPixelColor is slow for palleted images\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               if (AlphaIsValid()) \r
-                                       imgDest.SetPixelColor(destx,desty,rgb,true);\r
-                               else \r
-#endif //CXIMAGE_SUPPORT_ALPHA     \r
-                                       imgDest.SetPixelColor(destx,desty,rgb,false);\r
-                               x++;\r
-                       }//for destx\r
-                       y++;\r
-               }//for desty\r
-       }\r
-       //select the destination\r
-       \r
-       if (iDst) iDst->Transfer(imgDest);\r
-       else Transfer(imgDest);\r
-       \r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::Rotate180(CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long wid = GetWidth();\r
-       long ht = GetHeight();\r
-\r
-       CxImage imgDest;\r
-       imgDest.CopyInfo(*this);\r
-       imgDest.Create(wid,ht,GetBpp(),GetType());\r
-       imgDest.SetPalette(GetPalette());\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid())     imgDest.AlphaCreate();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       long x,y,y2;\r
-       for (y = 0; y < ht; y++){\r
-               info.nProgress = (long)(100*y/ht); //<Anatoly Ivasyuk>\r
-               y2=ht-y-1;\r
-               for (x = 0; x < wid; x++){\r
-                       if(head.biClrUsed==0)//RGB\r
-                               imgDest.SetPixelColor(wid-x-1, y2, BlindGetPixelColor(x, y));\r
-                       else  //PALETTE\r
-                               imgDest.SetPixelIndex(wid-x-1, y2, BlindGetPixelIndex(x, y));\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       if (AlphaIsValid())     imgDest.AlphaSet(wid-x-1, y2,BlindAlphaGet(x, y));\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-               }\r
-       }\r
-\r
-       //select the destination\r
-       if (iDst) iDst->Transfer(imgDest);\r
-       else Transfer(imgDest);\r
-       return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Resizes the image. mode can be 0 for slow (bilinear) method ,\r
- * 1 for fast (nearest pixel) method, or 2 for accurate (bicubic spline interpolation) method.\r
- * The function is faster with 24 and 1 bpp images, slow for 4 bpp images and slowest for 8 bpp images.\r
- */\r
-bool CxImage::Resample(long newx, long newy, int mode, CxImage* iDst)\r
-{\r
-       if (newx==0 || newy==0) return false;\r
-\r
-       if (head.biWidth==newx && head.biHeight==newy){\r
-               if (iDst) iDst->Copy(*this);\r
-               return true;\r
-       }\r
-\r
-       float xScale, yScale, fX, fY;\r
-       xScale = (float)head.biWidth  / (float)newx;\r
-       yScale = (float)head.biHeight / (float)newy;\r
-\r
-       CxImage newImage;\r
-       newImage.CopyInfo(*this);\r
-       newImage.Create(newx,newy,head.biBitCount,GetType());\r
-       newImage.SetPalette(GetPalette());\r
-       if (!newImage.IsValid()){\r
-               strcpy(info.szLastError,newImage.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       switch (mode) {\r
-       case 1: // nearest pixel\r
-       { \r
-               for(long y=0; y<newy; y++){\r
-                       info.nProgress = (long)(100*y/newy);\r
-                       if (info.nEscape) break;\r
-                       fY = y * yScale;\r
-                       for(long x=0; x<newx; x++){\r
-                               fX = x * xScale;\r
-                               newImage.SetPixelColor(x,y,GetPixelColor((long)fX,(long)fY));\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       case 2: // bicubic interpolation by Blake L. Carlson <blake-carlson(at)uiowa(dot)edu\r
-       {\r
-               float f_x, f_y, a, b, rr, gg, bb, r1, r2;\r
-               int   i_x, i_y, xx, yy;\r
-               RGBQUAD rgb;\r
-               BYTE* iDst;\r
-               for(long y=0; y<newy; y++){\r
-                       info.nProgress = (long)(100*y/newy);\r
-                       if (info.nEscape) break;\r
-                       f_y = (float) y * yScale - 0.5f;\r
-                       i_y = (int) floor(f_y);\r
-                       a   = f_y - (float)floor(f_y);\r
-                       for(long x=0; x<newx; x++){\r
-                               f_x = (float) x * xScale - 0.5f;\r
-                               i_x = (int) floor(f_x);\r
-                               b   = f_x - (float)floor(f_x);\r
-\r
-                               rr = gg = bb = 0.0f;\r
-                               for(int m=-1; m<3; m++) {\r
-                                       r1 = KernelBSpline((float) m - a);\r
-                                       yy = i_y+m;\r
-                                       if (yy<0) yy=0;\r
-                                       if (yy>=head.biHeight) yy = head.biHeight-1;\r
-                                       for(int n=-1; n<3; n++) {\r
-                                               r2 = r1 * KernelBSpline(b - (float)n);\r
-                                               xx = i_x+n;\r
-                                               if (xx<0) xx=0;\r
-                                               if (xx>=head.biWidth) xx=head.biWidth-1;\r
-\r
-                                               if (head.biClrUsed){\r
-                                                       rgb = GetPixelColor(xx,yy);\r
-                                               } else {\r
-                                                       iDst  = info.pImage + yy*info.dwEffWidth + xx*3;\r
-                                                       rgb.rgbBlue = *iDst++;\r
-                                                       rgb.rgbGreen= *iDst++;\r
-                                                       rgb.rgbRed  = *iDst;\r
-                                               }\r
-\r
-                                               rr += rgb.rgbRed * r2;\r
-                                               gg += rgb.rgbGreen * r2;\r
-                                               bb += rgb.rgbBlue * r2;\r
-                                       }\r
-                               }\r
-\r
-                               if (head.biClrUsed)\r
-                                       newImage.SetPixelColor(x,y,RGB(rr,gg,bb));\r
-                               else {\r
-                                       iDst = newImage.info.pImage + y*newImage.info.dwEffWidth + x*3;\r
-                                       *iDst++ = (BYTE)bb;\r
-                                       *iDst++ = (BYTE)gg;\r
-                                       *iDst   = (BYTE)rr;\r
-                               }\r
-\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       default: // bilinear interpolation\r
-               if (!(head.biWidth>newx && head.biHeight>newy && head.biBitCount==24)) {\r
-                       // (c) 1999 Steve McMahon (steve@dogma.demon.co.uk)\r
-                       long ifX, ifY, ifX1, ifY1, xmax, ymax;\r
-                       float ir1, ir2, ig1, ig2, ib1, ib2, dx, dy;\r
-                       BYTE r,g,b;\r
-                       RGBQUAD rgb1, rgb2, rgb3, rgb4;\r
-                       xmax = head.biWidth-1;\r
-                       ymax = head.biHeight-1;\r
-                       for(long y=0; y<newy; y++){\r
-                               info.nProgress = (long)(100*y/newy);\r
-                               if (info.nEscape) break;\r
-                               fY = y * yScale;\r
-                               ifY = (int)fY;\r
-                               ifY1 = min(ymax, ifY+1);\r
-                               dy = fY - ifY;\r
-                               for(long x=0; x<newx; x++){\r
-                                       fX = x * xScale;\r
-                                       ifX = (int)fX;\r
-                                       ifX1 = min(xmax, ifX+1);\r
-                                       dx = fX - ifX;\r
-                                       // Interpolate using the four nearest pixels in the source\r
-                                       if (head.biClrUsed){\r
-                                               rgb1=GetPaletteColor(GetPixelIndex(ifX,ifY));\r
-                                               rgb2=GetPaletteColor(GetPixelIndex(ifX1,ifY));\r
-                                               rgb3=GetPaletteColor(GetPixelIndex(ifX,ifY1));\r
-                                               rgb4=GetPaletteColor(GetPixelIndex(ifX1,ifY1));\r
-                                       }\r
-                                       else {\r
-                                               BYTE* iDst;\r
-                                               iDst = info.pImage + ifY*info.dwEffWidth + ifX*3;\r
-                                               rgb1.rgbBlue = *iDst++; rgb1.rgbGreen= *iDst++; rgb1.rgbRed =*iDst;\r
-                                               iDst = info.pImage + ifY*info.dwEffWidth + ifX1*3;\r
-                                               rgb2.rgbBlue = *iDst++; rgb2.rgbGreen= *iDst++; rgb2.rgbRed =*iDst;\r
-                                               iDst = info.pImage + ifY1*info.dwEffWidth + ifX*3;\r
-                                               rgb3.rgbBlue = *iDst++; rgb3.rgbGreen= *iDst++; rgb3.rgbRed =*iDst;\r
-                                               iDst = info.pImage + ifY1*info.dwEffWidth + ifX1*3;\r
-                                               rgb4.rgbBlue = *iDst++; rgb4.rgbGreen= *iDst++; rgb4.rgbRed =*iDst;\r
-                                       }\r
-                                       // Interplate in x direction:\r
-                                       ir1 = rgb1.rgbRed   + (rgb3.rgbRed   - rgb1.rgbRed)   * dy;\r
-                                       ig1 = rgb1.rgbGreen + (rgb3.rgbGreen - rgb1.rgbGreen) * dy;\r
-                                       ib1 = rgb1.rgbBlue  + (rgb3.rgbBlue  - rgb1.rgbBlue)  * dy;\r
-                                       ir2 = rgb2.rgbRed   + (rgb4.rgbRed   - rgb2.rgbRed)   * dy;\r
-                                       ig2 = rgb2.rgbGreen + (rgb4.rgbGreen - rgb2.rgbGreen) * dy;\r
-                                       ib2 = rgb2.rgbBlue  + (rgb4.rgbBlue  - rgb2.rgbBlue)  * dy;\r
-                                       // Interpolate in y:\r
-                                       r = (BYTE)(ir1 + (ir2-ir1) * dx);\r
-                                       g = (BYTE)(ig1 + (ig2-ig1) * dx);\r
-                                       b = (BYTE)(ib1 + (ib2-ib1) * dx);\r
-                                       // Set output\r
-                                       newImage.SetPixelColor(x,y,RGB(r,g,b));\r
-                               }\r
-                       } \r
-               } else {\r
-                       //high resolution shrink, thanks to Henrik Stellmann <henrik.stellmann@volleynet.de>\r
-                       const long ACCURACY = 1000;\r
-                       long i,j; // index for faValue\r
-                       long x,y; // coordinates in  source image\r
-                       BYTE* pSource;\r
-                       BYTE* pDest = newImage.info.pImage;\r
-                       long* naAccu  = new long[3 * newx + 3];\r
-                       long* naCarry = new long[3 * newx + 3];\r
-                       long* naTemp;\r
-                       long  nWeightX,nWeightY;\r
-                       float fEndX;\r
-                       long nScale = (long)(ACCURACY * xScale * yScale);\r
-\r
-                       memset(naAccu,  0, sizeof(long) * 3 * newx);\r
-                       memset(naCarry, 0, sizeof(long) * 3 * newx);\r
-\r
-                       int u, v = 0; // coordinates in dest image\r
-                       float fEndY = yScale - 1.0f;\r
-                       for (y = 0; y < head.biHeight; y++){\r
-                               info.nProgress = (long)(100*y/head.biHeight); //<Anatoly Ivasyuk>\r
-                               if (info.nEscape) break;\r
-                               pSource = info.pImage + y * info.dwEffWidth;\r
-                               u = i = 0;\r
-                               fEndX = xScale - 1.0f;\r
-                               if ((float)y < fEndY) {       // complete source row goes into dest row\r
-                                       for (x = 0; x < head.biWidth; x++){\r
-                                               if ((float)x < fEndX){       // complete source pixel goes into dest pixel\r
-                                                       for (j = 0; j < 3; j++) naAccu[i + j] += (*pSource++) * ACCURACY;\r
-                                               } else {       // source pixel is splitted for 2 dest pixels\r
-                                                       nWeightX = (long)(((float)x - fEndX) * ACCURACY);\r
-                                                       for (j = 0; j < 3; j++){\r
-                                                               naAccu[i] += (ACCURACY - nWeightX) * (*pSource);\r
-                                                               naAccu[3 + i++] += nWeightX * (*pSource++);\r
-                                                       }\r
-                                                       fEndX += xScale;\r
-                                                       u++;\r
-                                               }\r
-                                       }\r
-                               } else {       // source row is splitted for 2 dest rows       \r
-                                       nWeightY = (long)(((float)y - fEndY) * ACCURACY);\r
-                                       for (x = 0; x < head.biWidth; x++){\r
-                                               if ((float)x < fEndX){       // complete source pixel goes into 2 pixel\r
-                                                       for (j = 0; j < 3; j++){\r
-                                                               naAccu[i + j] += ((ACCURACY - nWeightY) * (*pSource));\r
-                                                               naCarry[i + j] += nWeightY * (*pSource++);\r
-                                                       }\r
-                                               } else {       // source pixel is splitted for 4 dest pixels\r
-                                                       nWeightX = (int)(((float)x - fEndX) * ACCURACY);\r
-                                                       for (j = 0; j < 3; j++) {\r
-                                                               naAccu[i] += ((ACCURACY - nWeightY) * (ACCURACY - nWeightX)) * (*pSource) / ACCURACY;\r
-                                                               *pDest++ = (BYTE)(naAccu[i] / nScale);\r
-                                                               naCarry[i] += (nWeightY * (ACCURACY - nWeightX) * (*pSource)) / ACCURACY;\r
-                                                               naAccu[i + 3] += ((ACCURACY - nWeightY) * nWeightX * (*pSource)) / ACCURACY;\r
-                                                               naCarry[i + 3] = (nWeightY * nWeightX * (*pSource)) / ACCURACY;\r
-                                                               i++;\r
-                                                               pSource++;\r
-                                                       }\r
-                                                       fEndX += xScale;\r
-                                                       u++;\r
-                                               }\r
-                                       }\r
-                                       if (u < newx){ // possibly not completed due to rounding errors\r
-                                               for (j = 0; j < 3; j++) *pDest++ = (BYTE)(naAccu[i++] / nScale);\r
-                                       }\r
-                                       naTemp = naCarry;\r
-                                       naCarry = naAccu;\r
-                                       naAccu = naTemp;\r
-                                       memset(naCarry, 0, sizeof(int) * 3);    // need only to set first pixel zero\r
-                                       pDest = newImage.info.pImage + (++v * newImage.info.dwEffWidth);\r
-                                       fEndY += yScale;\r
-                               }\r
-                       }\r
-                       if (v < newy){  // possibly not completed due to rounding errors\r
-                               for (i = 0; i < 3 * newx; i++) *pDest++ = (BYTE)(naAccu[i] / nScale);\r
-                       }\r
-                       delete [] naAccu;\r
-                       delete [] naCarry;\r
-               }\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()){\r
-               newImage.AlphaCreate();\r
-               for(long y=0; y<newy; y++){\r
-                       fY = y * yScale;\r
-                       for(long x=0; x<newx; x++){\r
-                               fX = x * xScale;\r
-                               newImage.AlphaSet(x,y,AlphaGet((long)fX,(long)fY));\r
-                       }\r
-               }\r
-       }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       //select the destination\r
-       if (iDst) iDst->Transfer(newImage);\r
-       else Transfer(newImage);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * New simpler resample. Adds new interpolation methods and simplifies code (using GetPixelColorInterpolated\r
- * and GetAreaColorInterpolated). It also (unlike old method) interpolates alpha layer. \r
- *\r
- * \param  newx, newy - size of resampled image\r
- * \param  inMethod - interpolation method to use (see comments at GetPixelColorInterpolated)\r
- *              If image size is being reduced, averaging is used instead (or simultaneously with) inMethod.\r
- * \param  ofMethod - what to replace outside pixels by (only significant for bordering pixels of enlarged image)\r
- * \param  iDst - pointer to destination CxImage or NULL.\r
- * \param  disableAveraging - force no averaging when shrinking images (Produces aliasing.\r
- *                      You probably just want to leave this off...)\r
- *\r
- * \author ***bd*** 2.2004\r
- */\r
-bool CxImage::Resample2(\r
-  long newx, long newy, \r
-  InterpolationMethod const inMethod, \r
-  OverflowMethod const ofMethod, \r
-  CxImage* const iDst,\r
-  bool const disableAveraging)\r
-{\r
-       if (newx<=0 || newy<=0 || !pDib) return false;\r
-       \r
-       if (head.biWidth==newx && head.biHeight==newy) {\r
-               //image already correct size (just copy and return)\r
-               if (iDst) iDst->Copy(*this);\r
-               return true;\r
-       }//if\r
-       \r
-       //calculate scale of new image (less than 1 for enlarge)\r
-       float xScale, yScale;\r
-       xScale = (float)head.biWidth  / (float)newx;    \r
-       yScale = (float)head.biHeight / (float)newy;\r
-       \r
-       //create temporary destination image\r
-       CxImage newImage;\r
-       newImage.CopyInfo(*this);\r
-       newImage.Create(newx,newy,head.biBitCount,GetType());\r
-       newImage.SetPalette(GetPalette());\r
-       if (!newImage.IsValid()){\r
-               strcpy(info.szLastError,newImage.GetLastError());\r
-               return false;\r
-       }\r
-       \r
-       //and alpha channel if required\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()) newImage.AlphaCreate();\r
-       BYTE *pxptra = 0;       // destination alpha data\r
-#endif\r
-       \r
-       float sX, sY;         //source location\r
-       long dX,dY;           //destination pixel (int value)\r
-       if ((xScale<=1 && yScale<=1) || disableAveraging) {\r
-               //image is being enlarged (or interpolation on demand)\r
-               if (!IsIndexed()) {\r
-                       //RGB24 image (optimized version with direct writes)\r
-                       RGBQUAD q;              //pixel colour\r
-                       BYTE *pxptr;            //pointer to destination pixel\r
-                       for(dY=0; dY<newy; dY++){\r
-                               info.nProgress = (long)(100*dY/newy);\r
-                               if (info.nEscape) break;\r
-                               sY = (dY + 0.5f) * yScale - 0.5f;\r
-                               pxptr=(BYTE*)(newImage.BlindGetPixelPointer(0,dY));\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               pxptra=newImage.AlphaGetPointer(0,dY);\r
-#endif\r
-                               for(dX=0; dX<newx; dX++){\r
-                                       sX = (dX + 0.5f) * xScale - 0.5f;\r
-                                       q=GetPixelColorInterpolated(sX,sY,inMethod,ofMethod,0);\r
-                                       *pxptr++=q.rgbBlue;\r
-                                       *pxptr++=q.rgbGreen;\r
-                                       *pxptr++=q.rgbRed;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       if (pxptra) *pxptra++=q.rgbReserved;\r
-#endif\r
-                               }//for dX\r
-                       }//for dY\r
-               } else {\r
-                       //enlarge paletted image. Slower method.\r
-                       for(dY=0; dY<newy; dY++){\r
-                               info.nProgress = (long)(100*dY/newy);\r
-                               if (info.nEscape) break;\r
-                               sY = (dY + 0.5f) * yScale - 0.5f;\r
-                               for(dX=0; dX<newx; dX++){\r
-                                       sX = (dX + 0.5f) * xScale - 0.5f;\r
-                                       newImage.SetPixelColor(dX,dY,GetPixelColorInterpolated(sX,sY,inMethod,ofMethod,0),true);\r
-                               }//for x\r
-                       }//for y\r
-               }//if\r
-       } else {\r
-               //image size is being reduced (averaging enabled)\r
-               for(dY=0; dY<newy; dY++){\r
-                       info.nProgress = (long)(100*dY/newy); if (info.nEscape) break;\r
-                       sY = (dY+0.5f) * yScale - 0.5f;\r
-                       for(dX=0; dX<newx; dX++){\r
-                               sX = (dX+0.5f) * xScale - 0.5f;\r
-                               newImage.SetPixelColor(dX,dY,GetAreaColorInterpolated(sX, sY, xScale, yScale, inMethod, ofMethod,0),true);\r
-                       }//for x\r
-               }//for y\r
-       }//if\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid() && pxptra == 0){\r
-               for(long y=0; y<newy; y++){\r
-                       dY = (long)(y * yScale);\r
-                       for(long x=0; x<newx; x++){\r
-                               dX = (long)(x * xScale);\r
-                               newImage.AlphaSet(x,y,AlphaGet(dX,dY));\r
-                       }\r
-               }\r
-       }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       //copy new image to the destination\r
-       if (iDst) \r
-               iDst->Transfer(newImage);\r
-       else \r
-               Transfer(newImage);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Reduces the number of bits per pixel to nbit (1, 4 or 8).\r
- * ppal points to a valid palette for the final image; if not supplied the function will use a standard palette.\r
- * ppal is not necessary for reduction to 1 bpp.\r
- */\r
-bool CxImage::DecreaseBpp(DWORD nbit, bool errordiffusion, RGBQUAD* ppal, DWORD clrimportant)\r
-{\r
-       if (!pDib) return false;\r
-       if (head.biBitCount <  nbit){\r
-               strcpy(info.szLastError,"DecreaseBpp: target BPP greater than source BPP");\r
-               return false;\r
-       }\r
-       if (head.biBitCount == nbit){\r
-               if (clrimportant==0) return true;\r
-               if (head.biClrImportant && (head.biClrImportant<clrimportant)) return true;\r
-       }\r
-\r
-       long er,eg,eb;\r
-       RGBQUAD c,ce;\r
-\r
-       CxImage tmp;\r
-       tmp.CopyInfo(*this);\r
-       tmp.Create(head.biWidth,head.biHeight,(WORD)nbit,info.dwType);\r
-       if (clrimportant) tmp.SetClrImportant(clrimportant);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       tmp.SelectionCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       tmp.AlphaCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       if (ppal) {\r
-               if (clrimportant) {\r
-                       tmp.SetPalette(ppal,clrimportant);\r
-               } else {\r
-                       tmp.SetPalette(ppal,1<<tmp.head.biBitCount);\r
-               }\r
-       } else {\r
-               tmp.SetStdPalette();\r
-       }\r
-\r
-       for (long y=0;y<head.biHeight;y++){\r
-               if (info.nEscape) break;\r
-               info.nProgress = (long)(100*y/head.biHeight);\r
-               for (long x=0;x<head.biWidth;x++){\r
-                       if (!errordiffusion){\r
-                               tmp.BlindSetPixelColor(x,y,BlindGetPixelColor(x,y));\r
-                       } else {\r
-                               c = BlindGetPixelColor(x,y);\r
-                               tmp.BlindSetPixelColor(x,y,c);\r
-\r
-                               ce = tmp.BlindGetPixelColor(x,y);\r
-                               er=(long)c.rgbRed - (long)ce.rgbRed;\r
-                               eg=(long)c.rgbGreen - (long)ce.rgbGreen;\r
-                               eb=(long)c.rgbBlue - (long)ce.rgbBlue;\r
-\r
-                               c = GetPixelColor(x+1,y);\r
-                               c.rgbRed = (BYTE)min(255L,max(0L,(long)c.rgbRed + ((er*7)/16)));\r
-                               c.rgbGreen = (BYTE)min(255L,max(0L,(long)c.rgbGreen + ((eg*7)/16)));\r
-                               c.rgbBlue = (BYTE)min(255L,max(0L,(long)c.rgbBlue + ((eb*7)/16)));\r
-                               SetPixelColor(x+1,y,c);\r
-                               int coeff=1;\r
-                               for(int i=-1; i<2; i++){\r
-                                       switch(i){\r
-                                       case -1:\r
-                                               coeff=2; break;\r
-                                       case 0:\r
-                                               coeff=4; break;\r
-                                       case 1:\r
-                                               coeff=1; break;\r
-                                       }\r
-                                       c = GetPixelColor(x+i,y+1);\r
-                                       c.rgbRed = (BYTE)min(255L,max(0L,(long)c.rgbRed + ((er * coeff)/16)));\r
-                                       c.rgbGreen = (BYTE)min(255L,max(0L,(long)c.rgbGreen + ((eg * coeff)/16)));\r
-                                       c.rgbBlue = (BYTE)min(255L,max(0L,(long)c.rgbBlue + ((eb * coeff)/16)));\r
-                                       SetPixelColor(x+i,y+1,c);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Increases the number of bits per pixel of the image.\r
- * \param nbit: 4, 8, 24\r
- */\r
-bool CxImage::IncreaseBpp(DWORD nbit)\r
-{\r
-       if (!pDib) return false;\r
-       switch (nbit){\r
-       case 4:\r
-               {\r
-                       if (head.biBitCount==4) return true;\r
-                       if (head.biBitCount>4) return false;\r
-\r
-                       CxImage tmp;\r
-                       tmp.CopyInfo(*this);\r
-                       tmp.Create(head.biWidth,head.biHeight,4,info.dwType);\r
-                       tmp.SetPalette(GetPalette(),GetNumColors());\r
-                       if (!tmp.IsValid()){\r
-                               strcpy(info.szLastError,tmp.GetLastError());\r
-                               return false;\r
-                       }\r
-\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       tmp.SelectionCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       tmp.AlphaCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-                       for (long y=0;y<head.biHeight;y++){\r
-                               if (info.nEscape) break;\r
-                               for (long x=0;x<head.biWidth;x++){\r
-                                       tmp.BlindSetPixelIndex(x,y,BlindGetPixelIndex(x,y));\r
-                               }\r
-                       }\r
-                       Transfer(tmp);\r
-                       return true;\r
-               }\r
-       case 8:\r
-               {\r
-                       if (head.biBitCount==8) return true;\r
-                       if (head.biBitCount>8) return false;\r
-\r
-                       CxImage tmp;\r
-                       tmp.CopyInfo(*this);\r
-                       tmp.Create(head.biWidth,head.biHeight,8,info.dwType);\r
-                       tmp.SetPalette(GetPalette(),GetNumColors());\r
-                       if (!tmp.IsValid()){\r
-                               strcpy(info.szLastError,tmp.GetLastError());\r
-                               return false;\r
-                       }\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       tmp.SelectionCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       tmp.AlphaCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-                       for (long y=0;y<head.biHeight;y++){\r
-                               if (info.nEscape) break;\r
-                               for (long x=0;x<head.biWidth;x++){\r
-                                       tmp.BlindSetPixelIndex(x,y,BlindGetPixelIndex(x,y));\r
-                               }\r
-                       }\r
-                       Transfer(tmp);\r
-                       return true;\r
-               }\r
-       case 24:\r
-               {\r
-                       if (head.biBitCount==24) return true;\r
-                       if (head.biBitCount>24) return false;\r
-\r
-                       CxImage tmp;\r
-                       tmp.CopyInfo(*this);\r
-                       tmp.Create(head.biWidth,head.biHeight,24,info.dwType);\r
-                       if (!tmp.IsValid()){\r
-                               strcpy(info.szLastError,tmp.GetLastError());\r
-                               return false;\r
-                       }\r
-\r
-                       if (info.nBkgndIndex>=0) //translate transparency\r
-                               tmp.info.nBkgndColor=GetPaletteColor((BYTE)info.nBkgndIndex);\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       tmp.SelectionCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       tmp.AlphaCopy(*this);\r
-                       if (AlphaPaletteIsValid() && !AlphaIsValid()) tmp.AlphaCreate();\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-                       for (long y=0;y<head.biHeight;y++){\r
-                               if (info.nEscape) break;\r
-                               for (long x=0;x<head.biWidth;x++){\r
-                                       tmp.BlindSetPixelColor(x,y,BlindGetPixelColor(x,y),true);\r
-                               }\r
-                       }\r
-                       Transfer(tmp);\r
-                       return true;\r
-               }\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Converts the image to B&W using the desired method :\r
- * - 0 = Floyd-Steinberg\r
- * - 1 = Ordered-Dithering (4x4) \r
- * - 2 = Burkes\r
- * - 3 = Stucki\r
- * - 4 = Jarvis-Judice-Ninke\r
- * - 5 = Sierra\r
- * - 6 = Stevenson-Arce\r
- * - 7 = Bayer (4x4 ordered dithering) \r
- */\r
-bool CxImage::Dither(long method)\r
-{\r
-       if (!pDib) return false;\r
-       if (head.biBitCount == 1) return true;\r
-       \r
-       GrayScale();\r
-\r
-       CxImage tmp;\r
-       tmp.CopyInfo(*this);\r
-       tmp.Create(head.biWidth, head.biHeight, 1, info.dwType);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       tmp.SelectionCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       tmp.AlphaCopy(*this);\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       switch (method){\r
-       case 1:\r
-       {\r
-               // Multi-Level Ordered-Dithering by Kenny Hoff (Oct. 12, 1995)\r
-               #define dth_NumRows 4\r
-               #define dth_NumCols 4\r
-               #define dth_NumIntensityLevels 2\r
-               #define dth_NumRowsLessOne (dth_NumRows-1)\r
-               #define dth_NumColsLessOne (dth_NumCols-1)\r
-               #define dth_RowsXCols (dth_NumRows*dth_NumCols)\r
-               #define dth_MaxIntensityVal 255\r
-               #define dth_MaxDitherIntensityVal (dth_NumRows*dth_NumCols*(dth_NumIntensityLevels-1))\r
-\r
-               int DitherMatrix[dth_NumRows][dth_NumCols] = {{0,8,2,10}, {12,4,14,6}, {3,11,1,9}, {15,7,13,5} };\r
-               \r
-               unsigned char Intensity[dth_NumIntensityLevels] = { 0,1 };                       // 2 LEVELS B/W\r
-               //unsigned char Intensity[NumIntensityLevels] = { 0,255 };                       // 2 LEVELS\r
-               //unsigned char Intensity[NumIntensityLevels] = { 0,127,255 };                   // 3 LEVELS\r
-               //unsigned char Intensity[NumIntensityLevels] = { 0,85,170,255 };                // 4 LEVELS\r
-               //unsigned char Intensity[NumIntensityLevels] = { 0,63,127,191,255 };            // 5 LEVELS\r
-               //unsigned char Intensity[NumIntensityLevels] = { 0,51,102,153,204,255 };        // 6 LEVELS\r
-               //unsigned char Intensity[NumIntensityLevels] = { 0,42,85,127,170,213,255 };     // 7 LEVELS\r
-               //unsigned char Intensity[NumIntensityLevels] = { 0,36,73,109,145,182,219,255 }; // 8 LEVELS\r
-               int DitherIntensity, DitherMatrixIntensity, Offset, DeviceIntensity;\r
-               unsigned char DitherValue;\r
-  \r
-               for (long y=0;y<head.biHeight;y++){\r
-                       info.nProgress = (long)(100*y/head.biHeight);\r
-                       if (info.nEscape) break;\r
-                       for (long x=0;x<head.biWidth;x++){\r
-\r
-                               DeviceIntensity = BlindGetPixelIndex(x,y);\r
-                               DitherIntensity = DeviceIntensity*dth_MaxDitherIntensityVal/dth_MaxIntensityVal;\r
-                               DitherMatrixIntensity = DitherIntensity % dth_RowsXCols;\r
-                               Offset = DitherIntensity / dth_RowsXCols;\r
-                               if (DitherMatrix[y&dth_NumRowsLessOne][x&dth_NumColsLessOne] < DitherMatrixIntensity)\r
-                                       DitherValue = Intensity[1+Offset];\r
-                               else\r
-                                       DitherValue = Intensity[0+Offset];\r
-\r
-                               tmp.BlindSetPixelIndex(x,y,DitherValue);\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       case 2:\r
-       {\r
-               //Burkes error diffusion (Thanks to Franco Gerevini)\r
-               int TotalCoeffSum = 32;\r
-               long error, nlevel, coeff=1;\r
-               BYTE level;\r
-\r
-               for (long y = 0; y < head.biHeight; y++) {\r
-                       info.nProgress = (long)(100 * y / head.biHeight);\r
-                       if (info.nEscape) \r
-                               break;\r
-                       for (long x = 0; x < head.biWidth; x++) {\r
-                               level = BlindGetPixelIndex(x, y);\r
-                               if (level > 128) {\r
-                                       tmp.SetPixelIndex(x, y, 1);\r
-                                       error = level - 255;\r
-                               } else {\r
-                                       tmp.SetPixelIndex(x, y, 0);\r
-                                       error = level;\r
-                               }\r
-\r
-                               nlevel = GetPixelIndex(x + 1, y) + (error * 8) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(x + 1, y, level);\r
-                               nlevel = GetPixelIndex(x + 2, y) + (error * 4) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(x + 2, y, level);\r
-                               int i;\r
-                               for (i = -2; i < 3; i++) {\r
-                                       switch (i) {\r
-                                       case -2:\r
-                                               coeff = 2;\r
-                                               break;\r
-                                       case -1:\r
-                                               coeff = 4;\r
-                                               break;\r
-                                       case 0:\r
-                                               coeff = 8; \r
-                                               break;\r
-                                       case 1:\r
-                                               coeff = 4; \r
-                                               break;\r
-                                       case 2:\r
-                                               coeff = 2; \r
-                                               break;\r
-                                       }\r
-                                       nlevel = GetPixelIndex(x + i, y + 1) + (error * coeff) / TotalCoeffSum;\r
-                                       level = (BYTE)min(255, max(0, (int)nlevel));\r
-                                       SetPixelIndex(x + i, y + 1, level);\r
-                               }\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       case 3:\r
-       {\r
-               //Stucki error diffusion (Thanks to Franco Gerevini)\r
-               int TotalCoeffSum = 42;\r
-               long error, nlevel, coeff=1;\r
-               BYTE level;\r
-\r
-               for (long y = 0; y < head.biHeight; y++) {\r
-                       info.nProgress = (long)(100 * y / head.biHeight);\r
-                       if (info.nEscape) \r
-                               break;\r
-                       for (long x = 0; x < head.biWidth; x++) {\r
-                               level = BlindGetPixelIndex(x, y);\r
-                               if (level > 128) {\r
-                                       tmp.SetPixelIndex(x, y, 1);\r
-                                       error = level - 255;\r
-                               } else {\r
-                                       tmp.SetPixelIndex(x, y, 0);\r
-                                       error = level;\r
-                               }\r
-\r
-                               nlevel = GetPixelIndex(x + 1, y) + (error * 8) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(x + 1, y, level);\r
-                               nlevel = GetPixelIndex(x + 2, y) + (error * 4) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(x + 2, y, level);\r
-                               int i;\r
-                               for (i = -2; i < 3; i++) {\r
-                                       switch (i) {\r
-                                       case -2:\r
-                                               coeff = 2;\r
-                                               break;\r
-                                       case -1:\r
-                                               coeff = 4;\r
-                                               break;\r
-                                       case 0:\r
-                                               coeff = 8; \r
-                                               break;\r
-                                       case 1:\r
-                                               coeff = 4; \r
-                                               break;\r
-                                       case 2:\r
-                                               coeff = 2; \r
-                                               break;\r
-                                       }\r
-                                       nlevel = GetPixelIndex(x + i, y + 1) + (error * coeff) / TotalCoeffSum;\r
-                                       level = (BYTE)min(255, max(0, (int)nlevel));\r
-                                       SetPixelIndex(x + i, y + 1, level);\r
-                               }\r
-                               for (i = -2; i < 3; i++) {\r
-                                       switch (i) {\r
-                                       case -2:\r
-                                               coeff = 1;\r
-                                               break;\r
-                                       case -1:\r
-                                               coeff = 2;\r
-                                               break;\r
-                                       case 0:\r
-                                               coeff = 4; \r
-                                               break;\r
-                                       case 1:\r
-                                               coeff = 2; \r
-                                               break;\r
-                                       case 2:\r
-                                               coeff = 1; \r
-                                               break;\r
-                                       }\r
-                                       nlevel = GetPixelIndex(x + i, y + 2) + (error * coeff) / TotalCoeffSum;\r
-                                       level = (BYTE)min(255, max(0, (int)nlevel));\r
-                                       SetPixelIndex(x + i, y + 2, level);\r
-                               }\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       case 4:\r
-       {\r
-               //Jarvis, Judice and Ninke error diffusion (Thanks to Franco Gerevini)\r
-               int TotalCoeffSum = 48;\r
-               long error, nlevel, coeff=1;\r
-               BYTE level;\r
-\r
-               for (long y = 0; y < head.biHeight; y++) {\r
-                       info.nProgress = (long)(100 * y / head.biHeight);\r
-                       if (info.nEscape) \r
-                               break;\r
-                       for (long x = 0; x < head.biWidth; x++) {\r
-                               level = BlindGetPixelIndex(x, y);\r
-                               if (level > 128) {\r
-                                       tmp.SetPixelIndex(x, y, 1);\r
-                                       error = level - 255;\r
-                               } else {\r
-                                       tmp.SetPixelIndex(x, y, 0);\r
-                                       error = level;\r
-                               }\r
-\r
-                               nlevel = GetPixelIndex(x + 1, y) + (error * 7) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(x + 1, y, level);\r
-                               nlevel = GetPixelIndex(x + 2, y) + (error * 5) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(x + 2, y, level);\r
-                               int i;\r
-                               for (i = -2; i < 3; i++) {\r
-                                       switch (i) {\r
-                                       case -2:\r
-                                               coeff = 3;\r
-                                               break;\r
-                                       case -1:\r
-                                               coeff = 5;\r
-                                               break;\r
-                                       case 0:\r
-                                               coeff = 7; \r
-                                               break;\r
-                                       case 1:\r
-                                               coeff = 5; \r
-                                               break;\r
-                                       case 2:\r
-                                               coeff = 3; \r
-                                               break;\r
-                                       }\r
-                                       nlevel = GetPixelIndex(x + i, y + 1) + (error * coeff) / TotalCoeffSum;\r
-                                       level = (BYTE)min(255, max(0, (int)nlevel));\r
-                                       SetPixelIndex(x + i, y + 1, level);\r
-                               }\r
-                               for (i = -2; i < 3; i++) {\r
-                                       switch (i) {\r
-                                       case -2:\r
-                                               coeff = 1;\r
-                                               break;\r
-                                       case -1:\r
-                                               coeff = 3;\r
-                                               break;\r
-                                       case 0:\r
-                                               coeff = 5; \r
-                                               break;\r
-                                       case 1:\r
-                                               coeff = 3; \r
-                                               break;\r
-                                       case 2:\r
-                                               coeff = 1; \r
-                                               break;\r
-                                       }\r
-                                       nlevel = GetPixelIndex(x + i, y + 2) + (error * coeff) / TotalCoeffSum;\r
-                                       level = (BYTE)min(255, max(0, (int)nlevel));\r
-                                       SetPixelIndex(x + i, y + 2, level);\r
-                               }\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       case 5:\r
-       {\r
-               //Sierra error diffusion (Thanks to Franco Gerevini)\r
-               int TotalCoeffSum = 32;\r
-               long error, nlevel, coeff=1;\r
-               BYTE level;\r
-\r
-               for (long y = 0; y < head.biHeight; y++) {\r
-                       info.nProgress = (long)(100 * y / head.biHeight);\r
-                       if (info.nEscape) \r
-                               break;\r
-                       for (long x = 0; x < head.biWidth; x++) {\r
-                               level = BlindGetPixelIndex(x, y);\r
-                               if (level > 128) {\r
-                                       tmp.SetPixelIndex(x, y, 1);\r
-                                       error = level - 255;\r
-                               } else {\r
-                                       tmp.SetPixelIndex(x, y, 0);\r
-                                       error = level;\r
-                               }\r
-\r
-                               nlevel = GetPixelIndex(x + 1, y) + (error * 5) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(x + 1, y, level);\r
-                               nlevel = GetPixelIndex(x + 2, y) + (error * 3) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(x + 2, y, level);\r
-                               int i;\r
-                               for (i = -2; i < 3; i++) {\r
-                                       switch (i) {\r
-                                       case -2:\r
-                                               coeff = 2;\r
-                                               break;\r
-                                       case -1:\r
-                                               coeff = 4;\r
-                                               break;\r
-                                       case 0:\r
-                                               coeff = 5; \r
-                                               break;\r
-                                       case 1:\r
-                                               coeff = 4; \r
-                                               break;\r
-                                       case 2:\r
-                                               coeff = 2; \r
-                                               break;\r
-                                       }\r
-                                       nlevel = GetPixelIndex(x + i, y + 1) + (error * coeff) / TotalCoeffSum;\r
-                                       level = (BYTE)min(255, max(0, (int)nlevel));\r
-                                       SetPixelIndex(x + i, y + 1, level);\r
-                               }\r
-                               for (i = -1; i < 2; i++) {\r
-                                       switch (i) {\r
-                                       case -1:\r
-                                               coeff = 2;\r
-                                               break;\r
-                                       case 0:\r
-                                               coeff = 3; \r
-                                               break;\r
-                                       case 1:\r
-                                               coeff = 2; \r
-                                               break;\r
-                                       }\r
-                                       nlevel = GetPixelIndex(x + i, y + 2) + (error * coeff) / TotalCoeffSum;\r
-                                       level = (BYTE)min(255, max(0, (int)nlevel));\r
-                                       SetPixelIndex(x + i, y + 2, level);\r
-                               }\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       case 6:\r
-       {\r
-               //Stevenson and Arce error diffusion (Thanks to Franco Gerevini)\r
-               int TotalCoeffSum = 200;\r
-               long error, nlevel;\r
-               BYTE level;\r
-\r
-               for (long y = 0; y < head.biHeight; y++) {\r
-                       info.nProgress = (long)(100 * y / head.biHeight);\r
-                       if (info.nEscape) \r
-                               break;\r
-                       for (long x = 0; x < head.biWidth; x++) {\r
-                               level = BlindGetPixelIndex(x, y);\r
-                               if (level > 128) {\r
-                                       tmp.SetPixelIndex(x, y, 1);\r
-                                       error = level - 255;\r
-                               } else {\r
-                                       tmp.SetPixelIndex(x, y, 0);\r
-                                       error = level;\r
-                               }\r
-\r
-                               int tmp_index_x = x + 2;\r
-                               int tmp_index_y = y;\r
-                               int tmp_coeff = 32;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x - 3;\r
-                               tmp_index_y = y + 1;\r
-                               tmp_coeff = 12;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x - 1;\r
-                               tmp_coeff = 26;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x + 1;\r
-                               tmp_coeff = 30;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x + 3;\r
-                               tmp_coeff = 16;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x - 2;\r
-                               tmp_index_y = y + 2;\r
-                               tmp_coeff = 12;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x;\r
-                               tmp_coeff = 26;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x + 2;\r
-                               tmp_coeff = 12;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x - 3;\r
-                               tmp_index_y = y + 3;\r
-                               tmp_coeff = 5;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x - 1;\r
-                               tmp_coeff = 12;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x + 1;\r
-                               tmp_coeff = 12;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-\r
-                               tmp_index_x = x + 3;\r
-                               tmp_coeff = 5;\r
-                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;\r
-                               level = (BYTE)min(255, max(0, (int)nlevel));\r
-                               SetPixelIndex(tmp_index_x, tmp_index_y, level);\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       case 7:\r
-       {\r
-               // Bayer ordered dither\r
-               int order = 4;\r
-               //create Bayer matrix\r
-               if (order>4) order = 4;\r
-               int size = (1 << (2*order));\r
-               BYTE* Bmatrix = (BYTE*) malloc(size * sizeof(BYTE));\r
-               for(int i = 0; i < size; i++) {\r
-                       int n = order;\r
-                       int x = i / n;\r
-                       int y = i % n;\r
-                       int dither = 0;\r
-                       while (n-- > 0){\r
-                               dither = (((dither<<1)|((x&1) ^ (y&1)))<<1) | (y&1);\r
-                               x >>= 1;\r
-                               y >>= 1;\r
-                       }\r
-                       Bmatrix[i] = (BYTE)(dither);\r
-               }\r
-\r
-               int scale = max(0,(8-2*order));\r
-               int level;\r
-               for (long y=0;y<head.biHeight;y++){\r
-                       info.nProgress = (long)(100*y/head.biHeight);\r
-                       if (info.nEscape) break;\r
-                       for (long x=0;x<head.biWidth;x++){\r
-                               level = BlindGetPixelIndex(x,y) >> scale;\r
-                               if(level > Bmatrix[ (x % order) + order * (y % order) ]){\r
-                                       tmp.SetPixelIndex(x,y,1);\r
-                               } else {\r
-                                       tmp.SetPixelIndex(x,y,0);\r
-                               }\r
-                       }\r
-               }\r
-\r
-               free(Bmatrix);\r
-\r
-               break;\r
-       }\r
-       default:\r
-       {\r
-               // Floyd-Steinberg error diffusion (Thanks to Steve McMahon)\r
-               long error,nlevel,coeff=1;\r
-               BYTE level;\r
-\r
-               for (long y=0;y<head.biHeight;y++){\r
-                       info.nProgress = (long)(100*y/head.biHeight);\r
-                       if (info.nEscape) break;\r
-                       for (long x=0;x<head.biWidth;x++){\r
-\r
-                               level = BlindGetPixelIndex(x,y);\r
-                               if (level > 128){\r
-                                       tmp.SetPixelIndex(x,y,1);\r
-                                       error = level-255;\r
-                               } else {\r
-                                       tmp.SetPixelIndex(x,y,0);\r
-                                       error = level;\r
-                               }\r
-\r
-                               nlevel = GetPixelIndex(x+1,y) + (error * 7)/16;\r
-                               level = (BYTE)min(255,max(0,(int)nlevel));\r
-                               SetPixelIndex(x+1,y,level);\r
-                               for(int i=-1; i<2; i++){\r
-                                       switch(i){\r
-                                       case -1:\r
-                                               coeff=3; break;\r
-                                       case 0:\r
-                                               coeff=5; break;\r
-                                       case 1:\r
-                                               coeff=1; break;\r
-                                       }\r
-                                       nlevel = GetPixelIndex(x+i,y+1) + (error * coeff)/16;\r
-                                       level = (BYTE)min(255,max(0,(int)nlevel));\r
-                                       SetPixelIndex(x+i,y+1,level);\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       }\r
-\r
-       tmp.SetPaletteColor(0,0,0,0);\r
-       tmp.SetPaletteColor(1,255,255,255);\r
-       Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- *     CropRotatedRectangle\r
- * \param topx,topy : topmost and leftmost point of the rectangle \r
-          (topmost, and if there are 2 topmost points, the left one)\r
- * \param  width     : size of the right hand side of rect, from (topx,topy) roundwalking clockwise\r
- * \param  height    : size of the left hand side of rect, from (topx,topy) roundwalking clockwise\r
- * \param  angle     : angle of the right hand side of rect, from (topx,topy)\r
- * \param  iDst      : pointer to destination image (if 0, this image is modified)\r
- * \author  [VATI]\r
- */\r
-bool CxImage::CropRotatedRectangle( long topx, long topy, long width, long height, float angle, CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       \r
-       long startx,starty,endx,endy;\r
-       double cos_angle = cos(angle/*/57.295779513082320877*/);\r
-    double sin_angle = sin(angle/*/57.295779513082320877*/);\r
-\r
-       // if there is nothing special, call the original Crop():\r
-       if ( fabs(angle)<0.0002 )\r
-               return Crop( topx, topy, topx+width, topy+height, iDst);\r
-\r
-       startx = min(topx, topx - (long)(sin_angle*(double)height));\r
-       endx   = topx + (long)(cos_angle*(double)width);\r
-       endy   = topy + (long)(cos_angle*(double)height + sin_angle*(double)width);\r
-       // check: corners of the rectangle must be inside\r
-       if ( IsInside( startx, topy )==false ||\r
-                IsInside( endx, endy ) == false )\r
-                return false;\r
-\r
-       // first crop to bounding rectangle\r
-       CxImage tmp(*this, true, false, true);\r
-       // tmp.Copy(*this, true, false, true);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-    if (!tmp.Crop( startx, topy, endx, endy)){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-       \r
-       // the midpoint of the image now became the same as the midpoint of the rectangle\r
-       // rotate new image with minus angle amount\r
-    if ( false == tmp.Rotate( (float)(-angle*57.295779513082320877) ) ) // Rotate expects angle in degrees\r
-               return false;\r
-\r
-       // crop rotated image to the original selection rectangle\r
-    endx   = (tmp.head.biWidth+width)/2;\r
-       startx = (tmp.head.biWidth-width)/2;\r
-       starty = (tmp.head.biHeight+height)/2;\r
-    endy   = (tmp.head.biHeight-height)/2;\r
-    if ( false == tmp.Crop( startx, starty, endx, endy ) )\r
-               return false;\r
-\r
-       if (iDst) iDst->Transfer(tmp);\r
-       else Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::Crop(const RECT& rect, CxImage* iDst)\r
-{\r
-       return Crop(rect.left, rect.top, rect.right, rect.bottom, iDst);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::Crop(long left, long top, long right, long bottom, CxImage* iDst)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long startx = max(0L,min(left,head.biWidth));\r
-       long endx = max(0L,min(right,head.biWidth));\r
-       long starty = head.biHeight - max(0L,min(top,head.biHeight));\r
-       long endy = head.biHeight - max(0L,min(bottom,head.biHeight));\r
-\r
-       if (startx==endx || starty==endy) return false;\r
-\r
-       if (startx>endx) {long tmp=startx; startx=endx; endx=tmp;}\r
-       if (starty>endy) {long tmp=starty; starty=endy; endy=tmp;}\r
-\r
-       CxImage tmp(endx-startx,endy-starty,head.biBitCount,info.dwType);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       tmp.SetPalette(GetPalette(),head.biClrUsed);\r
-       tmp.info.nBkgndIndex = info.nBkgndIndex;\r
-       tmp.info.nBkgndColor = info.nBkgndColor;\r
-\r
-       switch (head.biBitCount) {\r
-       case 1:\r
-       case 4:\r
-       {\r
-               for(long y=starty, yd=0; y<endy; y++, yd++){\r
-                       info.nProgress = (long)(100*(y-starty)/(endy-starty)); //<Anatoly Ivasyuk>\r
-                       for(long x=startx, xd=0; x<endx; x++, xd++){\r
-                               tmp.SetPixelIndex(xd,yd,GetPixelIndex(x,y));\r
-                       }\r
-               }\r
-               break;\r
-       }\r
-       case 8:\r
-       case 24:\r
-       {\r
-               int linelen = tmp.head.biWidth * tmp.head.biBitCount >> 3;\r
-               BYTE* pDest = tmp.info.pImage;\r
-               BYTE* pSrc = info.pImage + starty * info.dwEffWidth + (startx*head.biBitCount >> 3);\r
-               for(long y=starty; y<endy; y++){\r
-                       info.nProgress = (long)(100*(y-starty)/(endy-starty)); //<Anatoly Ivasyuk>\r
-                       memcpy(pDest,pSrc,linelen);\r
-                       pDest+=tmp.info.dwEffWidth;\r
-                       pSrc+=info.dwEffWidth;\r
-               }\r
-    }\r
-       }\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()){ //<oboolo>\r
-               tmp.AlphaCreate();\r
-               if (!tmp.AlphaIsValid()) return false;\r
-               BYTE* pDest = tmp.pAlpha;\r
-               BYTE* pSrc = pAlpha + startx + starty*head.biWidth;\r
-               for (long y=starty; y<endy; y++){\r
-                       memcpy(pDest,pSrc,endx-startx);\r
-                       pDest+=tmp.head.biWidth;\r
-                       pSrc+=head.biWidth;\r
-               }\r
-       }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-       //select the destination\r
-       if (iDst) iDst->Transfer(tmp);\r
-       else Transfer(tmp);\r
-\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * \param xgain, ygain : can be from 0 to 1.\r
- * \param xpivot, ypivot : is the center of the transformation.\r
- * \param bEnableInterpolation : if true, enables bilinear interpolation.\r
- * \return true if everything is ok \r
- */\r
-bool CxImage::Skew(float xgain, float ygain, long xpivot, long ypivot, bool bEnableInterpolation)\r
-{\r
-       if (!pDib) return false;\r
-       float nx,ny;\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               nx = x + (xgain*(y - ypivot));\r
-                               ny = y + (ygain*(x - xpivot));\r
-#if CXIMAGE_SUPPORT_INTERPOLATION\r
-                               if (bEnableInterpolation){\r
-                                       tmp.SetPixelColor(x,y,GetPixelColorInterpolated(nx, ny, CxImage::IM_BILINEAR, CxImage::OM_BACKGROUND),true);\r
-                               } else\r
-#endif //CXIMAGE_SUPPORT_INTERPOLATION\r
-                               {\r
-                                       if (head.biClrUsed==0){\r
-                                               tmp.SetPixelColor(x,y,GetPixelColor((long)nx,(long)ny));\r
-                                       } else {\r
-                                               tmp.SetPixelIndex(x,y,GetPixelIndex((long)nx,(long)ny));\r
-                                       }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       tmp.AlphaSet(x,y,AlphaGet((long)nx,(long)ny));\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Expands the borders.\r
- * \param left, top, right, bottom = additional dimensions, should be greater than 0.\r
- * \param canvascolor = border color. canvascolor.rgbReserved will set the alpha channel (if any) in the border.\r
- * \param iDst = pointer to destination image (if it's 0, this image is modified)\r
- * \return true if everything is ok \r
- * \author [Colin Urquhart]; changes [DP]\r
- */\r
-bool CxImage::Expand(long left, long top, long right, long bottom, RGBQUAD canvascolor, CxImage* iDst)\r
-{\r
-    if (!pDib) return false;\r
-\r
-    if ((left < 0) || (right < 0) || (bottom < 0) || (top < 0)) return false;\r
-\r
-    long newWidth = head.biWidth + left + right;\r
-    long newHeight = head.biHeight + top + bottom;\r
-\r
-    right = left + head.biWidth - 1;\r
-    top = bottom + head.biHeight - 1;\r
-    \r
-    CxImage tmp;\r
-       tmp.CopyInfo(*this);\r
-       if (!tmp.Create(newWidth, newHeight, head.biBitCount, info.dwType)){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-    tmp.SetPalette(GetPalette(),head.biClrUsed);\r
-\r
-    switch (head.biBitCount) {\r
-    case 1:\r
-    case 4:\r
-               {\r
-                       BYTE pixel = tmp.GetNearestIndex(canvascolor);\r
-                       for(long y=0; y < newHeight; y++){\r
-                               info.nProgress = (long)(100*y/newHeight);\r
-                               for(long x=0; x < newWidth; x++){\r
-                                       if ((y < bottom) || (y > top) || (x < left) || (x > right)) {\r
-                                               tmp.SetPixelIndex(x,y, pixel);\r
-                                       } else {\r
-                                               tmp.SetPixelIndex(x,y,GetPixelIndex(x-left,y-bottom));\r
-                                       }\r
-                               }\r
-                       }\r
-                       break;\r
-               }\r
-    case 8:\r
-    case 24:\r
-               {\r
-                       if (head.biBitCount == 8) {\r
-                               BYTE pixel = tmp.GetNearestIndex( canvascolor);\r
-                               memset(tmp.info.pImage, pixel,  + (tmp.info.dwEffWidth * newHeight));\r
-                       } else {\r
-                               for (long y = 0; y < newHeight; ++y) {\r
-                                       BYTE *pDest = tmp.info.pImage + (y * tmp.info.dwEffWidth);\r
-                                       for (long x = 0; x < newWidth; ++x) {\r
-                                               *pDest++ = canvascolor.rgbBlue;\r
-                                               *pDest++ = canvascolor.rgbGreen;\r
-                                               *pDest++ = canvascolor.rgbRed;\r
-                                       }\r
-                               }\r
-                       }\r
-\r
-                       BYTE* pDest = tmp.info.pImage + (tmp.info.dwEffWidth * bottom) + (left*(head.biBitCount >> 3));\r
-                       BYTE* pSrc = info.pImage;\r
-                       for(long y=bottom; y <= top; y++){\r
-                               info.nProgress = (long)(100*y/(1 + top - bottom));\r
-                               memcpy(pDest,pSrc,(head.biBitCount >> 3) * (right - left + 1));\r
-                               pDest+=tmp.info.dwEffWidth;\r
-                               pSrc+=info.dwEffWidth;\r
-                       }\r
-               }\r
-    }\r
-\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-       if (SelectionIsValid()){\r
-               if (!tmp.SelectionCreate())\r
-                       return false;\r
-               BYTE* pSrc = SelectionGetPointer();\r
-               BYTE* pDst = tmp.SelectionGetPointer(left,bottom);\r
-               for(long y=bottom; y <= top; y++){\r
-                       memcpy(pDst,pSrc, (right - left + 1));\r
-                       pSrc+=head.biWidth;\r
-                       pDst+=tmp.head.biWidth;\r
-               }\r
-               tmp.info.rSelectionBox.left = info.rSelectionBox.left + left;\r
-               tmp.info.rSelectionBox.right = info.rSelectionBox.right + left;\r
-               tmp.info.rSelectionBox.top = info.rSelectionBox.top + bottom;\r
-               tmp.info.rSelectionBox.bottom = info.rSelectionBox.bottom + bottom;\r
-       }\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()){\r
-               if (!tmp.AlphaCreate())\r
-                       return false;\r
-               tmp.AlphaSet(canvascolor.rgbReserved);\r
-               BYTE* pSrc = AlphaGetPointer();\r
-               BYTE* pDst = tmp.AlphaGetPointer(left,bottom);\r
-               for(long y=bottom; y <= top; y++){\r
-                       memcpy(pDst,pSrc, (right - left + 1));\r
-                       pSrc+=head.biWidth;\r
-                       pDst+=tmp.head.biWidth;\r
-               }\r
-       }\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-\r
-    //select the destination\r
-       if (iDst) iDst->Transfer(tmp);\r
-    else Transfer(tmp);\r
-\r
-    return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImage::Expand(long newx, long newy, RGBQUAD canvascolor, CxImage* iDst)\r
-{\r
-       //thanks to <Colin Urquhart>\r
-\r
-    if (!pDib) return false;\r
-\r
-    if ((newx < head.biWidth) || (newy < head.biHeight)) return false;\r
-\r
-    int nAddLeft = (newx - head.biWidth) / 2;\r
-    int nAddTop = (newy - head.biHeight) / 2;\r
-\r
-    return Expand(nAddLeft, nAddTop, newx - (head.biWidth + nAddLeft), newy - (head.biHeight + nAddTop), canvascolor, iDst);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Resamples the image with the correct aspect ratio, and fills the borders.\r
- * \param newx, newy = thumbnail size.\r
- * \param canvascolor = border color.\r
- * \param iDst = pointer to destination image (if it's 0, this image is modified).\r
- * \return true if everything is ok.\r
- * \author [Colin Urquhart]\r
- */\r
-bool CxImage::Thumbnail(long newx, long newy, RGBQUAD canvascolor, CxImage* iDst)\r
-{\r
-    if (!pDib) return false;\r
-\r
-    if ((newx <= 0) || (newy <= 0)) return false;\r
-\r
-    CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-    // determine whether we need to shrink the image\r
-    if ((head.biWidth > newx) || (head.biHeight > newy)) {\r
-        float fScale;\r
-        float fAspect = (float) newx / (float) newy;\r
-        if (fAspect * head.biHeight > head.biWidth) {\r
-            fScale = (float) newy / head.biHeight;\r
-        } else {\r
-            fScale = (float) newx / head.biWidth;\r
-        }\r
-        tmp.Resample((long) (fScale * head.biWidth), (long) (fScale * head.biHeight), 0);\r
-    }\r
-\r
-    // expand the frame\r
-    tmp.Expand(newx, newy, canvascolor, iDst);\r
-\r
-    //select the destination\r
-    if (iDst) iDst->Transfer(tmp);\r
-    else Transfer(tmp);\r
-    return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Perform circle_based transformations.\r
- * \param type - for different transformations\r
- * - 0 for normal (proturberant) FishEye\r
- * - 1 for reverse (concave) FishEye\r
- * - 2 for Swirle \r
- * - 3 for Cilinder mirror\r
- * - 4 for bathroom\r
- *\r
- * \param rmax - effect radius. If 0, the whole image is processed\r
- * \param Koeff - only for swirle\r
- * \author Arkadiy Olovyannikov ark(at)msun(dot)ru\r
- */\r
-bool CxImage::CircleTransform(int type,long rmax,float Koeff)\r
-{\r
-       if (!pDib) return false;\r
-\r
-       long nx,ny;\r
-       double angle,radius,rnew;\r
-\r
-       CxImage tmp(*this);\r
-       if (!tmp.IsValid()){\r
-               strcpy(info.szLastError,tmp.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       long xmin,xmax,ymin,ymax,xmid,ymid;\r
-       if (pSelection){\r
-               xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
-               ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
-       } else {\r
-               xmin = ymin = 0;\r
-               xmax = head.biWidth; ymax=head.biHeight;\r
-       }\r
-       \r
-       xmid = (long) (tmp.GetWidth()/2);\r
-       ymid = (long) (tmp.GetHeight()/2);\r
-\r
-       if (!rmax) rmax=(long)sqrt((float)((xmid-xmin)*(xmid-xmin)+(ymid-ymin)*(ymid-ymin)));\r
-       if (Koeff==0.0f) Koeff=1.0f;\r
-\r
-       for(long y=ymin; y<ymax; y++){\r
-               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));\r
-               if (info.nEscape) break;\r
-               for(long x=xmin; x<xmax; x++){\r
-#if CXIMAGE_SUPPORT_SELECTION\r
-                       if (BlindSelectionIsInside(x,y))\r
-#endif //CXIMAGE_SUPPORT_SELECTION\r
-                       {\r
-                               nx=xmid-x;\r
-                               ny=ymid-y;\r
-                               radius=sqrt((float)(nx*nx+ny*ny));\r
-                               if (radius<rmax) {\r
-                                       angle=atan2((double)ny,(double)nx);\r
-                                       if (type==0)      rnew=radius*radius/rmax;\r
-                                       else if (type==1) rnew=sqrt(radius*rmax);\r
-                                       else if (type==2) {rnew=radius;angle += radius / Koeff;}\r
-                                       else rnew = 1; // potentially uninitialized\r
-                                       if (type<3){\r
-                                               nx = xmid + (long)(rnew * cos(angle));\r
-                                               ny = ymid - (long)(rnew * sin(angle));\r
-                                       }\r
-                                       else if (type==3){\r
-                                               nx = (long)fabs((angle*xmax/6.2831852));\r
-                                               ny = (long)fabs((radius*ymax/rmax));\r
-                                       }\r
-                                       else {\r
-                                               nx=x+(x%32)-16;\r
-                                               ny=y;\r
-                                       }\r
-//                                     nx=max(xmin,min(nx,xmax));\r
-//                                     ny=max(ymin,min(ny,ymax));\r
-                               }\r
-                               else { nx=-1;ny=-1;}\r
-                               if (head.biClrUsed==0){\r
-                                       tmp.SetPixelColor(x,y,GetPixelColor(nx,ny));\r
-                               } else {\r
-                                       tmp.SetPixelIndex(x,y,GetPixelIndex(nx,ny));\r
-                               }\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               tmp.AlphaSet(x,y,AlphaGet(nx,ny));\r
-#endif //CXIMAGE_SUPPORT_ALPHA\r
-                       }\r
-               }\r
-       }\r
-       Transfer(tmp);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Faster way to almost properly shrink image. Algorithm produces results comparable with "high resoultion shrink"\r
- * when resulting image is much smaller (that would be 3 times or more) than original. When\r
- * resulting image is only slightly smaller, results are closer to nearest pixel.\r
- * This algorithm works by averaging, but it does not calculate fractions of pixels. It adds whole\r
- * source pixels to the best destionation. It is not geometrically "correct".\r
- * It's main advantage over "high" resulution shrink is speed, so it's useful, when speed is most\r
- * important (preview thumbnails, "map" view, ...).\r
- * Method is optimized for RGB24 images.\r
- * \r
- * \param  newx, newy - size of destination image (must be smaller than original!)\r
- * \param  iDst - pointer to destination image (if it's 0, this image is modified)\r
- * \param  bChangeBpp - flag points to change result image bpp (if it's true, this result image bpp = 24 (useful for B/W image thumbnails))\r
- *\r
- * \return true if everything is ok\r
- * \author [bd], 9.2004; changes [Artiom Mirolubov], 1.2005\r
- */\r
-bool CxImage::QIShrink(long newx, long newy, CxImage* const iDst, bool bChangeBpp)\r
-{\r
-       if (!pDib) return false;\r
-       \r
-       if (newx>head.biWidth || newy>head.biHeight) { \r
-               //let me repeat... this method can't enlarge image\r
-               strcpy(info.szLastError,"QIShrink can't enlarge image");\r
-               return false;\r
-       }\r
-\r
-       if (newx==head.biWidth && newy==head.biHeight) {\r
-               //image already correct size (just copy and return)\r
-               if (iDst) iDst->Copy(*this);\r
-               return true;\r
-       }//if\r
-       \r
-       //create temporary destination image\r
-       CxImage newImage;\r
-       newImage.CopyInfo(*this);\r
-       newImage.Create(newx,newy,(bChangeBpp)?24:head.biBitCount,GetType());\r
-       newImage.SetPalette(GetPalette());\r
-       if (!newImage.IsValid()){\r
-               strcpy(info.szLastError,newImage.GetLastError());\r
-               return false;\r
-       }\r
-\r
-       //and alpha channel if required\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       if (AlphaIsValid()) newImage.AlphaCreate();\r
-#endif\r
-\r
-    const int oldx = head.biWidth;\r
-    const int oldy = head.biHeight;\r
-\r
-    int accuCellSize = 4;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-       BYTE *alphaPtr;\r
-       if (AlphaIsValid()) accuCellSize=5;\r
-#endif\r
-\r
-    unsigned int *accu = new unsigned int[newx*accuCellSize];      //array for suming pixels... one pixel for every destination column\r
-    unsigned int *accuPtr;                              //pointer for walking through accu\r
-    //each cell consists of blue, red, green component and count of pixels summed in this cell\r
-    memset(accu, 0, newx * accuCellSize * sizeof(unsigned int));  //clear accu\r
-\r
-    if (!IsIndexed()) {\r
-               //RGB24 version with pointers\r
-               BYTE *destPtr, *srcPtr, *destPtrS, *srcPtrS;        //destination and source pixel, and beginnings of current row\r
-               srcPtrS=(BYTE*)BlindGetPixelPointer(0,0);\r
-               destPtrS=(BYTE*)newImage.BlindGetPixelPointer(0,0);\r
-               int ex=0, ey=0;                                               //ex and ey replace division... \r
-               int dy=0;\r
-               //(we just add pixels, until by adding newx or newy we get a number greater than old size... then\r
-               // it's time to move to next pixel)\r
-        \r
-               for(int y=0; y<oldy; y++){                                    //for all source rows\r
-                       info.nProgress = (long)(100*y/oldy); if (info.nEscape) break;\r
-                       ey += newy;                                                   \r
-                       ex = 0;                                                       //restart with ex = 0\r
-                       accuPtr=accu;                                                 //restart from beginning of accu\r
-                       srcPtr=srcPtrS;                                               //and from new source line\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                       alphaPtr = AlphaGetPointer(0, y);\r
-#endif\r
-\r
-                       for(int x=0; x<oldx; x++){                                    //for all source columns\r
-                               ex += newx;\r
-                               *accuPtr     += *(srcPtr++);                                  //add current pixel to current accu slot\r
-                               *(accuPtr+1) += *(srcPtr++);\r
-                               *(accuPtr+2) += *(srcPtr++);\r
-                               (*(accuPtr+3)) ++;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               if (alphaPtr) *(accuPtr+4) += *(alphaPtr++);\r
-#endif\r
-                               if (ex>oldx) {                                                //when we reach oldx, it's time to move to new slot\r
-                                       accuPtr += accuCellSize;\r
-                                       ex -= oldx;                                                   //(substract oldx from ex and resume from there on)\r
-                               }//if (ex overflow)\r
-                       }//for x\r
-\r
-                       if (ey>=oldy) {                                                 //now when this happens\r
-                               ey -= oldy;                                                     //it's time to move to new destination row\r
-                               destPtr = destPtrS;                                             //reset pointers to proper initial values\r
-                               accuPtr = accu;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               alphaPtr = newImage.AlphaGetPointer(0, dy++);\r
-#endif\r
-                               for (int k=0; k<newx; k++) {                                    //copy accu to destination row (divided by number of pixels in each slot)\r
-                                       *(destPtr++) = (BYTE)(*(accuPtr) / *(accuPtr+3));\r
-                                       *(destPtr++) = (BYTE)(*(accuPtr+1) / *(accuPtr+3));\r
-                                       *(destPtr++) = (BYTE)(*(accuPtr+2) / *(accuPtr+3));\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       if (alphaPtr) *(alphaPtr++) = (BYTE)(*(accuPtr+4) / *(accuPtr+3));\r
-#endif\r
-                                       accuPtr += accuCellSize;\r
-                               }//for k\r
-                               memset(accu, 0, newx * accuCellSize * sizeof(unsigned int));                   //clear accu\r
-                               destPtrS += newImage.info.dwEffWidth;\r
-                       }//if (ey overflow)\r
-\r
-                       srcPtrS += info.dwEffWidth;                                     //next round we start from new source row\r
-               }//for y\r
-    } else {\r
-               //standard version with GetPixelColor...\r
-               int ex=0, ey=0;                                               //ex and ey replace division... \r
-               int dy=0;\r
-               //(we just add pixels, until by adding newx or newy we get a number greater than old size... then\r
-               // it's time to move to next pixel)\r
-               RGBQUAD rgb;\r
-        \r
-               for(int y=0; y<oldy; y++){                                    //for all source rows\r
-                       info.nProgress = (long)(100*y/oldy); if (info.nEscape) break;\r
-                       ey += newy;                                                   \r
-                       ex = 0;                                                       //restart with ex = 0\r
-                       accuPtr=accu;                                                 //restart from beginning of accu\r
-                       for(int x=0; x<oldx; x++){                                    //for all source columns\r
-                               ex += newx;\r
-                               rgb = GetPixelColor(x, y, true);\r
-                               *accuPtr     += rgb.rgbBlue;                                  //add current pixel to current accu slot\r
-                               *(accuPtr+1) += rgb.rgbRed;\r
-                               *(accuPtr+2) += rgb.rgbGreen;\r
-                               (*(accuPtr+3)) ++;\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                               if (pAlpha) *(accuPtr+4) += rgb.rgbReserved;\r
-#endif\r
-                               if (ex>oldx) {                                                //when we reach oldx, it's time to move to new slot\r
-                                       accuPtr += accuCellSize;\r
-                                       ex -= oldx;                                                   //(substract oldx from ex and resume from there on)\r
-                               }//if (ex overflow)\r
-                       }//for x\r
-\r
-                       if (ey>=oldy) {                                                 //now when this happens\r
-                               ey -= oldy;                                                     //it's time to move to new destination row\r
-                               accuPtr = accu;\r
-                               for (int dx=0; dx<newx; dx++) {                                 //copy accu to destination row (divided by number of pixels in each slot)\r
-                                       rgb.rgbBlue = (BYTE)(*(accuPtr) / *(accuPtr+3));\r
-                                       rgb.rgbRed  = (BYTE)(*(accuPtr+1) / *(accuPtr+3));\r
-                                       rgb.rgbGreen= (BYTE)(*(accuPtr+2) / *(accuPtr+3));\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-                                       if (pAlpha) rgb.rgbReserved = (BYTE)(*(accuPtr+4) / *(accuPtr+3));\r
-#endif\r
-                                       newImage.SetPixelColor(dx, dy, rgb, pAlpha!=0);\r
-                                       accuPtr += accuCellSize;\r
-                               }//for dx\r
-                               memset(accu, 0, newx * accuCellSize * sizeof(unsigned int));                   //clear accu\r
-                               dy++;\r
-                       }//if (ey overflow)\r
-               }//for y\r
-    }//if\r
-\r
-    delete [] accu;                                                 //delete helper array\r
-       \r
-       //copy new image to the destination\r
-       if (iDst) \r
-               iDst->Transfer(newImage);\r
-       else \r
-               Transfer(newImage);\r
-    return true;\r
-\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_TRANSFORMATION\r
+// xImaTran.cpp : Transformation functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#include "ximage.h"
+#include "ximath.h"
+
+#if CXIMAGE_SUPPORT_BASICTRANSFORMATIONS
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::GrayScale()
+{
+       if (!pDib) return false;
+       if (head.biBitCount<=8){
+               RGBQUAD* ppal=GetPalette();
+               int gray;
+               //converts the colors to gray, use the blue channel only
+               for(DWORD i=0;i<head.biClrUsed;i++){
+                       gray=(int)RGB2GRAY(ppal[i].rgbRed,ppal[i].rgbGreen,ppal[i].rgbBlue);
+                       ppal[i].rgbBlue = (BYTE)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){
+                       BYTE *img=info.pImage;
+                       for(DWORD 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 (long y=0;y<head.biHeight;y++){
+                               BYTE *iDst = ima.GetBits(y);
+                               BYTE *iSrc = GetBits(y);
+                               for (long x=0;x<head.biWidth; x++){
+                                       //iDst[x]=ppal[BlindGetPixelIndex(x,y)].rgbBlue;
+                                       if (head.biBitCount==4){
+                                               BYTE pos = (BYTE)(4*(1-x%2));
+                                               iDst[x]= ppal[(BYTE)((iSrc[x >> 1]&((BYTE)0x0F<<pos)) >> pos)].rgbBlue;
+                                       } else {
+                                               BYTE pos = (BYTE)(7-x%8);
+                                               iDst[x]= ppal[(BYTE)((iSrc[x >> 3]&((BYTE)0x01<<pos)) >> pos)].rgbBlue;
+                                       }
+                               }
+                       }
+                       Transfer(ima);
+               }
+       } else { //from RGB to 8 bit gray scale
+               BYTE *iSrc=info.pImage;
+               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
+               BYTE *img=ima.GetBits();
+               long l8=ima.GetEffWidth();
+               long l=head.biWidth * 3;
+               for(long y=0; y < head.biHeight; y++) {
+                       for(long x=0,x8=0; x < l; x+=3,x8++) {
+                               img[x8+y*l8]=(BYTE)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;
+
+       BYTE *buff = (BYTE*)malloc(info.dwEffWidth);
+       if (!buff) return false;
+
+       BYTE *iSrc,*iDst;
+       iSrc = GetBits(head.biHeight-1);
+       iDst = GetBits(0);
+       for (long 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;
+       }
+
+       BYTE *iSrc,*iDst;
+       long wdt=(head.biWidth-1) * (head.biBitCount==24 ? 3:1);
+       iSrc=info.pImage + wdt;
+       iDst=imatmp->info.pImage;
+       long 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;
+
+       long newWidth = GetHeight();
+       long 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
+
+       long x,x2,y,dlineup;
+       
+       // Speedy rotate for BW images <Robert Abram>
+       if (head.biBitCount == 1) {
+       
+               BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp;
+               ldiv_t div_r;
+
+               BYTE *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, (long)8);
+                       // set bit pos of src column byte                               
+                       bitpos = (BYTE)(1 << div_r.rem);
+                       srcdisp = bsrc + y * info.dwEffWidth;
+                       for (x = 0; x < (long)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 (long 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.
+               
+               BYTE *srcPtr, *dstPtr;                        //source and destionation for 24-bit version
+               int 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 = (long)(100*x/newWidth);
+                                               x2=newWidth-x-1;
+                                               dstPtr = (BYTE*) imgDest.BlindGetPixelPointer(x,ys);
+                                               srcPtr = (BYTE*) 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 = (long)(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;
+
+       long newWidth = GetHeight();
+       long 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
+
+       long x,y,y2;
+       // Speedy rotate for BW images <Robert Abram>
+       if (head.biBitCount == 1) {
+       
+               BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow,*srcdisp;
+               ldiv_t div_r;
+
+               BYTE *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, (long)8);
+                       // set bit pos of src column byte                               
+                       bitpos = (BYTE)(128 >> div_r.rem);
+                       srcdisp = bsrc + y * info.dwEffWidth;
+                       for (x = 0; x < (long)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 (long 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
+               BYTE *srcPtr, *dstPtr;                        //source and destionation for 24-bit version
+               int 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 = (long)(100*y/newHeight); //<Anatoly Ivasyuk>
+                                               y2=newHeight-y-1;
+                                               dstPtr = (BYTE*) imgDest.BlindGetPixelPointer(xs,y);
+                                               srcPtr = (BYTE*) 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 = (long)(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(long y=info.rSelectionBox.bottom; y<info.rSelectionBox.top; y++){
+                                       for(long x=info.rSelectionBox.left; x<info.rSelectionBox.right; x++){
+#if CXIMAGE_SUPPORT_SELECTION
+                                               if (BlindSelectionIsInside(x,y))
+#endif //CXIMAGE_SUPPORT_SELECTION
+                                               {
+                                                       BlindSetPixelIndex(x,y,(BYTE)(255-BlindGetPixelIndex(x,y)));
+                                               }
+                                       }
+                               }
+                       } else {
+                               BYTE *iSrc=info.pImage;
+                               for(unsigned long i=0; i < head.biSizeImage; i++){
+                                       *iSrc=(BYTE)~(*(iSrc));
+                                       iSrc++;
+                               }
+                       }
+               } else { //PALETTE, full image
+                       RGBQUAD* ppal=GetPalette();
+                       for(DWORD i=0;i<head.biClrUsed;i++){
+                               ppal[i].rgbBlue =(BYTE)(255-ppal[i].rgbBlue);
+                               ppal[i].rgbGreen =(BYTE)(255-ppal[i].rgbGreen);
+                               ppal[i].rgbRed =(BYTE)(255-ppal[i].rgbRed);
+                       }
+               }
+       } else {
+               if (pSelection==NULL){ //RGB, full image
+                       BYTE *iSrc=info.pImage;
+                       for(unsigned long i=0; i < head.biSizeImage; i++){
+                               *iSrc=(BYTE)~(*(iSrc));
+                               iSrc++;
+                       }
+               } else { // RGB with selection
+                       RGBQUAD color;
+                       for(long y=info.rSelectionBox.bottom; y<info.rSelectionBox.top; y++){
+                               for(long 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 = (BYTE)(255-color.rgbRed);
+                                               color.rgbGreen = (BYTE)(255-color.rgbGreen);
+                                               color.rgbBlue = (BYTE)(255-color.rgbBlue);
+                                               BlindSetPixelColor(x,y,color);
+                                       }
+                               }
+                       }
+               }
+               //<DP> invert transparent color too
+               info.nBkgndColor.rgbBlue = (BYTE)(255-info.nBkgndColor.rgbBlue);
+               info.nBkgndColor.rgbGreen = (BYTE)(255-info.nBkgndColor.rgbGreen);
+               info.nBkgndColor.rgbRed = (BYTE)(255-info.nBkgndColor.rgbRed);
+       }
+       return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_BASICTRANSFORMATIONS
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_TRANSFORMATION
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+bool CxImage::Rotate(float angle, CxImage* iDst)
+{
+       if (!pDib) return false;
+
+       //  Copyright (c) 1996-1998 Ulrich von Zadow
+
+       // Negative the angle, because the y-axis is negative.
+       double ang = -angle*acos((float)0)/90;
+       int newWidth, newHeight;
+       int nWidth = GetWidth();
+       int 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 = (int) floor(0.5f + rightTop.x - leftTop.x);
+       newHeight= (int) 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
+
+       int x,y,newX,newY,oldX,oldY;
+
+       if (head.biClrUsed==0){ //RGB
+               for (y = (int)leftTop.y, newY = 0; y<=(int)leftBottom.y; y++,newY++){
+                       info.nProgress = (long)(100*newY/newHeight);
+                       if (info.nEscape) break;
+                       for (x = (int)leftTop.x, newX = 0; x<=(int)rightTop.x; x++,newX++){
+                               oldX = (long)(x*cos_angle + y*sin_angle + 0.5);
+                               oldY = (long)(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 = (int)leftTop.y, newY = 0; y<=(int)leftBottom.y; y++,newY++){
+                       info.nProgress = (long)(100*newY/newHeight);
+                       if (info.nEscape) break;
+                       for (x = (int)leftTop.x, newX = 0; x<=(int)rightTop.x; x++,newX++){
+                               oldX = (long)(x*cos_angle + y*sin_angle + 0.5);
+                               oldY = (long)(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
+       
+       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 (int i=0; i<4; i++) {
+                       newp[i].x = p[i].x;
+                       newp[i].y = p[i].y;
+               }//for
+       } else {
+               for (int 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));
+       int newWidth = (int) floor(maxx-minx+0.5f);
+       int newHeight= (int) 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
+       int destx, desty;       //destination location
+       
+       y=ssy;                  //initialize y
+       if (!IsIndexed()){ //RGB24
+               //optimized RGB24 implementation (direct write to destination):
+               BYTE *pxptr;
+#if CXIMAGE_SUPPORT_ALPHA
+               BYTE *pxptra=0;
+#endif //CXIMAGE_SUPPORT_ALPHA
+               for (desty=0; desty<newHeight; desty++) {
+                       info.nProgress = (long)(100*desty/newHeight);
+                       if (info.nEscape) break;
+                       //initialize x
+                       x=ssx;
+                       //calculate pointer to first byte in row
+                       pxptr=(BYTE *)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 = (long)(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;
+
+       long wid = GetWidth();
+       long 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
+
+       long x,y,y2;
+       for (y = 0; y < ht; y++){
+               info.nProgress = (long)(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(long newx, long newy, int 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(long y=0; y<newy; y++){
+                       info.nProgress = (long)(100*y/newy);
+                       if (info.nEscape) break;
+                       fY = y * yScale;
+                       for(long x=0; x<newx; x++){
+                               fX = x * xScale;
+                               newImage.SetPixelColor(x,y,GetPixelColor((long)fX,(long)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;
+               int   i_x, i_y, xx, yy;
+               RGBQUAD rgb;
+               BYTE* iDst;
+               for(long y=0; y<newy; y++){
+                       info.nProgress = (long)(100*y/newy);
+                       if (info.nEscape) break;
+                       f_y = (float) y * yScale - 0.5f;
+                       i_y = (int) floor(f_y);
+                       a   = f_y - (float)floor(f_y);
+                       for(long x=0; x<newx; x++){
+                               f_x = (float) x * xScale - 0.5f;
+                               i_x = (int) floor(f_x);
+                               b   = f_x - (float)floor(f_x);
+
+                               rr = gg = bb = 0.0f;
+                               for(int 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(int 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++ = (BYTE)bb;
+                                       *iDst++ = (BYTE)gg;
+                                       *iDst   = (BYTE)rr;
+                               }
+
+                       }
+               }
+               break;
+       }
+       default: // bilinear interpolation
+               if (!(head.biWidth>newx && head.biHeight>newy && head.biBitCount==24)) {
+                       // (c) 1999 Steve McMahon (steve@dogma.demon.co.uk)
+                       long ifX, ifY, ifX1, ifY1, xmax, ymax;
+                       float ir1, ir2, ig1, ig2, ib1, ib2, dx, dy;
+                       BYTE r,g,b;
+                       RGBQUAD rgb1, rgb2, rgb3, rgb4;
+                       xmax = head.biWidth-1;
+                       ymax = head.biHeight-1;
+                       for(long y=0; y<newy; y++){
+                               info.nProgress = (long)(100*y/newy);
+                               if (info.nEscape) break;
+                               fY = y * yScale;
+                               ifY = (int)fY;
+                               ifY1 = min(ymax, ifY+1);
+                               dy = fY - ifY;
+                               for(long x=0; x<newx; x++){
+                                       fX = x * xScale;
+                                       ifX = (int)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 {
+                                               BYTE* 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 = (BYTE)(ir1 + (ir2-ir1) * dx);
+                                       g = (BYTE)(ig1 + (ig2-ig1) * dx);
+                                       b = (BYTE)(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 long ACCURACY = 1000;
+                       long i,j; // index for faValue
+                       long x,y; // coordinates in  source image
+                       BYTE* pSource;
+                       BYTE* pDest = newImage.info.pImage;
+                       long* naAccu  = new long[3 * newx + 3];
+                       long* naCarry = new long[3 * newx + 3];
+                       long* naTemp;
+                       long  nWeightX,nWeightY;
+                       float fEndX;
+                       long nScale = (long)(ACCURACY * xScale * yScale);
+
+                       memset(naAccu,  0, sizeof(long) * 3 * newx);
+                       memset(naCarry, 0, sizeof(long) * 3 * newx);
+
+                       int u, v = 0; // coordinates in dest image
+                       float fEndY = yScale - 1.0f;
+                       for (y = 0; y < head.biHeight; y++){
+                               info.nProgress = (long)(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 = (long)(((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 = (long)(((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 = (int)(((float)x - fEndX) * ACCURACY);
+                                                       for (j = 0; j < 3; j++) {
+                                                               naAccu[i] += ((ACCURACY - nWeightY) * (ACCURACY - nWeightX)) * (*pSource) / ACCURACY;
+                                                               *pDest++ = (BYTE)(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++ = (BYTE)(naAccu[i++] / nScale);
+                                       }
+                                       naTemp = naCarry;
+                                       naCarry = naAccu;
+                                       naAccu = naTemp;
+                                       memset(naCarry, 0, sizeof(int) * 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++ = (BYTE)(naAccu[i] / nScale);
+                       }
+                       delete [] naAccu;
+                       delete [] naCarry;
+               }
+       }
+
+#if CXIMAGE_SUPPORT_ALPHA
+       if (AlphaIsValid()){
+               newImage.AlphaCreate();
+               for(long y=0; y<newy; y++){
+                       fY = y * yScale;
+                       for(long x=0; x<newx; x++){
+                               fX = x * xScale;
+                               newImage.AlphaSet(x,y,AlphaGet((long)fX,(long)fY));
+                       }
+               }
+       }
+#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(
+  long newx, long 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();
+       BYTE *pxptra = 0;       // destination alpha data
+#endif
+       
+       float sX, sY;         //source location
+       long dX,dY;           //destination pixel (int 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
+                       BYTE *pxptr;            //pointer to destination pixel
+                       for(dY=0; dY<newy; dY++){
+                               info.nProgress = (long)(100*dY/newy);
+                               if (info.nEscape) break;
+                               sY = (dY + 0.5f) * yScale - 0.5f;
+                               pxptr=(BYTE*)(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 = (long)(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 = (long)(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(long y=0; y<newy; y++){
+                       dY = (long)(y * yScale);
+                       for(long x=0; x<newx; x++){
+                               dX = (long)(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(DWORD nbit, bool errordiffusion, RGBQUAD* ppal, DWORD 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;
+       }
+
+       long er,eg,eb;
+       RGBQUAD c,ce;
+
+       CxImage tmp;
+       tmp.CopyInfo(*this);
+       tmp.Create(head.biWidth,head.biHeight,(WORD)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 (long y=0;y<head.biHeight;y++){
+               if (info.nEscape) break;
+               info.nProgress = (long)(100*y/head.biHeight);
+               for (long 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=(long)c.rgbRed - (long)ce.rgbRed;
+                               eg=(long)c.rgbGreen - (long)ce.rgbGreen;
+                               eb=(long)c.rgbBlue - (long)ce.rgbBlue;
+
+                               c = GetPixelColor(x+1,y);
+                               c.rgbRed = (BYTE)min(255L,max(0L,(long)c.rgbRed + ((er*7)/16)));
+                               c.rgbGreen = (BYTE)min(255L,max(0L,(long)c.rgbGreen + ((eg*7)/16)));
+                               c.rgbBlue = (BYTE)min(255L,max(0L,(long)c.rgbBlue + ((eb*7)/16)));
+                               SetPixelColor(x+1,y,c);
+                               int coeff=1;
+                               for(int 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 = (BYTE)min(255L,max(0L,(long)c.rgbRed + ((er * coeff)/16)));
+                                       c.rgbGreen = (BYTE)min(255L,max(0L,(long)c.rgbGreen + ((eg * coeff)/16)));
+                                       c.rgbBlue = (BYTE)min(255L,max(0L,(long)c.rgbBlue + ((eb * coeff)/16)));
+                                       SetPixelColor(x+i,y+1,c);
+                               }
+                       }
+               }
+       }
+
+       Transfer(tmp);
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Increases the number of bits per pixel of the image.
+ * \param nbit: 4, 8, 24
+ */
+bool CxImage::IncreaseBpp(DWORD 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 (long y=0;y<head.biHeight;y++){
+                               if (info.nEscape) break;
+                               for (long 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 (long y=0;y<head.biHeight;y++){
+                               if (info.nEscape) break;
+                               for (long 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((BYTE)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 (long y=0;y<head.biHeight;y++){
+                               if (info.nEscape) break;
+                               for (long x=0;x<head.biWidth;x++){
+                                       tmp.BlindSetPixelColor(x,y,BlindGetPixelColor(x,y),true);
+                               }
+                       }
+                       Transfer(tmp);
+                       return true;
+               }
+       }
+       return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * 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) 
+ */
+bool CxImage::Dither(long 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))
+
+               int DitherMatrix[dth_NumRows][dth_NumCols] = {{0,8,2,10}, {12,4,14,6}, {3,11,1,9}, {15,7,13,5} };
+               
+               unsigned char Intensity[dth_NumIntensityLevels] = { 0,1 };                       // 2 LEVELS B/W
+               //unsigned char Intensity[NumIntensityLevels] = { 0,255 };                       // 2 LEVELS
+               //unsigned char Intensity[NumIntensityLevels] = { 0,127,255 };                   // 3 LEVELS
+               //unsigned char Intensity[NumIntensityLevels] = { 0,85,170,255 };                // 4 LEVELS
+               //unsigned char Intensity[NumIntensityLevels] = { 0,63,127,191,255 };            // 5 LEVELS
+               //unsigned char Intensity[NumIntensityLevels] = { 0,51,102,153,204,255 };        // 6 LEVELS
+               //unsigned char Intensity[NumIntensityLevels] = { 0,42,85,127,170,213,255 };     // 7 LEVELS
+               //unsigned char Intensity[NumIntensityLevels] = { 0,36,73,109,145,182,219,255 }; // 8 LEVELS
+               int DitherIntensity, DitherMatrixIntensity, Offset, DeviceIntensity;
+               unsigned char DitherValue;
+  
+               for (long y=0;y<head.biHeight;y++){
+                       info.nProgress = (long)(100*y/head.biHeight);
+                       if (info.nEscape) break;
+                       for (long 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)
+               int TotalCoeffSum = 32;
+               long error, nlevel, coeff=1;
+               BYTE level;
+
+               for (long y = 0; y < head.biHeight; y++) {
+                       info.nProgress = (long)(100 * y / head.biHeight);
+                       if (info.nEscape) 
+                               break;
+                       for (long 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 = (BYTE)min(255, max(0, (int)nlevel));
+                               SetPixelIndex(x + 1, y, level);
+                               nlevel = GetPixelIndex(x + 2, y) + (error * 4) / TotalCoeffSum;
+                               level = (BYTE)min(255, max(0, (int)nlevel));
+                               SetPixelIndex(x + 2, y, level);
+                               int 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 = (BYTE)min(255, max(0, (int)nlevel));
+                                       SetPixelIndex(x + i, y + 1, level);
+                               }
+                       }
+               }
+               break;
+       }
+       case 3:
+       {
+               //Stucki error diffusion (Thanks to Franco Gerevini)
+               int TotalCoeffSum = 42;
+               long error, nlevel, coeff=1;
+               BYTE level;
+
+               for (long y = 0; y < head.biHeight; y++) {
+                       info.nProgress = (long)(100 * y / head.biHeight);
+                       if (info.nEscape) 
+                               break;
+                       for (long 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 = (BYTE)min(255, max(0, (int)nlevel));
+                               SetPixelIndex(x + 1, y, level);
+                               nlevel = GetPixelIndex(x + 2, y) + (error * 4) / TotalCoeffSum;
+                               level = (BYTE)min(255, max(0, (int)nlevel));
+                               SetPixelIndex(x + 2, y, level);
+                               int 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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)nlevel));
+                                       SetPixelIndex(x + i, y + 2, level);
+                               }
+                       }
+               }
+               break;
+       }
+       case 4:
+       {
+               //Jarvis, Judice and Ninke error diffusion (Thanks to Franco Gerevini)
+               int TotalCoeffSum = 48;
+               long error, nlevel, coeff=1;
+               BYTE level;
+
+               for (long y = 0; y < head.biHeight; y++) {
+                       info.nProgress = (long)(100 * y / head.biHeight);
+                       if (info.nEscape) 
+                               break;
+                       for (long 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 = (BYTE)min(255, max(0, (int)nlevel));
+                               SetPixelIndex(x + 1, y, level);
+                               nlevel = GetPixelIndex(x + 2, y) + (error * 5) / TotalCoeffSum;
+                               level = (BYTE)min(255, max(0, (int)nlevel));
+                               SetPixelIndex(x + 2, y, level);
+                               int 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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)nlevel));
+                                       SetPixelIndex(x + i, y + 2, level);
+                               }
+                       }
+               }
+               break;
+       }
+       case 5:
+       {
+               //Sierra error diffusion (Thanks to Franco Gerevini)
+               int TotalCoeffSum = 32;
+               long error, nlevel, coeff=1;
+               BYTE level;
+
+               for (long y = 0; y < head.biHeight; y++) {
+                       info.nProgress = (long)(100 * y / head.biHeight);
+                       if (info.nEscape) 
+                               break;
+                       for (long 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 = (BYTE)min(255, max(0, (int)nlevel));
+                               SetPixelIndex(x + 1, y, level);
+                               nlevel = GetPixelIndex(x + 2, y) + (error * 3) / TotalCoeffSum;
+                               level = (BYTE)min(255, max(0, (int)nlevel));
+                               SetPixelIndex(x + 2, y, level);
+                               int 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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)nlevel));
+                                       SetPixelIndex(x + i, y + 2, level);
+                               }
+                       }
+               }
+               break;
+       }
+       case 6:
+       {
+               //Stevenson and Arce error diffusion (Thanks to Franco Gerevini)
+               int TotalCoeffSum = 200;
+               long error, nlevel;
+               BYTE level;
+
+               for (long y = 0; y < head.biHeight; y++) {
+                       info.nProgress = (long)(100 * y / head.biHeight);
+                       if (info.nEscape) 
+                               break;
+                       for (long 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;
+                               }
+
+                               int tmp_index_x = x + 2;
+                               int tmp_index_y = y;
+                               int tmp_coeff = 32;
+                               nlevel = GetPixelIndex(tmp_index_x, tmp_index_y) + (error * tmp_coeff) / TotalCoeffSum;
+                               level = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)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 = (BYTE)min(255, max(0, (int)nlevel));
+                               SetPixelIndex(tmp_index_x, tmp_index_y, level);
+                       }
+               }
+               break;
+       }
+       case 7:
+       {
+               // Bayer ordered dither
+               int order = 4;
+               //create Bayer matrix
+               if (order>4) order = 4;
+               int size = (1 << (2*order));
+               BYTE* Bmatrix = (BYTE*) malloc(size * sizeof(BYTE));
+               for(int i = 0; i < size; i++) {
+                       int n = order;
+                       int x = i / n;
+                       int y = i % n;
+                       int dither = 0;
+                       while (n-- > 0){
+                               dither = (((dither<<1)|((x&1) ^ (y&1)))<<1) | (y&1);
+                               x >>= 1;
+                               y >>= 1;
+                       }
+                       Bmatrix[i] = (BYTE)(dither);
+               }
+
+               int scale = max(0,(8-2*order));
+               int level;
+               for (long y=0;y<head.biHeight;y++){
+                       info.nProgress = (long)(100*y/head.biHeight);
+                       if (info.nEscape) break;
+                       for (long 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;
+       }
+       default:
+       {
+               // Floyd-Steinberg error diffusion (Thanks to Steve McMahon)
+               long error,nlevel,coeff=1;
+               BYTE level;
+
+               for (long y=0;y<head.biHeight;y++){
+                       info.nProgress = (long)(100*y/head.biHeight);
+                       if (info.nEscape) break;
+                       for (long 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 = (BYTE)min(255,max(0,(int)nlevel));
+                               SetPixelIndex(x+1,y,level);
+                               for(int 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 = (BYTE)min(255,max(0,(int)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( long topx, long topy, long width, long height, float angle, CxImage* iDst)
+{
+       if (!pDib) return false;
+
+       
+       long 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 - (long)(sin_angle*(double)height));
+       endx   = topx + (long)(cos_angle*(double)width);
+       endy   = topy + (long)(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(long left, long top, long right, long bottom, CxImage* iDst)
+{
+       if (!pDib) return false;
+
+       long startx = max(0L,min(left,head.biWidth));
+       long endx = max(0L,min(right,head.biWidth));
+       long starty = head.biHeight - max(0L,min(top,head.biHeight));
+       long endy = head.biHeight - max(0L,min(bottom,head.biHeight));
+
+       if (startx==endx || starty==endy) return false;
+
+       if (startx>endx) {long tmp=startx; startx=endx; endx=tmp;}
+       if (starty>endy) {long tmp=starty; starty=endy; endy=tmp;}
+
+       CxImage tmp(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(long y=starty, yd=0; y<endy; y++, yd++){
+                       info.nProgress = (long)(100*(y-starty)/(endy-starty)); //<Anatoly Ivasyuk>
+                       for(long x=startx, xd=0; x<endx; x++, xd++){
+                               tmp.SetPixelIndex(xd,yd,GetPixelIndex(x,y));
+                       }
+               }
+               break;
+       }
+       case 8:
+       case 24:
+       {
+               int linelen = tmp.head.biWidth * tmp.head.biBitCount >> 3;
+               BYTE* pDest = tmp.info.pImage;
+               BYTE* pSrc = info.pImage + starty * info.dwEffWidth + (startx*head.biBitCount >> 3);
+               for(long y=starty; y<endy; y++){
+                       info.nProgress = (long)(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;
+               BYTE* pDest = tmp.pAlpha;
+               BYTE* pSrc = pAlpha + startx + starty*head.biWidth;
+               for (long 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, long xpivot, long ypivot, bool bEnableInterpolation)
+{
+       if (!pDib) return false;
+       float nx,ny;
+
+       CxImage tmp(*this);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       long 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(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long 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((long)nx,(long)ny));
+                                       } else {
+                                               tmp.SetPixelIndex(x,y,GetPixelIndex((long)nx,(long)ny));
+                                       }
+#if CXIMAGE_SUPPORT_ALPHA
+                                       tmp.AlphaSet(x,y,AlphaGet((long)nx,(long)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(long left, long top, long right, long bottom, RGBQUAD canvascolor, CxImage* iDst)
+{
+    if (!pDib) return false;
+
+    if ((left < 0) || (right < 0) || (bottom < 0) || (top < 0)) return false;
+
+    long newWidth = head.biWidth + left + right;
+    long 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:
+               {
+                       BYTE pixel = tmp.GetNearestIndex(canvascolor);
+                       for(long y=0; y < newHeight; y++){
+                               info.nProgress = (long)(100*y/newHeight);
+                               for(long 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) {
+                               BYTE pixel = tmp.GetNearestIndex( canvascolor);
+                               memset(tmp.info.pImage, pixel,  + (tmp.info.dwEffWidth * newHeight));
+                       } else {
+                               for (long y = 0; y < newHeight; ++y) {
+                                       BYTE *pDest = tmp.info.pImage + (y * tmp.info.dwEffWidth);
+                                       for (long x = 0; x < newWidth; ++x) {
+                                               *pDest++ = canvascolor.rgbBlue;
+                                               *pDest++ = canvascolor.rgbGreen;
+                                               *pDest++ = canvascolor.rgbRed;
+                                       }
+                               }
+                       }
+
+                       BYTE* pDest = tmp.info.pImage + (tmp.info.dwEffWidth * bottom) + (left*(head.biBitCount >> 3));
+                       BYTE* pSrc = info.pImage;
+                       for(long y=bottom; y <= top; y++){
+                               info.nProgress = (long)(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;
+               BYTE* pSrc = SelectionGetPointer();
+               BYTE* pDst = tmp.SelectionGetPointer(left,bottom);
+               for(long 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);
+               BYTE* pSrc = AlphaGetPointer();
+               BYTE* pDst = tmp.AlphaGetPointer(left,bottom);
+               for(long 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(long newx, long newy, RGBQUAD canvascolor, CxImage* iDst)
+{
+       //thanks to <Colin Urquhart>
+
+    if (!pDib) return false;
+
+    if ((newx < head.biWidth) || (newy < head.biHeight)) return false;
+
+    int nAddLeft = (newx - head.biWidth) / 2;
+    int 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(long newx, long 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((long) (fScale * head.biWidth), (long) (fScale * head.biHeight), 0);
+    }
+
+    // expand the frame
+    tmp.Expand(newx, newy, canvascolor, iDst);
+
+    //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(int type,long rmax,float Koeff)
+{
+       if (!pDib) return false;
+
+       long nx,ny;
+       double angle,radius,rnew;
+
+       CxImage tmp(*this);
+       if (!tmp.IsValid()){
+               strcpy(info.szLastError,tmp.GetLastError());
+               return false;
+       }
+
+       long 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 = (long) (tmp.GetWidth()/2);
+       ymid = (long) (tmp.GetHeight()/2);
+
+       if (!rmax) rmax=(long)sqrt((float)((xmid-xmin)*(xmid-xmin)+(ymid-ymin)*(ymid-ymin)));
+       if (Koeff==0.0f) Koeff=1.0f;
+
+       for(long y=ymin; y<ymax; y++){
+               info.nProgress = (long)(100*(y-ymin)/(ymax-ymin));
+               if (info.nEscape) break;
+               for(long 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 + (long)(rnew * cos(angle));
+                                               ny = ymid - (long)(rnew * sin(angle));
+                                       }
+                                       else if (type==3){
+                                               nx = (long)fabs((angle*xmax/6.2831852));
+                                               ny = (long)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(long newx, long 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 int oldx = head.biWidth;
+    const int oldy = head.biHeight;
+
+    int accuCellSize = 4;
+#if CXIMAGE_SUPPORT_ALPHA
+       BYTE *alphaPtr;
+       if (AlphaIsValid()) accuCellSize=5;
+#endif
+
+    unsigned int *accu = new unsigned int[newx*accuCellSize];      //array for suming pixels... one pixel for every destination column
+    unsigned int *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(unsigned int));  //clear accu
+
+    if (!IsIndexed()) {
+               //RGB24 version with pointers
+               BYTE *destPtr, *srcPtr, *destPtrS, *srcPtrS;        //destination and source pixel, and beginnings of current row
+               srcPtrS=(BYTE*)BlindGetPixelPointer(0,0);
+               destPtrS=(BYTE*)newImage.BlindGetPixelPointer(0,0);
+               int ex=0, ey=0;                                               //ex and ey replace division... 
+               int 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(int y=0; y<oldy; y++){                                    //for all source rows
+                       info.nProgress = (long)(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(int 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 (int k=0; k<newx; k++) {                                    //copy accu to destination row (divided by number of pixels in each slot)
+                                       *(destPtr++) = (BYTE)(*(accuPtr) / *(accuPtr+3));
+                                       *(destPtr++) = (BYTE)(*(accuPtr+1) / *(accuPtr+3));
+                                       *(destPtr++) = (BYTE)(*(accuPtr+2) / *(accuPtr+3));
+#if CXIMAGE_SUPPORT_ALPHA
+                                       if (alphaPtr) *(alphaPtr++) = (BYTE)(*(accuPtr+4) / *(accuPtr+3));
+#endif
+                                       accuPtr += accuCellSize;
+                               }//for k
+                               memset(accu, 0, newx * accuCellSize * sizeof(unsigned int));                   //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...
+               int ex=0, ey=0;                                               //ex and ey replace division... 
+               int 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(int y=0; y<oldy; y++){                                    //for all source rows
+                       info.nProgress = (long)(100*y/oldy); if (info.nEscape) break;
+                       ey += newy;                                                   
+                       ex = 0;                                                       //restart with ex = 0
+                       accuPtr=accu;                                                 //restart from beginning of accu
+                       for(int 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 (int dx=0; dx<newx; dx++) {                                 //copy accu to destination row (divided by number of pixels in each slot)
+                                       rgb.rgbBlue = (BYTE)(*(accuPtr) / *(accuPtr+3));
+                                       rgb.rgbRed  = (BYTE)(*(accuPtr+1) / *(accuPtr+3));
+                                       rgb.rgbGreen= (BYTE)(*(accuPtr+2) / *(accuPtr+3));
+#if CXIMAGE_SUPPORT_ALPHA
+                                       if (pAlpha) rgb.rgbReserved = (BYTE)(*(accuPtr+4) / *(accuPtr+3));
+#endif
+                                       newImage.SetPixelColor(dx, dy, rgb, pAlpha!=0);
+                                       accuPtr += accuCellSize;
+                               }//for dx
+                               memset(accu, 0, newx * accuCellSize * sizeof(unsigned int));                   //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
index bbf668335d22fbe2c759ad51ae160e98fda49f82..6b9151eb6c8bc2ddcb53a340275bec8be61be1f0 100644 (file)
-/*\r
- * File:       ximawbmp.cpp\r
- * Purpose:    Platform Independent WBMP Image Class Loader and Writer\r
- * 12/Jul/2002 Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximawbmp.h"\r
-\r
-#if CXIMAGE_SUPPORT_WBMP\r
-\r
-#include "ximaiter.h"\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageWBMP::Decode(CxFile *hFile)\r
-{\r
-       if (hFile == NULL) return false;\r
-\r
-       WBMPHEADER wbmpHead;\r
-\r
-  cx_try\r
-  {\r
-       ReadOctet(hFile, &wbmpHead.Type);\r
-\r
-       DWORD dat;\r
-       ReadOctet(hFile, &dat);\r
-       wbmpHead.FixHeader = (BYTE)dat;\r
-\r
-       ReadOctet(hFile, &wbmpHead.ImageWidth);\r
-       ReadOctet(hFile, &wbmpHead.ImageHeight);\r
-\r
-       if (hFile->Eof())\r
-               cx_throw("Not a WBMP");\r
-\r
-       if (wbmpHead.Type != 0)\r
-               cx_throw("Unsupported WBMP type");                      \r
-\r
-       head.biWidth = wbmpHead.ImageWidth;\r
-       head.biHeight= wbmpHead.ImageHeight;\r
-\r
-       if (head.biWidth<=0 || head.biHeight<=0)\r
-               cx_throw("Corrupted WBMP");\r
-\r
-       if (info.nEscape == -1){\r
-               info.dwType = CXIMAGE_FORMAT_WBMP;\r
-               return true;\r
-       }\r
-\r
-       Create(head.biWidth, head.biHeight, 1, CXIMAGE_FORMAT_WBMP);\r
-       if (!IsValid()) cx_throw("WBMP Create failed");\r
-       SetGrayPalette();\r
-\r
-       int linewidth=(head.biWidth+7)/8;\r
-    CImageIterator iter(this);\r
-       iter.Upset();\r
-    for (long y=0; y < head.biHeight; y++){\r
-               hFile->Read(iter.GetRow(),linewidth,1);\r
-               iter.PrevRow();\r
-    }\r
-\r
-  } cx_catch {\r
-       if (strcmp(message,"")) strncpy(info.szLastError,message,255);\r
-       return FALSE;\r
-  }\r
-    return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageWBMP::ReadOctet(CxFile * hFile, DWORD *data)\r
-{\r
-       BYTE c;\r
-       *data = 0;\r
-       do {\r
-               if (hFile->Eof()) return false;\r
-               c = (BYTE)hFile->GetC();\r
-               *data <<= 7;\r
-               *data |= (c & 0x7F);\r
-       } while ((c&0x80)!=0);\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageWBMP::Encode(CxFile * hFile)\r
-{\r
-       if (EncodeSafeCheck(hFile)) return false;\r
-\r
-       //check format limits\r
-       if (head.biBitCount!=1){\r
-               strcpy(info.szLastError,"Can't save this image as WBMP");\r
-               return false;\r
-       }\r
-\r
-       WBMPHEADER wbmpHead;\r
-       wbmpHead.Type=0;\r
-       wbmpHead.FixHeader=0;\r
-       wbmpHead.ImageWidth=head.biWidth;\r
-       wbmpHead.ImageHeight=head.biHeight;\r
-\r
-    // Write the file header\r
-       hFile->PutC('\0');\r
-       hFile->PutC('\0');\r
-       WriteOctet(hFile,wbmpHead.ImageWidth);\r
-       WriteOctet(hFile,wbmpHead.ImageHeight);\r
-    // Write the pixels\r
-       int linewidth=(wbmpHead.ImageWidth+7)/8;\r
-    CImageIterator iter(this);\r
-       iter.Upset();\r
-    for (DWORD y=0; y < wbmpHead.ImageHeight; y++){\r
-               hFile->Write(iter.GetRow(),linewidth,1);\r
-               iter.PrevRow();\r
-    }\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageWBMP::WriteOctet(CxFile * hFile, const DWORD data)\r
-{\r
-       int ns = 0;\r
-       while (data>>(ns+7)) ns+=7;\r
-       while (ns>0){\r
-               if (!hFile->PutC(0x80 | (BYTE)(data>>ns))) return false;\r
-               ns-=7;\r
-       }\r
-       if (!(hFile->PutC((BYTE)(0x7F & data)))) return false;\r
-       return true;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif // CXIMAGE_SUPPORT_WBMP\r
-\r
+/*
+ * File:       ximawbmp.cpp
+ * Purpose:    Platform Independent WBMP Image Class Loader and Writer
+ * 12/Jul/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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);
+
+       DWORD dat;
+       ReadOctet(hFile, &dat);
+       wbmpHead.FixHeader = (BYTE)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();
+
+       int linewidth=(head.biWidth+7)/8;
+    CImageIterator iter(this);
+       iter.Upset();
+    for (long 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, DWORD *data)
+{
+       BYTE c;
+       *data = 0;
+       do {
+               if (hFile->Eof()) return false;
+               c = (BYTE)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
+       int linewidth=(wbmpHead.ImageWidth+7)/8;
+    CImageIterator iter(this);
+       iter.Upset();
+    for (DWORD y=0; y < wbmpHead.ImageHeight; y++){
+               hFile->Write(iter.GetRow(),linewidth,1);
+               iter.PrevRow();
+    }
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageWBMP::WriteOctet(CxFile * hFile, const DWORD data)
+{
+       int ns = 0;
+       while (data>>(ns+7)) ns+=7;
+       while (ns>0){
+               if (!hFile->PutC(0x80 | (BYTE)(data>>ns))) return false;
+               ns-=7;
+       }
+       if (!(hFile->PutC((BYTE)(0x7F & data)))) return false;
+       return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_WBMP
+
index 8103345b4233f5d6effb8fd9e7caaab2f30ae5b6..f52368443ebd0ea4a2b0699809dd6e178153da59 100644 (file)
@@ -1,49 +1,49 @@
-/*\r
- * File:       ximawbmp.h\r
- * Purpose:    WBMP Image Class Loader and Writer\r
- */\r
-/* ==========================================================\r
- * CxImageWBMP (c) 12/Jul/2002 Davide Pizzolato - www.xdp.it\r
- * For conditions of distribution and use, see copyright notice in ximage.h\r
- * ==========================================================\r
- */\r
-#if !defined(__ximaWBMP_h)\r
-#define __ximaWBMP_h\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_WBMP\r
-\r
-class CxImageWBMP: public CxImage\r
-{\r
-#pragma pack(1)\r
-typedef struct tagWbmpHeader\r
-{\r
-    DWORD  Type;            // 0\r
-    BYTE   FixHeader;       // 0\r
-    DWORD  ImageWidth;      // Image Width\r
-    DWORD  ImageHeight;     // Image Height\r
-} WBMPHEADER;\r
-#pragma pack()\r
-public:\r
-       CxImageWBMP(): CxImage(CXIMAGE_FORMAT_WBMP) {}\r
-\r
-//     bool Load(const TCHAR * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_WBMP);}\r
-//     bool Save(const TCHAR * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_WBMP);}\r
-       bool Decode(CxFile * hFile);\r
-       bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }\r
-protected:\r
-       bool ReadOctet(CxFile * hFile, DWORD *data);\r
-\r
-public:\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-protected:\r
-       bool WriteOctet(CxFile * hFile, const DWORD data);\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-};\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+ * 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
+{
+    DWORD  Type;            // 0
+    BYTE   FixHeader;       // 0
+    DWORD  ImageWidth;      // Image Width
+    DWORD  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, DWORD *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 DWORD data);
+#endif // CXIMAGE_SUPPORT_ENCODE
+};
+
+#endif
+
+#endif
index 97ebf123db5777780394c89c406d3136c6963b85..1ca308023e235fc3fb7b2c3793d6514227fea4b1 100644 (file)
-/*\r
-*********************************************************************\r
- * File:       ximawmf.cpp\r
- * Purpose:    Windows Metafile Class Loader and Writer\r
- * Author:     Volker Horch - vhorch@gmx.de\r
- * created:    13-Jun-2002\r
- *\r
- * Note:       If the code below works, i wrote it.\r
- *                     If it doesn't work, i don't know who wrote it.\r
-*********************************************************************\r
- */\r
-\r
-/*\r
-*********************************************************************\r
-       Note by Author:\r
-*********************************************************************\r
-\r
-       Metafile Formats:\r
-       =================\r
-\r
-       There are 2 kinds of Windows Metafiles:\r
-       - Standard Windows Metafile\r
-       - Placeable Windows Metafile\r
-\r
-       A StandardWindows Metafile looks like:\r
-       - Metafile Header (MEATAHEADER)\r
-       - Metafile Records \r
-\r
-       A Placeable Metafile looks like:\r
-       - Aldus Header (METAFILEHEADER)\r
-       - Metafile Header (METAHEADER)\r
-       - Metafile Records\r
-\r
-       The "Metafile Header" and the "Metafile Records" are the same\r
-       for both formats. However, the Standard Metafile does not contain any\r
-       information about the original dimensions or x/y ratio of the Metafile.\r
-\r
-       I decided, to allow only placeable Metafiles here. If you also want to\r
-       enable Standard Metafiles, you will have to guess the dimensions of\r
-       the image.\r
-\r
-*********************************************************************\r
-       Limitations:    see ximawmf.h\r
-                                       you may configure some stuff there\r
-*********************************************************************\r
-*/\r
-\r
-#include "ximawmf.h"\r
-\r
-#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-bool CxImageWMF::Decode(CxFile *hFile, long nForceWidth, long nForceHeight)\r
-{\r
-       if (hFile == NULL) return false;\r
-\r
-       HENHMETAFILE    hMeta;\r
-       HDC                             hDC;\r
-       int                             cx,cy;\r
-\r
-       //save the current position of the file\r
-       long pos = hFile->Tell();\r
-\r
-       // Read the Metafile and convert to an Enhanced Metafile\r
-       METAFILEHEADER  mfh;\r
-       hMeta = ConvertWmfFiletoEmf(hFile, &mfh);\r
-       if (hMeta) {    // ok, it's a WMF\r
-\r
-/////////////////////////////////////////////////////////////////////\r
-//     We use the original WMF size information, because conversion to\r
-//     EMF adjusts the Metafile to Full Screen or does not set rclBounds at all\r
-//     ENHMETAHEADER   emh;\r
-//     UINT                    uRet;\r
-//     uRet = GetEnhMetaFileHeader(hMeta,                                      // handle of enhanced metafile \r
-//                                                             sizeof(ENHMETAHEADER),  // size of buffer, in bytes \r
-//                                                             &emh);                                  // address of buffer to receive data  \r
-//     if (!uRet){\r
-//             DeleteEnhMetaFile(hMeta);\r
-//             return false;\r
-//     }\r
-//     // calculate size\r
-//     cx = emh.rclBounds.right - emh.rclBounds.left;\r
-//     cy = emh.rclBounds.bottom - emh.rclBounds.top;\r
-/////////////////////////////////////////////////////////////////////\r
-\r
-               // calculate size\r
-               // scale the metafile (pixels/inch of metafile => pixels/inch of display)\r
-               // mfh.inch already checked to be <> 0\r
-\r
-               hDC = ::GetDC(0);\r
-               int cx1 = ::GetDeviceCaps(hDC, LOGPIXELSX);\r
-               int cy1 = ::GetDeviceCaps(hDC, LOGPIXELSY);\r
-               ::ReleaseDC(0, hDC);\r
-\r
-               cx = (mfh.inch/2 + (mfh.bbox.right - mfh.bbox.left) * cx1) / mfh.inch;\r
-               cy = (mfh.inch/2 + (mfh.bbox.bottom - mfh.bbox.top) * cy1) / mfh.inch;\r
-\r
-       } else {                // maybe it's an EMF...\r
-\r
-               hFile->Seek(pos,SEEK_SET);\r
-\r
-               ENHMETAHEADER   emh;\r
-               hMeta = ConvertEmfFiletoEmf(hFile, &emh);\r
-\r
-               if (!hMeta){\r
-                       strcpy(info.szLastError,"corrupted WMF");\r
-                       return false; // definitively give up\r
-               }\r
-\r
-               // ok, it's an EMF; calculate canvas size\r
-               cx = emh.rclBounds.right - emh.rclBounds.left;\r
-               cy = emh.rclBounds.bottom - emh.rclBounds.top;\r
-\r
-               // alternative methods, sometime not so reliable... [DP]\r
-               //cx = emh.szlDevice.cx;\r
-               //cy = emh.szlDevice.cy;\r
-               //\r
-               //hDC = ::GetDC(0);\r
-               //float hscale = (float)GetDeviceCaps(hDC, HORZRES)/(100.0f * GetDeviceCaps(hDC, HORZSIZE));\r
-               //float vscale  =  (float)GetDeviceCaps(hDC, VERTRES)/(100.0f * GetDeviceCaps(hDC, VERTSIZE));\r
-               //::ReleaseDC(0, hDC);\r
-               //cx = (long)((emh.rclFrame.right - emh.rclFrame.left) * hscale);\r
-               //cy = (long)((emh.rclFrame.bottom - emh.rclFrame.top) * vscale);\r
-       }\r
-\r
-       if (info.nEscape == -1) {       // Check if cancelled\r
-               head.biWidth = cx;\r
-               head.biHeight= cy;\r
-               info.dwType = CXIMAGE_FORMAT_WMF;\r
-               DeleteEnhMetaFile(hMeta);\r
-               strcpy(info.szLastError,"output dimensions returned");\r
-               return true;\r
-       }\r
-\r
-       if (!cx || !cy) {\r
-               DeleteEnhMetaFile(hMeta);\r
-               strcpy(info.szLastError,"empty WMF");\r
-               return false;\r
-       }\r
-\r
-       if (nForceWidth) cx=nForceWidth;\r
-       if (nForceHeight) cy=nForceHeight;\r
-       ShrinkMetafile(cx, cy);         // !! Otherwise Bitmap may have bombastic size\r
-\r
-       HDC hDC0 = ::GetDC(0);  // DC of screen\r
-       HBITMAP hBitmap = CreateCompatibleBitmap(hDC0, cx, cy); // has # colors of display\r
-       hDC = CreateCompatibleDC(hDC0); // memory dc compatible with screen\r
-       ::ReleaseDC(0, hDC0);   // don't need anymore. get rid of it.\r
-\r
-       if (hDC){\r
-               if (hBitmap){\r
-                       RECT rc = {0,0,cx,cy};\r
-                       int bpp = ::GetDeviceCaps(hDC, BITSPIXEL);\r
-\r
-                       HBITMAP hBitmapOld = (HBITMAP)SelectObject(hDC, hBitmap);\r
-\r
-                       // clear out the entire bitmap with windows background\r
-                       // because the MetaFile may not contain background information\r
-                       DWORD   dwBack = XMF_COLOR_BACK;\r
-#if XMF_SUPPORT_TRANSPARENCY\r
-                       if (bpp == 24) dwBack = XMF_COLOR_TRANSPARENT;\r
-#endif\r
-                   DWORD OldColor = SetBkColor(hDC, dwBack);\r
-                   ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);\r
-                       SetBkColor(hDC, OldColor);\r
-\r
-                       //retrieves optional palette entries from the specified enhanced metafile\r
-                       PLOGPALETTE plogPal;\r
-                       PBYTE pjTmp; \r
-                       HPALETTE hPal; \r
-                       int iEntries = GetEnhMetaFilePaletteEntries(hMeta, 0, NULL);\r
-                       if (iEntries) { \r
-                               if ((plogPal = (PLOGPALETTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, \r
-                                       sizeof(DWORD) + sizeof(PALETTEENTRY)*iEntries )) == NULL) { \r
-                                       DeleteObject(hBitmap);\r
-                                       DeleteDC(hDC);\r
-                                       DeleteEnhMetaFile(hMeta);\r
-                                       strcpy(info.szLastError,"Cancelled");\r
-                                       return false;\r
-                               } \r
-\r
-                               plogPal->palVersion = 0x300; \r
-                               plogPal->palNumEntries = (WORD) iEntries; \r
-                               pjTmp = (PBYTE) plogPal; \r
-                               pjTmp += 4; \r
-\r
-                               GetEnhMetaFilePaletteEntries(hMeta, iEntries, (PPALETTEENTRY)pjTmp); \r
-                               hPal = CreatePalette(plogPal); \r
-                               GlobalFree(plogPal); \r
-\r
-                               SelectPalette(hDC, hPal, FALSE); \r
-                               RealizePalette(hDC); \r
-                       } \r
-                       \r
-                       // Play the Metafile into Memory DC\r
-                       BOOL bRet = PlayEnhMetaFile(hDC,        // handle to a device context \r
-                                                                       hMeta,  // handle to an enhanced metafile  \r
-                                                                       &rc);   // pointer to bounding rectangle\r
-\r
-                       SelectObject(hDC, hBitmapOld);\r
-                       DeleteEnhMetaFile(hMeta);       // we are done with this one\r
-\r
-                       if (info.nEscape) {     // Check if cancelled\r
-                               DeleteObject(hBitmap);\r
-                               DeleteDC(hDC);\r
-                               strcpy(info.szLastError,"Cancelled");\r
-                               return false;\r
-                       }\r
-\r
-                       // the Bitmap now has the image.\r
-                       // Create our DIB and convert the DDB into DIB\r
-                       if (!Create(cx, cy, bpp, CXIMAGE_FORMAT_WMF)) {\r
-                               DeleteObject(hBitmap);\r
-                               DeleteDC(hDC);\r
-                               return false;\r
-                       }\r
-\r
-#if XMF_SUPPORT_TRANSPARENCY\r
-                       if (bpp == 24) {\r
-                               RGBQUAD rgbTrans = { XMF_RGBQUAD_TRANSPARENT };\r
-                               SetTransColor(rgbTrans);\r
-                       }\r
-#endif\r
-                   // We're finally ready to get the DIB. Call the driver and let\r
-                   // it party on our bitmap. It will fill in the color table,\r
-                   // and bitmap bits of our global memory block.\r
-                       bRet = GetDIBits(hDC, hBitmap, 0,\r
-                               (UINT)cy, GetBits(), (LPBITMAPINFO)pDib, DIB_RGB_COLORS);\r
-\r
-                       DeleteObject(hBitmap);\r
-                       DeleteDC(hDC);\r
-\r
-                       return (bRet!=0);\r
-               } else {\r
-                       DeleteDC(hDC);\r
-               }\r
-       } else {\r
-               if (hBitmap) DeleteObject(hBitmap);\r
-       }\r
-\r
-       DeleteEnhMetaFile(hMeta);\r
-\r
-       return false;\r
-}\r
-\r
-/**********************************************************************\r
- Function:     CheckMetafileHeader\r
- Purpose:      Check if the Metafileheader of a file is valid\r
-**********************************************************************/\r
-BOOL CxImageWMF::CheckMetafileHeader(METAFILEHEADER *metafileheader)\r
-{\r
-       WORD    *pw;\r
-       WORD    cs;\r
-       int             i;\r
-\r
-       // check magic #\r
-       if (metafileheader->key != 0x9ac6cdd7L) return false;\r
-\r
-       // test checksum of header\r
-       pw = (WORD *)metafileheader;\r
-       cs = *pw;\r
-       pw++;\r
-       for (i = 0; i < 9; i++) {\r
-               cs ^= *pw;\r
-               pw++;\r
-       }\r
-\r
-       if (cs != metafileheader->checksum)     return false;\r
-\r
-       // check resolution\r
-       if ((metafileheader->inch <= 0) || (metafileheader->inch > 2540)) return false;\r
-\r
-       return true;\r
-}\r
-\r
-/**********************************************************************\r
- Function:     ConvertWmfFiletoEmf\r
- Purpose:      Converts a Windows Metafile into an Enhanced Metafile\r
-**********************************************************************/\r
-HENHMETAFILE CxImageWMF::ConvertWmfFiletoEmf(CxFile *fp, METAFILEHEADER *metafileheader)\r
-{\r
-       HENHMETAFILE    hMeta;\r
-       long                    lenFile;\r
-       long                    len;\r
-       BYTE                    *p;\r
-       METAHEADER              mfHeader;\r
-       DWORD                   seekpos;\r
-\r
-       hMeta = 0;\r
-\r
-       // get length of the file\r
-       lenFile = fp->Size();\r
-\r
-       // a placeable metafile starts with a METAFILEHEADER\r
-       // read it and check metafileheader\r
-       len = fp->Read(metafileheader, 1, sizeof(METAFILEHEADER));\r
-       if (len < sizeof(METAFILEHEADER)) return (hMeta);\r
-\r
-       if (CheckMetafileHeader(metafileheader)) {\r
-               // This is a placeable metafile \r
-               // Convert the placeable format into something that can\r
-               // be used with GDI metafile functions \r
-               seekpos = sizeof(METAFILEHEADER);\r
-       } else {\r
-               // Not a placeable wmf. A windows metafile?\r
-               // at least not scaleable.\r
-               // we could try to convert, but would loose ratio. don't allow this\r
-               return (hMeta);\r
-\r
-               //metafileheader->bbox.right = ?;\r
-               //metafileheader->bbox.left = ?;\r
-               //metafileheader->bbox.bottom = ?;\r
-               //metafileheader->bbox.top = ?;\r
-               //metafileheader->inch = ?;\r
-               //\r
-               //seekpos = 0;\r
-               // fp->Seek(0, SEEK_SET);       // rewind\r
-       }\r
-\r
-       // At this point we have a metaheader regardless of whether\r
-       // the metafile was a windows metafile or a placeable metafile\r
-       // so check to see if it is valid. There is really no good\r
-       // way to do this so just make sure that the mtType is either\r
-       // 1 or 2 (memory or disk file) \r
-       // in addition we compare the length of the METAHEADER against\r
-       // the length of the file. if filelength < len => no Metafile\r
-\r
-       len = fp->Read(&mfHeader, 1, sizeof(METAHEADER));\r
-       if (len < sizeof(METAHEADER)) return (hMeta);\r
-\r
-       if ((mfHeader.mtType != 1) && (mfHeader.mtType != 2)) return (hMeta);\r
-\r
-       // Length in Bytes from METAHEADER\r
-       len = mfHeader.mtSize * 2;\r
-       if (len > lenFile) return (hMeta);\r
-\r
-       // Allocate memory for the metafile bits \r
-       p = (BYTE *)malloc(len);\r
-       if (!p) return (hMeta);\r
-\r
-       // seek back to METAHEADER and read all the stuff at once\r
-       fp->Seek(seekpos, SEEK_SET);\r
-       lenFile = fp->Read(p, 1, len);\r
-       if (lenFile != len)     {\r
-               free(p);\r
-               return (hMeta);\r
-       }\r
-\r
-       // the following (commented code)  works, but adjusts rclBound of the\r
-       // Enhanced Metafile to full screen.\r
-       // the METAFILEHEADER from above is needed to scale the image\r
-\r
-//     hMeta = SetWinMetaFileBits(len, p, NULL, NULL);\r
-\r
-       // scale the metafile (pixels/inch of metafile => pixels/inch of display)\r
-\r
-       METAFILEPICT    mfp;\r
-       int cx1, cy1;\r
-       HDC hDC;\r
-\r
-       hDC = ::GetDC(0);\r
-       cx1 = ::GetDeviceCaps(hDC, LOGPIXELSX);\r
-       cy1 = ::GetDeviceCaps(hDC, LOGPIXELSY);\r
-\r
-       memset(&mfp, 0, sizeof(mfp));\r
-\r
-       mfp.mm = MM_ANISOTROPIC;\r
-       mfp.xExt = 10000; //(metafileheader->bbox.right - metafileheader->bbox.left) * cx1 / metafileheader->inch;\r
-       mfp.yExt = 10000; //(metafileheader->bbox.bottom - metafileheader->bbox.top) * cy1 / metafileheader->inch;\r
-       mfp.hMF = 0;\r
-\r
-       // in MM_ANISOTROPIC mode xExt and yExt are in MM_HIENGLISH\r
-       // MM_HIENGLISH means: Each logical unit is converted to 0.001 inch\r
-       //mfp.xExt *= 1000;\r
-       //mfp.yExt *= 1000;\r
-       // ????\r
-       //int k = 332800 / ::GetSystemMetrics(SM_CXSCREEN);\r
-       //mfp.xExt *= k;        mfp.yExt *= k;\r
-\r
-       // fix for Win9x\r
-       while ((mfp.xExt < 6554) && (mfp.yExt < 6554))\r
-       {\r
-               mfp.xExt *= 10;\r
-               mfp.yExt *= 10;\r
-       }\r
-\r
-       hMeta = SetWinMetaFileBits(len, p, hDC, &mfp);\r
-\r
-       if (!hMeta){ //try 2nd conversion using a different mapping\r
-               mfp.mm = MM_TEXT;\r
-               hMeta = SetWinMetaFileBits(len, p, hDC, &mfp);\r
-       }\r
-\r
-       ::ReleaseDC(0, hDC);\r
-\r
-       // Free Memory\r
-       free(p);\r
-\r
-       return (hMeta);\r
-}\r
-/////////////////////////////////////////////////////////////////////\r
-HENHMETAFILE CxImageWMF::ConvertEmfFiletoEmf(CxFile *pFile, ENHMETAHEADER *pemfh)\r
-{\r
-       HENHMETAFILE    hMeta;\r
-       long iLen = pFile->Size();\r
-\r
-       // Check the header first: <km>\r
-       long pos = pFile->Tell();\r
-       long iLenRead = pFile->Read(pemfh, 1, sizeof(ENHMETAHEADER));\r
-       if (iLenRead < sizeof(ENHMETAHEADER))         return NULL;\r
-       if (pemfh->iType != EMR_HEADER)               return NULL;\r
-       if (pemfh->dSignature != ENHMETA_SIGNATURE)   return NULL;\r
-       //if (pemfh->nBytes != (DWORD)iLen)             return NULL;\r
-       pFile->Seek(pos,SEEK_SET);\r
-\r
-       BYTE* pBuff = (BYTE *)malloc(iLen);\r
-       if (!pBuff)     return (FALSE);\r
-\r
-       // Read the Enhanced Metafile\r
-       iLenRead = pFile->Read(pBuff, 1, iLen);\r
-       if (iLenRead != iLen) {\r
-               free(pBuff);\r
-               return NULL;\r
-       }\r
-\r
-       // Make it a Memory Metafile\r
-       hMeta = SetEnhMetaFileBits(iLen, pBuff);\r
-\r
-       free(pBuff);    // finished with this one\r
-\r
-       if (!hMeta)     return NULL;    // oops.\r
-\r
-       // Get the Enhanced Metafile Header\r
-       UINT uRet = GetEnhMetaFileHeader(hMeta,                         // handle of enhanced metafile \r
-                                                               sizeof(ENHMETAHEADER),  // size of buffer, in bytes \r
-                                                               pemfh);                                 // address of buffer to receive data  \r
-  \r
-       if (!uRet) {\r
-               DeleteEnhMetaFile(hMeta);\r
-               return NULL;\r
-       }\r
-\r
-       return (hMeta);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_DECODE\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-/////////////////////////////////////////////////////////////////////\r
-bool CxImageWMF::Encode(CxFile * hFile)\r
-{\r
-       if (hFile == NULL) return false;\r
-       strcpy(info.szLastError, "Save WMF not supported");\r
-       return false;\r
-}\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-/////////////////////////////////////////////////////////////////////\r
-\r
-/**********************************************************************\r
-Function:      ShrinkMetafile\r
-Purpose:       Shrink the size of a metafile to be not larger than\r
-                       the definition\r
-**********************************************************************/\r
-void CxImageWMF::ShrinkMetafile(int &cx, int &cy)\r
-{\r
-       int     xScreen = XMF_MAXSIZE_CX;\r
-       int     yScreen = XMF_MAXSIZE_CY;\r
-\r
-       if (cx > xScreen){\r
-               cy = cy * xScreen / cx;\r
-               cx = xScreen;\r
-       }\r
-\r
-       if (cy > yScreen){\r
-               cx = cx * yScreen / cy;\r
-               cy = yScreen;\r
-       }\r
-}\r
-\r
-#endif // CIMAGE_SUPPORT_WMF\r
-\r
+/*
+*********************************************************************
+ * 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, long nForceWidth, long nForceHeight)
+{
+       if (hFile == NULL) return false;
+
+       HENHMETAFILE    hMeta;
+       HDC                             hDC;
+       int                             cx,cy;
+
+       //save the current position of the file
+       long 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;
+//     UINT                    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);
+               int cx1 = ::GetDeviceCaps(hDC, LOGPIXELSX);
+               int 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 = (long)((emh.rclFrame.right - emh.rclFrame.left) * hscale);
+               //cy = (long)((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};
+                       int 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
+                       DWORD   dwBack = XMF_COLOR_BACK;
+#if XMF_SUPPORT_TRANSPARENCY
+                       if (bpp == 24) dwBack = XMF_COLOR_TRANSPARENT;
+#endif
+                   DWORD 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; 
+                       int iEntries = GetEnhMetaFilePaletteEntries(hMeta, 0, NULL);
+                       if (iEntries) { 
+                               if ((plogPal = (PLOGPALETTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, 
+                                       sizeof(DWORD) + sizeof(PALETTEENTRY)*iEntries )) == NULL) { 
+                                       DeleteObject(hBitmap);
+                                       DeleteDC(hDC);
+                                       DeleteEnhMetaFile(hMeta);
+                                       strcpy(info.szLastError,"Cancelled");
+                                       return false;
+                               } 
+
+                               plogPal->palVersion = 0x300; 
+                               plogPal->palNumEntries = (WORD) 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,
+                               (UINT)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)
+{
+       WORD    *pw;
+       WORD    cs;
+       int             i;
+
+       // check magic #
+       if (metafileheader->key != 0x9ac6cdd7L) return false;
+
+       // test checksum of header
+       pw = (WORD *)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;
+       long                    lenFile;
+       long                    len;
+       BYTE                    *p;
+       METAHEADER              mfHeader;
+       DWORD                   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 = (BYTE *)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;
+       int 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;
+       // ????
+       //int 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;
+       long iLen = pFile->Size();
+
+       // Check the header first: <km>
+       long pos = pFile->Tell();
+       long 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 != (DWORD)iLen)             return NULL;
+       pFile->Seek(pos,SEEK_SET);
+
+       BYTE* pBuff = (BYTE *)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
+       UINT 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(int &cx, int &cy)
+{
+       int     xScreen = XMF_MAXSIZE_CX;
+       int     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
+
index fb59452872687850194f0eccd913852c55d4da4d..75e119a064289363e77c0f4b7689c9d5d605d55c 100644 (file)
-/*\r
-*********************************************************************\r
- * File:       ximawmf.h\r
- * Purpose:    Windows Metafile Class Loader and Writer\r
- * Author:     Volker Horch - vhorch@gmx.de\r
- * created:    13-Jun-2002\r
-*********************************************************************\r
- */\r
-\r
-/*\r
-*********************************************************************\r
-       Notes by Author:\r
-*********************************************************************\r
-\r
-       Limitations:\r
-       ============\r
-\r
-       a) Transparency:\r
-\r
-       A Metafile is vector graphics, which has transparency by design.\r
-       This class always converts into a Bitmap format. Transparency is\r
-       supported, but there is no good way to find out, which parts\r
-       of the Metafile are transparent. There are two ways how we can\r
-       handle this:\r
-\r
-       - Clear the Background of the Bitmap with the background color\r
-         you like (i have used COLOR_WINDOW) and don't support transparency.\r
-\r
-         below #define XMF_SUPPORT_TRANSPARENCY 0\r
-                       #define XMF_COLOR_BACK RGB(Background color you like)\r
-\r
-       - Clear the Background of the Bitmap with a very unusual color\r
-         (which one ?) and use this color as the transparent color\r
-\r
-         below #define XMF_SUPPORT_TRANSPARENCY 1\r
-                       #define XMF_COLOR_TRANSPARENT_R ...\r
-                       #define XMF_COLOR_TRANSPARENT_G ...\r
-                       #define XMF_COLOR_TRANSPARENT_B ...\r
-\r
-       b) Resolution\r
-\r
-       Once we have converted the Metafile into a Bitmap and we zoom in\r
-       or out, the image may not look very good. If we still had the\r
-       original Metafile, zooming would produce good results always.\r
-\r
-       c) Size\r
-\r
-       Although the filesize of a Metafile may be very small, it might\r
-       produce a Bitmap with a bombastic size. Assume you have a Metafile\r
-       with an image size of 6000*4000, which contains just one Metafile\r
-       record ((e.g. a line from (0,0) to (6000, 4000)). The filesize\r
-       of this Metafile would be let's say 100kB. If we convert it to\r
-       a 6000*4000 Bitmap with 24 Bits/Pixes, the Bitmap would consume\r
-       about 68MB of memory.\r
-\r
-       I have choosen, to limit the size of the Bitmap to max.\r
-       screensize, to avoid memory problems.\r
-\r
-       If you want something else,\r
-       modify #define XMF_MAXSIZE_CX / XMF_MAXSIZE_CY below\r
-\r
-*********************************************************************\r
-*/\r
-\r
-#ifndef _XIMAWMF_H\r
-#define _XIMAWMF_H\r
-\r
-#include "ximage.h"\r
-\r
-#if CXIMAGE_SUPPORT_WMF && CXIMAGE_SUPPORT_WINDOWS\r
-\r
-class CxImageWMF: public CxImage\r
-{\r
-\r
-#pragma pack(1)\r
-\r
-typedef struct tagRECT16\r
-{\r
-       short int       left;\r
-       short int       top;\r
-       short int       right;\r
-       short int       bottom;\r
-} RECT16;\r
-\r
-// taken from Windos 3.11 SDK Documentation (Programmer's Reference Volume 4: Resources)\r
-typedef struct tagMETAFILEHEADER\r
-{\r
-       DWORD   key;            // always 0x9ac6cdd7\r
-       WORD    reserved1;      // reserved = 0\r
-       RECT16  bbox;           // bounding rectangle in metafile units as defined in "inch"\r
-       WORD    inch;           // number of metafile units per inch (should be < 1440)\r
-       DWORD   reserved2;      // reserved = 0\r
-       WORD    checksum;       // sum of the first 10 WORDS (using XOR operator)\r
-} METAFILEHEADER;\r
-\r
-#pragma pack()\r
-\r
-public:\r
-       CxImageWMF(): CxImage(CXIMAGE_FORMAT_WMF) { }\r
-\r
-       bool Decode(CxFile * hFile, long nForceWidth=0, long nForceHeight=0);\r
-       bool Decode(FILE *hFile, long nForceWidth=0, long nForceHeight=0)\r
-                       { CxIOFile file(hFile); return Decode(&file,nForceWidth,nForceHeight); }\r
-\r
-#if CXIMAGE_SUPPORT_ENCODE\r
-       bool Encode(CxFile * hFile);\r
-       bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }\r
-#endif // CXIMAGE_SUPPORT_ENCODE\r
-\r
-protected:\r
-       void ShrinkMetafile(int &cx, int &cy);\r
-       BOOL CheckMetafileHeader(METAFILEHEADER *pmetafileheader);\r
-       HENHMETAFILE ConvertWmfFiletoEmf(CxFile *pFile, METAFILEHEADER *pmetafileheader);\r
-       HENHMETAFILE ConvertEmfFiletoEmf(CxFile *pFile, ENHMETAHEADER *pemfh);\r
-\r
-};\r
-\r
-#define        METAFILEKEY     0x9ac6cdd7L\r
-\r
-// Background color definition (if no transparency). see Notes above\r
-#define        XMF_COLOR_BACK  GetSysColor(COLOR_WINDOW)\r
-// alternatives\r
-//#define      XMF_COLOR_BACK  RGB(192, 192, 192)      // lite gray\r
-//#define      XMF_COLOR_BACK  RGB(  0,   0,   0)      // black\r
-//#define      XMF_COLOR_BACK  RGB(255, 255, 255)      // white\r
-\r
-\r
-// transparency support. see Notes above\r
-#define        XMF_SUPPORT_TRANSPARENCY        0\r
-#define        XMF_COLOR_TRANSPARENT_R         211\r
-#define        XMF_COLOR_TRANSPARENT_G         121\r
-#define        XMF_COLOR_TRANSPARENT_B         112\r
-// don't change\r
-#define        XMF_COLOR_TRANSPARENT           RGB (XMF_COLOR_TRANSPARENT_R, \\r
-                                                                                XMF_COLOR_TRANSPARENT_G, \\r
-                                                                                XMF_COLOR_TRANSPARENT_B)\r
-// don't change\r
-#define        XMF_RGBQUAD_TRANSPARENT         XMF_COLOR_TRANSPARENT_B, \\r
-                                                                       XMF_COLOR_TRANSPARENT_G, \\r
-                                                                       XMF_COLOR_TRANSPARENT_R, \\r
-                                                                       0\r
-// max. size. see Notes above\r
-// alternatives\r
-//#define      XMF_MAXSIZE_CX  (GetSystemMetrics(SM_CXSCREEN)-10)\r
-//#define      XMF_MAXSIZE_CY  (GetSystemMetrics(SM_CYSCREEN)-50)\r
-//#define      XMF_MAXSIZE_CX  (2*GetSystemMetrics(SM_CXSCREEN)/3)\r
-//#define      XMF_MAXSIZE_CY  (2*GetSystemMetrics(SM_CYSCREEN)/3)\r
-#define        XMF_MAXSIZE_CX  4000\r
-#define        XMF_MAXSIZE_CY  4000\r
-\r
-\r
-#endif\r
-\r
-#endif\r
+/*
+*********************************************************************
+ * 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
+{
+       short int       left;
+       short int       top;
+       short int       right;
+       short int       bottom;
+} RECT16;
+
+// taken from Windos 3.11 SDK Documentation (Programmer's Reference Volume 4: Resources)
+typedef struct tagMETAFILEHEADER
+{
+       DWORD   key;            // always 0x9ac6cdd7
+       WORD    reserved1;      // reserved = 0
+       RECT16  bbox;           // bounding rectangle in metafile units as defined in "inch"
+       WORD    inch;           // number of metafile units per inch (should be < 1440)
+       DWORD   reserved2;      // reserved = 0
+       WORD    checksum;       // sum of the first 10 WORDS (using XOR operator)
+} METAFILEHEADER;
+
+#pragma pack()
+
+public:
+       CxImageWMF(): CxImage(CXIMAGE_FORMAT_WMF) { }
+
+       bool Decode(CxFile * hFile, long nForceWidth=0, long nForceHeight=0);
+       bool Decode(FILE *hFile, long nForceWidth=0, long 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(int &cx, int &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
index 9e75a3773793ea2729d72b661e27847be9fd3d42..2ae2f936c85c9308490b79fb2749e0e3ddde0e8e 100644 (file)
-// xImaWnd.cpp : Windows functions\r
-/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it\r
- * CxImage version 6.0.0 02/Feb/2008\r
- */\r
-\r
-#include "ximage.h"\r
-\r
-#include "ximaiter.h" \r
-#include "ximabmp.h"\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if defined (_WIN32_WCE)\r
-\r
-#ifndef DEFAULT_GUI_FONT\r
-#define DEFAULT_GUI_FONT 17\r
-#endif\r
-\r
-#ifndef PROOF_QUALITY\r
-#define PROOF_QUALITY 2\r
-#endif\r
-\r
-struct DIBINFO : public BITMAPINFO\r
-{\r
-       RGBQUAD    arColors[255];    // Color table info - adds an extra 255 entries to palette\r
-       operator LPBITMAPINFO()          { return (LPBITMAPINFO) this; }\r
-       operator LPBITMAPINFOHEADER()    { return &bmiHeader;          }\r
-       RGBQUAD* ColorTable()            { return bmiColors;           }\r
-};\r
-\r
-int BytesPerLine(int nWidth, int nBitsPerPixel)\r
-{\r
-    return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8;\r
-}\r
-\r
-int NumColorEntries(int nBitsPerPixel, int nCompression, DWORD biClrUsed)\r
-{\r
-       int nColors = 0;\r
-       switch (nBitsPerPixel)\r
-       {\r
-       case 1:\r
-               nColors = 2;  break;\r
-       case 2:\r
-               nColors = 4;  break;   // winCE only\r
-       case 4:\r
-               nColors = 16; break;\r
-       case 8:\r
-               nColors =256; break;\r
-       case 24:\r
-               nColors = 0;  break;\r
-       case 16:\r
-       case 32:\r
-               nColors = 3;  break; // I've found that PocketPCs need this regardless of BI_RGB or BI_BITFIELDS\r
-       default:\r
-               ASSERT(FALSE);\r
-       }\r
-       // If biClrUsed is provided, and it is a legal value, use it\r
-       if (biClrUsed > 0 && biClrUsed <= (DWORD)nColors)\r
-               return biClrUsed;\r
-       \r
-       return nColors;\r
-}\r
-\r
-int GetDIBits(\r
-  HDC hdc,           // handle to DC\r
-  HBITMAP hbmp,      // handle to bitmap\r
-  UINT uStartScan,   // first scan line to set\r
-  UINT cScanLines,   // number of scan lines to copy\r
-  LPVOID lpvBits,    // array for bitmap bits\r
-  LPBITMAPINFO lpbi, // bitmap data buffer\r
-  UINT uUsage        // RGB or palette index\r
-)\r
-{\r
-       UINT    iColorTableSize = 0;\r
-\r
-       if (!hbmp)\r
-               return 0;\r
-\r
-       // Get dimensions of bitmap\r
-       BITMAP bm;\r
-       if (!::GetObject(hbmp, sizeof(bm),(LPVOID)&bm))\r
-               return 0;\r
-\r
-       //3. Creating new bitmap and receive pointer to it's bits.\r
-       HBITMAP hTargetBitmap;\r
-       void *pBuffer;\r
-       \r
-       //3.1 Initilize DIBINFO structure\r
-       DIBINFO  dibInfo;\r
-       dibInfo.bmiHeader.biBitCount = 24;\r
-       dibInfo.bmiHeader.biClrImportant = 0;\r
-       dibInfo.bmiHeader.biClrUsed = 0;\r
-       dibInfo.bmiHeader.biCompression = 0;\r
-       dibInfo.bmiHeader.biHeight = bm.bmHeight;\r
-       dibInfo.bmiHeader.biPlanes = 1;\r
-       dibInfo.bmiHeader.biSize = 40;\r
-       dibInfo.bmiHeader.biSizeImage = bm.bmHeight*BytesPerLine(bm.bmWidth,24);\r
-       dibInfo.bmiHeader.biWidth = bm.bmWidth;\r
-       dibInfo.bmiHeader.biXPelsPerMeter = 3780;\r
-       dibInfo.bmiHeader.biYPelsPerMeter = 3780;\r
-       dibInfo.bmiColors[0].rgbBlue = 0;\r
-       dibInfo.bmiColors[0].rgbGreen = 0;\r
-       dibInfo.bmiColors[0].rgbRed = 0;\r
-       dibInfo.bmiColors[0].rgbReserved = 0;\r
-\r
-       //3.2 Create bitmap and receive pointer to points into pBuffer\r
-       HDC hDC = ::GetDC(NULL);\r
-       ASSERT(hDC);\r
-       hTargetBitmap = CreateDIBSection(\r
-               hDC,\r
-               (const BITMAPINFO*)dibInfo,\r
-               DIB_RGB_COLORS,\r
-               (void**)&pBuffer,\r
-               NULL,\r
-               0);\r
-\r
-       ::ReleaseDC(NULL, hDC);\r
-\r
-       //4. Copy source bitmap into the target bitmap.\r
-\r
-       //4.1 Create 2 device contexts\r
-       HDC memDc = CreateCompatibleDC(NULL);\r
-       if (!memDc) {\r
-               ASSERT(FALSE);\r
-       }\r
-       \r
-       HDC targetDc = CreateCompatibleDC(NULL);\r
-       if (!targetDc) {\r
-               ASSERT(FALSE);\r
-       }\r
-\r
-       //4.2 Select source bitmap into one DC, target into another\r
-       HBITMAP hOldBitmap1 = (HBITMAP)::SelectObject(memDc, hbmp);\r
-       HBITMAP hOldBitmap2 = (HBITMAP)::SelectObject(targetDc, hTargetBitmap);\r
-\r
-       //4.3 Copy source bitmap into the target one\r
-       BitBlt(targetDc, 0, 0, bm.bmWidth, bm.bmHeight, memDc, 0, 0, SRCCOPY);\r
-\r
-       //4.4 Restore device contexts\r
-       ::SelectObject(memDc, hOldBitmap1);\r
-       ::SelectObject(targetDc, hOldBitmap2);\r
-       DeleteDC(memDc);\r
-       DeleteDC(targetDc);\r
-\r
-       //Here we can bitmap bits: pBuffer. Note:\r
-       // 1. pBuffer contains 3 bytes per point\r
-       // 2. Lines ane from the bottom to the top!\r
-       // 3. Points in the line are from the left to the right\r
-       // 4. Bytes in one point are BGR (blue, green, red) not RGB\r
-       // 5. Don't delete pBuffer, it will be automatically deleted\r
-       //    when delete hTargetBitmap\r
-       lpvBits = pBuffer;\r
-\r
-       DeleteObject(hbmp);\r
-       //DeleteObject(hTargetBitmap);\r
-\r
-       return 1;\r
-}\r
-#endif \r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#if CXIMAGE_SUPPORT_WINDOWS\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImage::Blt(HDC pDC, long x, long y)\r
-{\r
-       if((pDib==0)||(pDC==0)||(!info.bEnabled)) return 0;\r
-\r
-    HBRUSH brImage = CreateDIBPatternBrushPt(pDib, DIB_RGB_COLORS);\r
-    POINT pt;\r
-    SetBrushOrgEx(pDC,x,y,&pt); //<RT>\r
-    HBRUSH brOld = (HBRUSH) SelectObject(pDC, brImage);\r
-    PatBlt(pDC, x, y, head.biWidth, head.biHeight, PATCOPY);\r
-    SelectObject(pDC, brOld);\r
-    SetBrushOrgEx(pDC,pt.x,pt.y,NULL);\r
-    DeleteObject(brImage);\r
-    return 1;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Transfer the image in a global bitmap handle (clipboard copy)\r
- */\r
-HANDLE CxImage::CopyToHandle()\r
-{\r
-       HANDLE hMem=NULL;\r
-       if (pDib){\r
-               hMem= GlobalAlloc(GHND, GetSize());\r
-               if (hMem){\r
-                       BYTE* pDst=(BYTE*)GlobalLock(hMem);\r
-                       if (pDst){\r
-                               memcpy(pDst,pDib,GetSize());\r
-                       }\r
-                       GlobalUnlock(hMem);\r
-               }\r
-       }\r
-       return hMem;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Global object (clipboard paste) constructor\r
- * \param hMem: source bitmap object, the clipboard format must be CF_DIB\r
- * \return true if everything is ok\r
- */\r
-bool CxImage::CreateFromHANDLE(HANDLE hMem)\r
-{\r
-       if (!Destroy())\r
-               return false;\r
-\r
-       DWORD dwSize = GlobalSize(hMem);\r
-       if (!dwSize) return false;\r
-\r
-       BYTE *lpVoid;                                           //pointer to the bitmap\r
-       lpVoid = (BYTE *)GlobalLock(hMem);\r
-       BITMAPINFOHEADER *pHead;                        //pointer to the bitmap header\r
-       pHead = (BITMAPINFOHEADER *)lpVoid;\r
-       if (lpVoid){\r
-\r
-               //CxMemFile hFile(lpVoid,dwSize);\r
-\r
-               //copy the bitmap header\r
-               memcpy(&head,pHead,sizeof(BITMAPINFOHEADER));\r
-               //check if it's a top-down bitmap\r
-               bool bTopDownDib = head.biHeight<0;\r
-               if (bTopDownDib) head.biHeight=-head.biHeight;\r
-               //create the image\r
-               if(!Create(head.biWidth,head.biHeight,head.biBitCount)){\r
-                       GlobalUnlock(lpVoid);\r
-                       return false;\r
-               }\r
-               //preserve DPI\r
-               SetXDPI((long)floor(head.biXPelsPerMeter * 254.0 / 10000.0 + 0.5));\r
-               SetYDPI((long)floor(head.biYPelsPerMeter * 254.0 / 10000.0 + 0.5));\r
-\r
-               /*//copy the pixels (old way)\r
-               if((pHead->biCompression != BI_RGB) || (pHead->biBitCount == 32)){ //<Jörgen Alfredsson>\r
-                       // BITFIELD case\r
-                       // set the internal header in the dib\r
-                       memcpy(pDib,&head,sizeof(head));\r
-                       // get the bitfield masks\r
-                       DWORD bf[3];\r
-                       memcpy(bf,lpVoid+pHead->biSize,12);\r
-                       // transform into RGB\r
-                       Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)pHead->biBitCount);\r
-               } else { //normal bitmap\r
-                       memcpy(pDib,lpVoid,GetSize());\r
-               }*/\r
-\r
-               // <Michael Gandyra>\r
-               // fill in color map\r
-               bool bIsOldBmp = (head.biSize == sizeof(BITMAPCOREHEADER));\r
-               RGBQUAD *pRgb = GetPalette();\r
-               if (pRgb) {\r
-                       // number of colors to fill in\r
-                       int nColors = DibNumColors(pHead);\r
-                       if (bIsOldBmp) {\r
-                               /* get pointer to BITMAPCOREINFO (old style 1.x) */\r
-                               LPBITMAPCOREINFO lpbmc = (LPBITMAPCOREINFO)lpVoid;\r
-                               for (int i = nColors - 1; i >= 0; i--) {\r
-                                       pRgb[i].rgbRed      = lpbmc->bmciColors[i].rgbtRed;\r
-                                       pRgb[i].rgbGreen    = lpbmc->bmciColors[i].rgbtGreen;\r
-                                       pRgb[i].rgbBlue     = lpbmc->bmciColors[i].rgbtBlue;\r
-                                       pRgb[i].rgbReserved = (BYTE)0;\r
-                               }\r
-                       } else {\r
-                               /* get pointer to BITMAPINFO (new style 3.x) */\r
-                               LPBITMAPINFO lpbmi = (LPBITMAPINFO)lpVoid;\r
-                               for (int i = nColors - 1; i >= 0; i--) {\r
-                                       pRgb[i].rgbRed      = lpbmi->bmiColors[i].rgbRed;\r
-                                       pRgb[i].rgbGreen    = lpbmi->bmiColors[i].rgbGreen;\r
-                                       pRgb[i].rgbBlue     = lpbmi->bmiColors[i].rgbBlue;\r
-                                       pRgb[i].rgbReserved = (BYTE)0;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               // <Michael Gandyra>\r
-               DWORD dwCompression = pHead->biCompression;\r
-               // compressed bitmap ?\r
-               if(dwCompression!=BI_RGB || pHead->biBitCount==32 || pHead->biBitCount ==16) {\r
-                       // get the bitmap bits\r
-                       LPSTR lpDIBBits = (LPSTR)((BYTE*)pHead + *(DWORD*)pHead + (WORD)(GetNumColors() * sizeof(RGBQUAD)));\r
-                       // decode and copy them to our image\r
-                       switch (pHead->biBitCount) {\r
-                       case 32 :\r
-                               {\r
-                                       // BITFIELD case\r
-                                       if (dwCompression == BI_BITFIELDS || dwCompression == BI_RGB) {\r
-                                               // get the bitfield masks\r
-                                               DWORD bf[3];\r
-                                               memcpy(bf,lpVoid+pHead->biSize,12);\r
-                                               // transform into RGB\r
-                                               Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)pHead->biBitCount);\r
-                                       } else {\r
-                                               // "unknown compression";\r
-                                               GlobalUnlock(lpVoid);\r
-                                               return false;\r
-                                       }\r
-                               }\r
-                               break;\r
-                       case 16 :\r
-                               {\r
-                                       // get the bitfield masks\r
-                                       long offset=0;\r
-                                       DWORD bf[3];\r
-                                       if (dwCompression == BI_BITFIELDS) {\r
-                                               memcpy(bf,lpVoid+pHead->biSize,12);\r
-                                               offset= 12;\r
-                                       } else {\r
-                                               bf[0] = 0x7C00;\r
-                                               bf[1] = 0x3E0;\r
-                                               bf[2] = 0x1F; // RGB555\r
-                                       }\r
-                                       // copy the pixels\r
-                                       memcpy(info.pImage, lpDIBBits + offset, head.biHeight*((head.biWidth+1)/2)*4);\r
-                                       // transform into RGB\r
-                                       Bitfield2RGB(info.pImage, bf[0], bf[1], bf[2], 16);\r
-                               }\r
-                               break;\r
-                       case 8 :\r
-                       case 4 :\r
-                       case 1 :\r
-                               {\r
-                                       switch (dwCompression) {\r
-                                       case BI_RLE4:\r
-                                               {\r
-                                                       BYTE status_byte = 0;\r
-                                                       BYTE second_byte = 0;\r
-                                                       int scanline = 0;\r
-                                                       int bits = 0;\r
-                                                       BOOL low_nibble = FALSE;\r
-                                                       CImageIterator iter(this);\r
-\r
-                                                       for (BOOL bContinue = TRUE; bContinue; ) {\r
-                                                               status_byte = *(lpDIBBits++);\r
-                                                               switch (status_byte) {\r
-                                                               case RLE_COMMAND :\r
-                                                                       status_byte = *(lpDIBBits++);\r
-                                                                       switch (status_byte) {\r
-                                                                       case RLE_ENDOFLINE :\r
-                                                                               bits = 0;\r
-                                                                               scanline++;\r
-                                                                               low_nibble = FALSE;\r
-                                                                               break;\r
-                                                                       case RLE_ENDOFBITMAP :\r
-                                                                               bContinue = FALSE;\r
-                                                                               break;\r
-                                                                       case RLE_DELTA :\r
-                                                                               {\r
-                                                                                       // read the delta values\r
-                                                                                       BYTE delta_x;\r
-                                                                                       BYTE delta_y;\r
-                                                                                       delta_x = *(lpDIBBits++);\r
-                                                                                       delta_y = *(lpDIBBits++);\r
-                                                                                       // apply them\r
-                                                                                       bits       += delta_x / 2;\r
-                                                                                       scanline   += delta_y;\r
-                                                                                       break;\r
-                                                                               }\r
-                                                                       default :\r
-                                                                               second_byte = *(lpDIBBits++);\r
-                                                                               BYTE* sline = iter.GetRow(scanline);\r
-                                                                               for (int i = 0; i < status_byte; i++) {\r
-                                                                                       if ((BYTE*)(sline+bits) < (BYTE*)(info.pImage+head.biSizeImage)){\r
-                                                                                               if (low_nibble) {\r
-                                                                                                       if (i&1)\r
-                                                                                                               *(sline + bits) |= (second_byte & 0x0f);\r
-                                                                                                       else\r
-                                                                                                               *(sline + bits) |= (second_byte & 0xf0)>>4;\r
-                                                                                                       bits++;\r
-                                                                                               } else {\r
-                                                                                                       if (i&1)\r
-                                                                                                               *(sline + bits) = (BYTE)(second_byte & 0x0f)<<4;\r
-                                                                                                       else\r
-                                                                                                               *(sline + bits) = (BYTE)(second_byte & 0xf0);\r
-                                                                                               }\r
-                                                                                       }\r
-\r
-                                                                                       if ((i & 1) && (i != (status_byte - 1)))\r
-                                                                                               second_byte = *(lpDIBBits++);\r
-\r
-                                                                                       low_nibble = !low_nibble;\r
-                                                                               }\r
-                                                                               if ((((status_byte+1) >> 1) & 1 ) == 1)\r
-                                                                                       second_byte = *(lpDIBBits++);                                                                                           \r
-                                                                               break;\r
-                                                                       };\r
-                                                                       break;\r
-                                                                       default :\r
-                                                                       {\r
-                                                                               BYTE* sline = iter.GetRow(scanline);\r
-                                                                               second_byte = *(lpDIBBits++);\r
-                                                                               for (unsigned i = 0; i < status_byte; i++) {\r
-                                                                                       if ((BYTE*)(sline+bits) < (BYTE*)(info.pImage+head.biSizeImage)){\r
-                                                                                               if (low_nibble) {\r
-                                                                                                       if (i&1)\r
-                                                                                                               *(sline + bits) |= (second_byte & 0x0f);\r
-                                                                                                       else\r
-                                                                                                               *(sline + bits) |= (second_byte & 0xf0)>>4;\r
-                                                                                                       bits++;\r
-                                                                                               } else {\r
-                                                                                                       if (i&1)\r
-                                                                                                               *(sline + bits) = (BYTE)(second_byte & 0x0f)<<4;\r
-                                                                                                       else\r
-                                                                                                               *(sline + bits) = (BYTE)(second_byte & 0xf0);\r
-                                                                                               }\r
-                                                                                       }\r
-                                                                                       low_nibble = !low_nibble;\r
-                                                                               }\r
-                                                                       }\r
-                                                                       break;\r
-                                                               };\r
-                                                       }\r
-                                               }\r
-                                               break;\r
-                                       case BI_RLE8 :\r
-                                               {\r
-                                                       BYTE status_byte = 0;\r
-                                                       BYTE second_byte = 0;\r
-                                                       int scanline = 0;\r
-                                                       int bits = 0;\r
-                                                       CImageIterator iter(this);\r
-\r
-                                                       for (BOOL bContinue = TRUE; bContinue; ) {\r
-                                                               status_byte = *(lpDIBBits++);\r
-                                                               if (status_byte==RLE_COMMAND) {\r
-                                                                       status_byte = *(lpDIBBits++);\r
-                                                                       switch (status_byte) {\r
-                                                                       case RLE_ENDOFLINE :\r
-                                                                               bits = 0;\r
-                                                                               scanline++;\r
-                                                                               break;\r
-                                                                       case RLE_ENDOFBITMAP :\r
-                                                                               bContinue = FALSE;\r
-                                                                               break;\r
-                                                                       case RLE_DELTA :\r
-                                                                               {\r
-                                                                                       // read the delta values\r
-                                                                                       BYTE delta_x;\r
-                                                                                       BYTE delta_y;\r
-                                                                                       delta_x = *(lpDIBBits++);\r
-                                                                                       delta_y = *(lpDIBBits++);\r
-                                                                                       // apply them\r
-                                                                                       bits     += delta_x;\r
-                                                                                       scanline += delta_y;\r
-                                                                               }\r
-                                                                               break;\r
-                                                                       default :\r
-                                                                               int nNumBytes = sizeof(BYTE) * status_byte;\r
-                                                                               memcpy((void *)(iter.GetRow(scanline) + bits), lpDIBBits, nNumBytes);\r
-                                                                               lpDIBBits += nNumBytes;\r
-                                                                               // align run length to even number of bytes \r
-                                                                               if ((status_byte & 1) == 1)\r
-                                                                                       second_byte = *(lpDIBBits++);\r
-                                                                               bits += status_byte;\r
-                                                                               break;\r
-                                                                       };\r
-                                                               } else {\r
-                                                                       BYTE *sline = iter.GetRow(scanline);\r
-                                                                       second_byte = *(lpDIBBits++);\r
-                                                                       for (unsigned i = 0; i < status_byte; i++) {\r
-                                                                               if ((DWORD)bits<info.dwEffWidth){\r
-                                                                                       *(sline + bits) = second_byte;\r
-                                                                                       bits++;\r
-                                                                               } else {\r
-                                                                                       bContinue = FALSE; //don't delete: we are in memory, it is not as with files\r
-                                                                                       break;\r
-                                                                               }\r
-                                                                       }\r
-                                                               }\r
-                                                       }\r
-                                               }\r
-                                               break;\r
-                                       default :\r
-                                               {\r
-                                                       // "compression type not supported";\r
-                                                       GlobalUnlock(lpVoid);\r
-                                                       return false;\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               } else {\r
-                       //normal bitmap (not compressed)\r
-                       memcpy(pDib,lpVoid,GetSize());\r
-               }\r
-\r
-               GlobalUnlock(lpVoid);\r
-\r
-               if (bTopDownDib) Flip();\r
-\r
-               return true;\r
-       }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Transfer the image in a  bitmap handle\r
- * \param hdc: target device context (the screen, usually)\r
- * \return bitmap handle, or NULL if an error occurs.\r
- */\r
-HBITMAP CxImage::MakeBitmap(HDC hdc)\r
-{\r
-       if (!pDib)\r
-               return NULL;\r
-\r
-       if (!hdc){\r
-               // this call to CreateBitmap doesn't create a DIB <jaslet>\r
-               // // Create a device-independent bitmap <CSC>\r
-               //  return CreateBitmap(head.biWidth,head.biHeight,     1, head.biBitCount, GetBits());\r
-               // use instead this code\r
-               HDC hMemDC = CreateCompatibleDC(NULL);\r
-               LPVOID pBit32;\r
-               HBITMAP bmp = CreateDIBSection(hMemDC,(LPBITMAPINFO)pDib,DIB_RGB_COLORS, &pBit32, NULL, 0);\r
-               if (pBit32) memcpy(pBit32, GetBits(), head.biSizeImage);\r
-               DeleteDC(hMemDC);\r
-               return bmp;\r
-       }\r
-\r
-       // this single line seems to work very well\r
-       //HBITMAP bmp = CreateDIBitmap(hdc, (LPBITMAPINFOHEADER)pDib, CBM_INIT,\r
-       //      GetBits(), (LPBITMAPINFO)pDib, DIB_RGB_COLORS);\r
-       // this alternative works also with _WIN32_WCE\r
-       LPVOID pBit32;\r
-       HBITMAP bmp = CreateDIBSection(hdc, (LPBITMAPINFO)pDib, DIB_RGB_COLORS, &pBit32, NULL, 0);\r
-       if (pBit32) memcpy(pBit32, GetBits(), head.biSizeImage);\r
-\r
-       return bmp;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Bitmap resource constructor\r
- * \param hbmp : bitmap resource handle\r
- * \param hpal : (optional) palette, useful for 8bpp DC \r
- * \return true if everything is ok\r
- */\r
-bool CxImage::CreateFromHBITMAP(HBITMAP hbmp, HPALETTE hpal)\r
-{\r
-       if (!Destroy())\r
-               return false;\r
-\r
-       if (hbmp) { \r
-        BITMAP bm;\r
-               // get informations about the bitmap\r
-        GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm);\r
-               // create the image\r
-        if (!Create(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, 0))\r
-                       return false;\r
-               // create a device context for the bitmap\r
-        HDC dc = ::GetDC(NULL);\r
-               if (!dc)\r
-                       return false;\r
-\r
-               if (hpal){\r
-                       SelectObject(dc,hpal); //the palette you should get from the user or have a stock one\r
-                       RealizePalette(dc);\r
-               }\r
-\r
-               // copy the pixels\r
-        if (GetDIBits(dc, hbmp, 0, head.biHeight, info.pImage,\r
-                       (LPBITMAPINFO)pDib, DIB_RGB_COLORS) == 0){ //replace &head with pDib <Wil Stark>\r
-            strcpy(info.szLastError,"GetDIBits failed");\r
-                       ::ReleaseDC(NULL, dc);\r
-                       return false;\r
-        }\r
-        ::ReleaseDC(NULL, dc);\r
-               return true;\r
-    }\r
-       return false;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * icon resource constructor\r
- * \param hico : icon resource handle\r
- * \return true if everything is ok\r
- * \author []; changes [Arlen Albert Keshabian]\r
- */\r
-#if !defined (_WIN32_WCE)\r
-bool CxImage::CreateFromHICON(HICON hico)\r
-{\r
-       if (!Destroy() || !hico)\r
-               return false;\r
-\r
-       bool l_bResult = true;\r
-\r
-       ICONINFO iinfo;\r
-       GetIconInfo(hico,&iinfo);\r
-\r
-       BITMAP l_Bitmap;\r
-       GetObject(iinfo.hbmColor, sizeof(BITMAP), &l_Bitmap);\r
-\r
-       if(l_Bitmap.bmBitsPixel == 32)\r
-       {\r
-               BITMAPINFO l_BitmapInfo;\r
-               l_BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);\r
-               l_BitmapInfo.bmiHeader.biWidth = l_Bitmap.bmWidth;\r
-               l_BitmapInfo.bmiHeader.biHeight = l_Bitmap.bmHeight;\r
-               l_BitmapInfo.bmiHeader.biPlanes = l_Bitmap.bmPlanes;\r
-               l_BitmapInfo.bmiHeader.biBitCount = l_Bitmap.bmBitsPixel;\r
-               l_BitmapInfo.bmiHeader.biCompression = BI_RGB;\r
-\r
-               RGBQUAD *l_pRawBytes = new RGBQUAD[l_Bitmap.bmWidth * l_Bitmap.bmHeight];\r
-\r
-               HDC dc = ::GetDC(NULL);\r
-\r
-               if(dc)\r
-               {\r
-                       if(GetDIBits(dc, iinfo.hbmColor, 0, l_Bitmap.bmHeight, l_pRawBytes, &l_BitmapInfo, DIB_RGB_COLORS))\r
-                               l_bResult = CreateFromArray((BYTE*)l_pRawBytes, l_Bitmap.bmWidth, l_Bitmap.bmHeight, l_Bitmap.bmBitsPixel, l_Bitmap.bmWidthBytes, false);\r
-                       else\r
-                               l_bResult = false;\r
-\r
-                       ::ReleaseDC(NULL, dc);\r
-               }\r
-               else\r
-                       l_bResult = false;\r
-\r
-               delete [] l_pRawBytes;\r
-       }\r
-       else\r
-       {\r
-               l_bResult = CreateFromHBITMAP(iinfo.hbmColor);\r
-#if CXIMAGE_SUPPORT_ALPHA\r
-               if(l_bResult)\r
-               {\r
-                       CxImage mask;\r
-                       mask.CreateFromHBITMAP(iinfo.hbmMask);\r
-                       mask.GrayScale();\r
-                       mask.Negative();\r
-                       AlphaSet(mask);\r
-               }\r
-#endif\r
-       }\r
-\r
-       DeleteObject(iinfo.hbmColor); //<Sims>\r
-       DeleteObject(iinfo.hbmMask);  //<Sims>\r
-       \r
-       return l_bResult;\r
-}\r
-#endif //_WIN32_WCE\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImage::Draw(HDC hdc, const RECT& rect, RECT* pClipRect, bool bSmooth)\r
-{\r
-       return Draw(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pClipRect,bSmooth);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Draws the image in the specified device context, with support for alpha channel, alpha palette, transparency, opacity.\r
- * \param hdc : destination device context\r
- * \param x,y : (optional) offset\r
- * \param cx,cy : (optional) size.\r
- *                 - If cx or cy are not specified (or less than 0), the normal width or height will be used\r
- *                 - If cx or cy are different than width or height, the image will be stretched\r
- *\r
- * \param pClipRect : limit the drawing operations inside a given rectangle in the output device context.\r
- * \param bSmooth : activates a bilinear filter that will enhance the appearence for zommed pictures.\r
- *                   Quite slow. Needs CXIMAGE_SUPPORT_INTERPOLATION.\r
- * \return true if everything is ok\r
- */\r
-long CxImage::Draw(HDC hdc, long x, long y, long cx, long cy, RECT* pClipRect, bool bSmooth)\r
-{\r
-       if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;\r
-\r
-       if (cx < 0) cx = head.biWidth;\r
-       if (cy < 0) cy = head.biHeight;\r
-       bool bTransparent = info.nBkgndIndex >= 0;\r
-       bool bAlpha = pAlpha != 0;\r
-\r
-       //required for MM_ANISOTROPIC, MM_HIENGLISH, and similar modes [Greg Peatfield]\r
-       int hdc_Restore = ::SaveDC(hdc);\r
-       if (!hdc_Restore) \r
-               return 0;\r
-\r
-#if !defined (_WIN32_WCE)\r
-       RECT mainbox; // (experimental) \r
-       if (pClipRect){\r
-               GetClipBox(hdc,&mainbox);\r
-               HRGN rgn = CreateRectRgnIndirect(pClipRect);\r
-               ExtSelectClipRgn(hdc,rgn,RGN_AND);\r
-               DeleteObject(rgn);\r
-       }\r
-#endif\r
-\r
-       //find the smallest area to paint\r
-       RECT clipbox,paintbox;\r
-       GetClipBox(hdc,&clipbox);\r
-\r
-       paintbox.top = min(clipbox.bottom,max(clipbox.top,y));\r
-       paintbox.left = min(clipbox.right,max(clipbox.left,x));\r
-       paintbox.right = max(clipbox.left,min(clipbox.right,x+cx));\r
-       paintbox.bottom = max(clipbox.top,min(clipbox.bottom,y+cy));\r
-\r
-       long destw = paintbox.right - paintbox.left;\r
-       long desth = paintbox.bottom - paintbox.top;\r
-\r
-       if (!(bTransparent || bAlpha || info.bAlphaPaletteEnabled)){\r
-               if (cx==head.biWidth && cy==head.biHeight){ //NORMAL\r
-#if !defined (_WIN32_WCE)\r
-                       SetStretchBltMode(hdc,COLORONCOLOR);\r
-#endif\r
-                       SetDIBitsToDevice(hdc, x, y, cx, cy, 0, 0, 0, cy,\r
-                                               info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS);\r
-               } else { //STRETCH\r
-                       //pixel informations\r
-                       RGBQUAD c={0,0,0,0};\r
-                       //Preparing Bitmap Info\r
-                       BITMAPINFO bmInfo;\r
-                       memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));\r
-                       bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);\r
-                       bmInfo.bmiHeader.biWidth=destw;\r
-                       bmInfo.bmiHeader.biHeight=desth;\r
-                       bmInfo.bmiHeader.biPlanes=1;\r
-                       bmInfo.bmiHeader.biBitCount=24;\r
-                       BYTE *pbase;    //points to the final dib\r
-                       BYTE *pdst;             //current pixel from pbase\r
-                       BYTE *ppix;             //current pixel from image\r
-                       //get the background\r
-                       HDC TmpDC=CreateCompatibleDC(hdc);\r
-                       HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);\r
-                       HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);\r
-\r
-                       if (pbase){\r
-                               long xx,yy;\r
-                               long sx,sy;\r
-                               float dx,dy;\r
-                               BYTE *psrc;\r
-\r
-                               long ew = ((((24 * destw) + 31) / 32) * 4);\r
-                               long ymax = paintbox.bottom;\r
-                               long xmin = paintbox.left;\r
-                               float fx=(float)head.biWidth/(float)cx;\r
-                               float fy=(float)head.biHeight/(float)cy;\r
-\r
-                               for(yy=0;yy<desth;yy++){\r
-                                       dy = head.biHeight-(ymax-yy-y)*fy;\r
-                                       sy = max(0L,(long)floor(dy));\r
-                                       psrc = info.pImage+sy*info.dwEffWidth;\r
-                                       pdst = pbase+yy*ew;\r
-                                       for(xx=0;xx<destw;xx++){\r
-                                               dx = (xx+xmin-x)*fx;\r
-                                               sx = max(0L,(long)floor(dx));\r
-#if CXIMAGE_SUPPORT_INTERPOLATION\r
-                                               if (bSmooth){\r
-                                                       if (fx > 1 && fy > 1) { \r
-                                                               c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
-                                                       } else { \r
-                                                               c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
-                                                       } \r
-                                               } else\r
-#endif //CXIMAGE_SUPPORT_INTERPOLATION\r
-                                               {\r
-                                                       if (head.biClrUsed){\r
-                                                               c=GetPaletteColor(GetPixelIndex(sx,sy));\r
-                                                       } else {\r
-                                                               ppix = psrc + sx*3;\r
-                                                               c.rgbBlue = *ppix++;\r
-                                                               c.rgbGreen= *ppix++;\r
-                                                               c.rgbRed  = *ppix;\r
-                                                       }\r
-                                               }\r
-                                               *pdst++=c.rgbBlue;\r
-                                               *pdst++=c.rgbGreen;\r
-                                               *pdst++=c.rgbRed;\r
-                                       }\r
-                               }\r
-                       }\r
-                       //paint the image & cleanup\r
-                       SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0);\r
-                       DeleteObject(SelectObject(TmpDC,TmpObj));\r
-                       DeleteDC(TmpDC);\r
-               }\r
-       } else {        // draw image with transparent/alpha blending\r
-       //////////////////////////////////////////////////////////////////\r
-               //Alpha blend - Thanks to Florian Egel\r
-\r
-               //pixel informations\r
-               RGBQUAD c={0,0,0,0};\r
-               RGBQUAD ct = GetTransColor();\r
-               long* pc = (long*)&c;\r
-               long* pct= (long*)&ct;\r
-               long cit = GetTransIndex();\r
-               long ci = 0;\r
-\r
-               //Preparing Bitmap Info\r
-               BITMAPINFO bmInfo;\r
-               memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));\r
-               bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);\r
-               bmInfo.bmiHeader.biWidth=destw;\r
-               bmInfo.bmiHeader.biHeight=desth;\r
-               bmInfo.bmiHeader.biPlanes=1;\r
-               bmInfo.bmiHeader.biBitCount=24;\r
-\r
-               BYTE *pbase;    //points to the final dib\r
-               BYTE *pdst;             //current pixel from pbase\r
-               BYTE *ppix;             //current pixel from image\r
-\r
-               //get the background\r
-               HDC TmpDC=CreateCompatibleDC(hdc);\r
-               HBITMAP TmpBmp=CreateDIBSection(hdc,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);\r
-               HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);\r
-               BitBlt(TmpDC,0,0,destw,desth,hdc,paintbox.left,paintbox.top,SRCCOPY);\r
-\r
-               if (pbase){\r
-                       long xx,yy,alphaoffset,ix,iy;\r
-                       BYTE a,a1,*psrc;\r
-                       long ew = ((((24 * destw) + 31) / 32) * 4);\r
-                       long ymax = paintbox.bottom;\r
-                       long xmin = paintbox.left;\r
-\r
-                       if (cx!=head.biWidth || cy!=head.biHeight){\r
-                               //STRETCH\r
-                               float fx=(float)head.biWidth/(float)cx;\r
-                               float fy=(float)head.biHeight/(float)cy;\r
-                               float dx,dy;\r
-                               long sx,sy;\r
-                               \r
-                               for(yy=0;yy<desth;yy++){\r
-                                       dy = head.biHeight-(ymax-yy-y)*fy;\r
-                                       sy = max(0L,(long)floor(dy));\r
-\r
-                                       alphaoffset = sy*head.biWidth;\r
-                                       pdst = pbase + yy*ew;\r
-                                       psrc = info.pImage + sy*info.dwEffWidth;\r
-\r
-                                       for(xx=0;xx<destw;xx++){\r
-                                               dx = (xx+xmin-x)*fx;\r
-                                               sx = max(0L,(long)floor(dx));\r
-\r
-                                               if (bAlpha) a=pAlpha[alphaoffset+sx]; else a=255;\r
-                                               a =(BYTE)((a*(1+info.nAlphaMax))>>8);\r
-\r
-                                               if (head.biClrUsed){\r
-                                                       ci = GetPixelIndex(sx,sy);\r
-#if CXIMAGE_SUPPORT_INTERPOLATION\r
-                                                       if (bSmooth){\r
-                                                               if (fx > 1 && fy > 1) { \r
-                                                                       c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
-                                                               } else { \r
-                                                                       c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
-                                                               } \r
-                                                       } else\r
-#endif //CXIMAGE_SUPPORT_INTERPOLATION\r
-                                                       {\r
-                                                               c = GetPaletteColor(GetPixelIndex(sx,sy));\r
-                                                       }\r
-                                                       if (info.bAlphaPaletteEnabled){\r
-                                                               a = (BYTE)((a*(1+c.rgbReserved))>>8);\r
-                                                       }\r
-                                               } else {\r
-#if CXIMAGE_SUPPORT_INTERPOLATION\r
-                                                       if (bSmooth){\r
-                                                               if (fx > 1 && fy > 1) { \r
-                                                                       c = GetAreaColorInterpolated(dx - 0.5f, dy - 0.5f, fx, fy, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
-                                                               } else { \r
-                                                                       c = GetPixelColorInterpolated(dx - 0.5f, dy - 0.5f, CxImage::IM_BILINEAR, CxImage::OM_REPEAT); \r
-                                                               } \r
-                                                       } else\r
-#endif //CXIMAGE_SUPPORT_INTERPOLATION\r
-                                                       {\r
-                                                               ppix = psrc + sx*3;\r
-                                                               c.rgbBlue = *ppix++;\r
-                                                               c.rgbGreen= *ppix++;\r
-                                                               c.rgbRed  = *ppix;\r
-                                                       }\r
-                                               }\r
-                                               //if (*pc!=*pct || !bTransparent){\r
-                                               //if ((head.biClrUsed && ci!=cit) || ((!head.biClrUsed||bSmooth) && *pc!=*pct) || !bTransparent){\r
-                                               if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){\r
-                                                       // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication\r
-                                                       if (a == 0) {                   // Transparent, retain dest \r
-                                                               pdst+=3; \r
-                                                       } else if (a == 255) {  // opaque, ignore dest \r
-                                                               *pdst++= c.rgbBlue; \r
-                                                               *pdst++= c.rgbGreen; \r
-                                                               *pdst++= c.rgbRed; \r
-                                                       } else {                                // semi transparent \r
-                                                               a1=(BYTE)~a;\r
-                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8); \r
-                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8); \r
-                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbRed)>>8); \r
-                                                       } \r
-                                               } else {\r
-                                                       pdst+=3;\r
-                                               }\r
-                                       }\r
-                               }\r
-                       } else {\r
-                               //NORMAL\r
-                               iy=head.biHeight-ymax+y;\r
-                               for(yy=0;yy<desth;yy++,iy++){\r
-                                       alphaoffset=iy*head.biWidth;\r
-                                       ix=xmin-x;\r
-                                       pdst=pbase+yy*ew;\r
-                                       ppix=info.pImage+iy*info.dwEffWidth+ix*3;\r
-                                       for(xx=0;xx<destw;xx++,ix++){\r
-\r
-                                               if (bAlpha) a=pAlpha[alphaoffset+ix]; else a=255;\r
-                                               a = (BYTE)((a*(1+info.nAlphaMax))>>8);\r
-\r
-                                               if (head.biClrUsed){\r
-                                                       ci = GetPixelIndex(ix,iy);\r
-                                                       c = GetPaletteColor((BYTE)ci);\r
-                                                       if (info.bAlphaPaletteEnabled){\r
-                                                               a = (BYTE)((a*(1+c.rgbReserved))>>8);\r
-                                                       }\r
-                                               } else {\r
-                                                       c.rgbBlue = *ppix++;\r
-                                                       c.rgbGreen= *ppix++;\r
-                                                       c.rgbRed  = *ppix++;\r
-                                               }\r
-\r
-                                               //if (*pc!=*pct || !bTransparent){\r
-                                               if ((head.biClrUsed && ci!=cit) || (!head.biClrUsed && *pc!=*pct) || !bTransparent){\r
-                                                       // DJT, assume many pixels are fully transparent or opaque and thus avoid multiplication\r
-                                                       if (a == 0) {                   // Transparent, retain dest \r
-                                                               pdst+=3; \r
-                                                       } else if (a == 255) {  // opaque, ignore dest \r
-                                                               *pdst++= c.rgbBlue; \r
-                                                               *pdst++= c.rgbGreen; \r
-                                                               *pdst++= c.rgbRed; \r
-                                                       } else {                                // semi transparent \r
-                                                               a1=(BYTE)~a;\r
-                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8); \r
-                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8); \r
-                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbRed)>>8); \r
-                                                       } \r
-                                               } else {\r
-                                                       pdst+=3;\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               //paint the image & cleanup\r
-               SetDIBitsToDevice(hdc,paintbox.left,paintbox.top,destw,desth,0,0,0,desth,pbase,&bmInfo,0);\r
-               DeleteObject(SelectObject(TmpDC,TmpObj));\r
-               DeleteDC(TmpDC);\r
-       }\r
-\r
-#if !defined (_WIN32_WCE)\r
-       if (pClipRect){  // (experimental)\r
-               HRGN rgn = CreateRectRgnIndirect(&mainbox);\r
-               ExtSelectClipRgn(hdc,rgn,RGN_OR);\r
-               DeleteObject(rgn);\r
-       }\r
-#endif\r
-\r
-       ::RestoreDC(hdc,hdc_Restore);\r
-       return 1;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImage::Draw2(HDC hdc, const RECT& rect)\r
-{\r
-       return Draw2(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Draws (stretch) the image with single transparency support\r
- * \param hdc : destination device context\r
- * \param x,y : (optional) offset\r
- * \param cx,cy : (optional) size.\r
- *                 - If cx or cy are not specified (or less than 0), the normal width or height will be used\r
- *                 - If cx or cy are different than width or height, the image will be stretched\r
- *\r
- * \return true if everything is ok\r
- */\r
-long CxImage::Draw2(HDC hdc, long x, long y, long cx, long cy)\r
-{\r
-       if((pDib==0)||(hdc==0)||(cx==0)||(cy==0)||(!info.bEnabled)) return 0;\r
-       if (cx < 0) cx = head.biWidth;\r
-       if (cy < 0) cy = head.biHeight;\r
-       bool bTransparent = (info.nBkgndIndex >= 0);\r
-\r
-       //required for MM_ANISOTROPIC, MM_HIENGLISH, and similar modes [Greg Peatfield]\r
-       int hdc_Restore = ::SaveDC(hdc);\r
-       if (!hdc_Restore) \r
-               return 0;\r
-\r
-       if (!bTransparent){\r
-#if !defined (_WIN32_WCE)\r
-               SetStretchBltMode(hdc,COLORONCOLOR);    \r
-#endif\r
-               StretchDIBits(hdc, x, y, cx, cy, 0, 0, head.biWidth, head.biHeight,\r
-                                               info.pImage,(BITMAPINFO*)pDib, DIB_RGB_COLORS,SRCCOPY);\r
-       } else {\r
-               // draw image with transparent background\r
-               const int safe = 0; // or else GDI fails in the following - sometimes \r
-               RECT rcDst = {x+safe, y+safe, x+cx, y+cy};\r
-               if (RectVisible(hdc, &rcDst)){\r
-               /////////////////////////////////////////////////////////////////\r
-                       // True Mask Method - Thanks to Paul Reynolds and Ron Gery\r
-                       int nWidth = head.biWidth;\r
-                       int nHeight = head.biHeight;\r
-                       // Create two memory dcs for the image and the mask\r
-                       HDC dcImage=CreateCompatibleDC(hdc);\r
-                       HDC dcTrans=CreateCompatibleDC(hdc);\r
-                       // Select the image into the appropriate dc\r
-                       HBITMAP bm = CreateCompatibleBitmap(hdc, nWidth, nHeight);\r
-                       HBITMAP pOldBitmapImage = (HBITMAP)SelectObject(dcImage,bm);\r
-#if !defined (_WIN32_WCE)\r
-                       SetStretchBltMode(dcImage,COLORONCOLOR);\r
-#endif\r
-                       StretchDIBits(dcImage, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,\r
-                                                       info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS,SRCCOPY);\r
-\r
-                       // Create the mask bitmap\r
-                       HBITMAP bitmapTrans = CreateBitmap(nWidth, nHeight, 1, 1, NULL);\r
-                       // Select the mask bitmap into the appropriate dc\r
-                       HBITMAP pOldBitmapTrans = (HBITMAP)SelectObject(dcTrans, bitmapTrans);\r
-                       // Build mask based on transparent colour\r
-                       RGBQUAD rgbBG;\r
-                       if (head.biBitCount<24) rgbBG = GetPaletteColor((BYTE)info.nBkgndIndex);\r
-                       else rgbBG = info.nBkgndColor;\r
-                       COLORREF crColour = RGB(rgbBG.rgbRed, rgbBG.rgbGreen, rgbBG.rgbBlue);\r
-                       COLORREF crOldBack = SetBkColor(dcImage,crColour);\r
-                       BitBlt(dcTrans,0, 0, nWidth, nHeight, dcImage, 0, 0, SRCCOPY);\r
-\r
-                       // Do the work - True Mask method - cool if not actual display\r
-                       StretchBlt(hdc,x, y,cx,cy, dcImage, 0, 0, nWidth, nHeight, SRCINVERT);\r
-                       StretchBlt(hdc,x, y,cx,cy, dcTrans, 0, 0, nWidth, nHeight, SRCAND);\r
-                       StretchBlt(hdc,x, y,cx,cy, dcImage, 0, 0, nWidth, nHeight, SRCINVERT);\r
-\r
-                       // Restore settings\r
-                       SelectObject(dcImage,pOldBitmapImage);\r
-                       SelectObject(dcTrans,pOldBitmapTrans);\r
-                       SetBkColor(hdc,crOldBack);\r
-                       DeleteObject( bitmapTrans );  // RG 29/01/2002\r
-                       DeleteDC(dcImage);\r
-                       DeleteDC(dcTrans);\r
-                       DeleteObject(bm);\r
-               }\r
-       }\r
-       ::RestoreDC(hdc,hdc_Restore);\r
-       return 1;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImage::Stretch(HDC hdc, const RECT& rect, DWORD dwRop)\r
-{\r
-       return Stretch(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, dwRop);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Stretch the image. Obsolete: use Draw() or Draw2()\r
- * \param hdc : destination device context\r
- * \param xoffset,yoffset : (optional) offset\r
- * \param xsize,ysize : size.\r
- * \param dwRop : raster operation code (see BitBlt documentation)\r
- * \return true if everything is ok\r
- */\r
-long CxImage::Stretch(HDC hdc, long xoffset, long yoffset, long xsize, long ysize, DWORD dwRop)\r
-{\r
-       if((pDib)&&(hdc)) {\r
-               //palette must be correctly filled\r
-#if !defined (_WIN32_WCE)\r
-               SetStretchBltMode(hdc,COLORONCOLOR);    \r
-#endif\r
-               StretchDIBits(hdc, xoffset, yoffset,\r
-                                       xsize, ysize, 0, 0, head.biWidth, head.biHeight,\r
-                                       info.pImage,(BITMAPINFO*)pDib,DIB_RGB_COLORS,dwRop);\r
-               return 1;\r
-       }\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-/**\r
- * Tiles the device context in the specified rectangle with the image.\r
- * \param hdc : destination device context\r
- * \param rc : tiled rectangle in the output device context\r
- * \return true if everything is ok\r
- */\r
-long CxImage::Tile(HDC hdc, RECT *rc)\r
-{\r
-       if((pDib)&&(hdc)&&(rc)) {\r
-               int w = rc->right - rc->left;\r
-               int h = rc->bottom - rc->top;\r
-               int x,y,z;\r
-               int bx=head.biWidth;\r
-               int by=head.biHeight;\r
-               for (y = 0 ; y < h ; y += by){\r
-                       if ((y+by)>h) by=h-y;\r
-                       z=bx;\r
-                       for (x = 0 ; x < w ; x += z){\r
-                               if ((x+z)>w) z=w-x;\r
-                               RECT r = {rc->left + x,rc->top + y,rc->left + x + z,rc->top + y + by};\r
-                               Draw(hdc,rc->left + x, rc->top + y,-1,-1,&r);\r
-                       }\r
-               }\r
-               return 1;\r
-       }\r
-       return 0;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// For UNICODE support: char -> TCHAR\r
-long CxImage::DrawString(HDC hdc, long x, long y, const TCHAR* text, RGBQUAD color, const TCHAR* font, long lSize, long lWeight, BYTE bItalic, BYTE bUnderline, bool bSetAlpha)\r
-//long CxImage::DrawString(HDC hdc, long x, long y, const char* text, RGBQUAD color, const char* font, long lSize, long lWeight, BYTE bItalic, BYTE bUnderline, bool bSetAlpha)\r
-{\r
-       if (IsValid()){\r
-               //get the background\r
-               HDC pDC;\r
-               if (hdc) pDC=hdc; else pDC = ::GetDC(0);\r
-               if (pDC==NULL) return 0;\r
-               HDC TmpDC=CreateCompatibleDC(pDC);\r
-               if (hdc==NULL) ::ReleaseDC(0, pDC);\r
-               if (TmpDC==NULL) return 0;\r
-               //choose the font\r
-               HFONT m_Font;\r
-               LOGFONT* m_pLF;\r
-               m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));\r
-               _tcsncpy(m_pLF->lfFaceName,font,31);    // For UNICODE support\r
-               //strncpy(m_pLF->lfFaceName,font,31);\r
-               m_pLF->lfHeight=lSize;\r
-               m_pLF->lfWeight=lWeight;\r
-               m_pLF->lfItalic=bItalic;\r
-               m_pLF->lfUnderline=bUnderline;\r
-               m_Font=CreateFontIndirect(m_pLF);\r
-               //select the font in the dc\r
-               HFONT pOldFont=NULL;\r
-               if (m_Font)\r
-                       pOldFont = (HFONT)SelectObject(TmpDC,m_Font);\r
-               else\r
-                       pOldFont = (HFONT)SelectObject(TmpDC,GetStockObject(DEFAULT_GUI_FONT));\r
-\r
-               //Set text color\r
-               SetTextColor(TmpDC,RGB(255,255,255));\r
-               SetBkColor(TmpDC,RGB(0,0,0));\r
-               //draw the text\r
-               SetBkMode(TmpDC,OPAQUE);\r
-               //Set text position;\r
-               RECT pos = {0,0,0,0};\r
-               //long len = (long)strlen(text);\r
-               long len = (long)_tcslen(text); // For UNICODE support\r
-               ::DrawText(TmpDC,text,len,&pos,DT_CALCRECT);\r
-               pos.right+=pos.bottom; //for italics\r
-\r
-               //Preparing Bitmap Info\r
-               long width=pos.right;\r
-               long height=pos.bottom;\r
-               BITMAPINFO bmInfo;\r
-               memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));\r
-               bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);\r
-               bmInfo.bmiHeader.biWidth=width;\r
-               bmInfo.bmiHeader.biHeight=height;\r
-               bmInfo.bmiHeader.biPlanes=1;\r
-               bmInfo.bmiHeader.biBitCount=24;\r
-               BYTE *pbase; //points to the final dib\r
-\r
-               HBITMAP TmpBmp=CreateDIBSection(TmpDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);\r
-               HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);\r
-               memset(pbase,0,height*((((24 * width) + 31) / 32) * 4));\r
-\r
-               ::DrawText(TmpDC,text,len,&pos,0);\r
-\r
-               CxImage itext;\r
-               itext.CreateFromHBITMAP(TmpBmp);\r
-\r
-               y=head.biHeight-y-1;\r
-               for (long ix=0;ix<width;ix++){\r
-                       for (long iy=0;iy<height;iy++){\r
-                               if (itext.GetPixelColor(ix,iy).rgbBlue) SetPixelColor(x+ix,y+iy,color,bSetAlpha);\r
-                       }\r
-               }\r
-\r
-               //cleanup\r
-               if (pOldFont) SelectObject(TmpDC,pOldFont);\r
-               DeleteObject(m_Font);\r
-               free(m_pLF);\r
-               DeleteObject(SelectObject(TmpDC,TmpObj));\r
-               DeleteDC(TmpDC);\r
-       }\r
-\r
-       return 1;\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-// <VATI>\r
-long CxImage::DrawStringEx(HDC hdc, long x, long y, CXTEXTINFO *pTextType, bool bSetAlpha )\r
-{\r
-       if (!IsValid())\r
-        return -1;\r
-    \r
-       //get the background\r
-       HDC pDC;\r
-       if (hdc) pDC=hdc; else pDC = ::GetDC(0);\r
-       if (pDC==NULL) return 0;\r
-       HDC TmpDC=CreateCompatibleDC(pDC);\r
-       if (hdc==NULL) ::ReleaseDC(0, pDC);\r
-       if (TmpDC==NULL) return 0;\r
-\r
-    //choose the font\r
-       HFONT m_Font;\r
-    m_Font=CreateFontIndirect( &pTextType->lfont );\r
-    \r
-    // get colors in RGBQUAD\r
-    RGBQUAD p_forecolor = RGBtoRGBQUAD(pTextType->fcolor);\r
-    RGBQUAD p_backcolor = RGBtoRGBQUAD(pTextType->bcolor);\r
-\r
-    // check alignment and re-set default if necessary\r
-    if ( pTextType->align != DT_CENTER &&\r
-         pTextType->align != DT_LEFT &&\r
-         pTextType->align != DT_RIGHT )\r
-        pTextType->align = DT_CENTER;\r
-\r
-    // check rounding radius and re-set default if necessary\r
-    if ( pTextType->b_round > 50 )\r
-        pTextType->b_round = 10;\r
-\r
-    // check opacity and re-set default if necessary\r
-    if ( pTextType->b_opacity > 1. || pTextType->b_opacity < .0 )\r
-        pTextType->b_opacity = 0.;\r
-\r
-    //select the font in the dc\r
-       HFONT pOldFont=NULL;\r
-       if (m_Font)\r
-               pOldFont = (HFONT)SelectObject(TmpDC,m_Font);\r
-       else\r
-               pOldFont = (HFONT)SelectObject(TmpDC,GetStockObject(DEFAULT_GUI_FONT));\r
-\r
-       //Set text color\r
-    SetTextColor(TmpDC,RGB(255,255,255));\r
-       SetBkColor(TmpDC,RGB(0,0,0));\r
-       SetBkMode(TmpDC,OPAQUE);\r
-       //Set text position;\r
-       RECT pos = {0,0,0,0};\r
-       \r
-    // get text length and number of lines\r
-    long i=0, numlines=1, len=(long)_tcsclen(pTextType->text);\r
-    while (i<len)\r
-    {\r
-        if ( pTextType->text[i++]==13 )\r
-            numlines++;\r
-    }\r
-\r
-       ::DrawText(TmpDC, pTextType->text, len, &pos, /*DT_EDITCONTROL|DT_EXTERNALLEADING|*/DT_NOPREFIX | DT_CALCRECT );\r
-\r
-    // increase only if it's really italics, and only one line height\r
-       if ( pTextType->lfont.lfItalic ) \r
-        pos.right += pos.bottom/2/numlines; \r
-\r
-    // background frame and rounding radius\r
-       int frame = 0, roundR = 0;\r
-    if ( pTextType->opaque )\r
-    {\r
-        roundR= (int)(pos.bottom/numlines * pTextType->b_round / 100 ) ;\r
-        frame = (int)(/*3.5 + */0.29289*roundR ) ;\r
-        pos.right += pos.bottom/numlines/3 ; // JUST FOR BEAUTY\r
-    }\r
-\r
-       //Preparing Bitmap Info\r
-       long width=pos.right +frame*2;\r
-       long height=pos.bottom +frame*2;\r
-       BITMAPINFO bmInfo;\r
-       memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));\r
-       bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);\r
-       bmInfo.bmiHeader.biWidth=width;\r
-       bmInfo.bmiHeader.biHeight=height;\r
-       bmInfo.bmiHeader.biPlanes=1;\r
-       bmInfo.bmiHeader.biBitCount=24;\r
-       BYTE *pbase; //points to the final dib\r
-\r
-       HBITMAP TmpBmp=CreateDIBSection(TmpDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);\r
-       HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);\r
-       memset(pbase,0,height*((((24 * width) + 31) / 32) * 4));\r
-\r
-       ::DrawText(TmpDC,pTextType->text,len, &pos, /*DT_EDITCONTROL|DT_EXTERNALLEADING|*/DT_NOPREFIX| pTextType->align );\r
-    \r
-       CxImage itext;\r
-       itext.CreateFromHBITMAP(TmpBmp);\r
-    y=head.biHeight-y-1;\r
-\r
-       itext.Negative();\r
-\r
-       if (pTextType->smooth==FALSE){\r
-               itext.Threshold(128);\r
-       } else {\r
-               //itext.TextBlur();\r
-       }\r
-\r
-    //move the insertion point according to alignment type\r
-    // DT_CENTER: cursor points to the center of text rectangle\r
-    // DT_RIGHT:  cursor points to right side end of text rectangle\r
-    // DT_LEFT:   cursor points to left end of text rectangle\r
-    if ( pTextType->align == DT_CENTER )\r
-        x -= width/2;\r
-    else if ( pTextType->align == DT_RIGHT )\r
-        x -= width;\r
-    if (x<0) x=0;\r
-    \r
-    //draw the background first, if it exists\r
-    long ix,iy;\r
-    if ( pTextType->opaque )\r
-    {\r
-        int ixf=0; \r
-        for (ix=0;ix<width;ix++)\r
-        {\r
-            if ( ix<=roundR )\r
-                ixf = (int)(.5+roundR-sqrt((float)(roundR*roundR-(ix-roundR)*(ix-roundR))));\r
-            else if ( ix>=width-roundR-1 )\r
-                ixf = (int)(.5+roundR-sqrt((float)(roundR*roundR-(width-1-ix-roundR)*(width-1-ix-roundR))));\r
-            else\r
-                ixf=0;\r
-\r
-            for (iy=0;iy<height;iy++)\r
-            {\r
-                if ( (ix<=roundR && ( iy > height-ixf-1 || iy < ixf )) ||\r
-                     (ix>=width-roundR-1 && ( iy > height-ixf-1 || iy < ixf )) )\r
-                    continue;\r
-                else\r
-                    if ( pTextType->b_opacity > 0.0 && pTextType->b_opacity < 1.0 )\r
-                    {\r
-                        RGBQUAD bcolor, pcolor;\r
-                        // calculate a transition color from original image to background color:\r
-                        pcolor = GetPixelColor(x+ix,y+iy);\r
-                                               bcolor.rgbBlue = (unsigned char)(pTextType->b_opacity * pcolor.rgbBlue + (1.0-pTextType->b_opacity) * p_backcolor.rgbBlue );\r
-                        bcolor.rgbRed = (unsigned char)(pTextType->b_opacity * pcolor.rgbRed + (1.0-pTextType->b_opacity) * p_backcolor.rgbRed ) ;\r
-                        bcolor.rgbGreen = (unsigned char)(pTextType->b_opacity * pcolor.rgbGreen + (1.0-pTextType->b_opacity) * p_backcolor.rgbGreen ) ;\r
-                        bcolor.rgbReserved = 0;\r
-                        SetPixelColor(x+ix,y+iy,bcolor,bSetAlpha);\r
-                    }\r
-                    else\r
-                        SetPixelColor(x+ix,y+iy,p_backcolor,bSetAlpha);\r
-                       }\r
-               }\r
-    }\r
-\r
-    // draw the text itself\r
-    for (ix=0;ix<width;ix++)\r
-    {\r
-               for (iy=0;iy<height;iy++)\r
-        {\r
-                       RGBQUAD pcolor = GetPixelColor(x+ix,y+iy);\r
-                       RGBQUAD tcolor = itext.GetPixelColor(ix,iy);\r
-            if (tcolor.rgbBlue!=255){\r
-                               float a = tcolor.rgbBlue/255.0f;\r
-                               pcolor.rgbBlue  = (unsigned char)(a * (pcolor.rgbBlue  - p_forecolor.rgbBlue)  + p_forecolor.rgbBlue );\r
-                pcolor.rgbRed   = (unsigned char)(a * (pcolor.rgbRed   - p_forecolor.rgbRed)   + p_forecolor.rgbRed ) ;\r
-                pcolor.rgbGreen = (unsigned char)(a * (pcolor.rgbGreen - p_forecolor.rgbGreen) + p_forecolor.rgbGreen );\r
-                pcolor.rgbReserved = 0;\r
-                SetPixelColor(x+ix+frame,y+iy-frame,pcolor,bSetAlpha);\r
-              //SetPixelColor(x+ix+frame,y+iy-frame,p_forecolor,bSetAlpha);\r
-                       }\r
-               }\r
-       }\r
-\r
-       //cleanup\r
-    if (pOldFont) SelectObject(TmpDC,pOldFont);\r
-       DeleteObject(m_Font);\r
-       DeleteObject(SelectObject(TmpDC,TmpObj));\r
-       DeleteDC(TmpDC);\r
-       return 1;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////////////\r
-void CxImage::InitTextInfo( CXTEXTINFO *txt )\r
-{\r
-\r
-    memset( txt, 0, sizeof(CXTEXTINFO));\r
-    \r
-    // LOGFONT defaults\r
-    txt->lfont.lfHeight        = -36; \r
-    txt->lfont.lfCharSet       = EASTEUROPE_CHARSET; // just for Central-European users \r
-    txt->lfont.lfWeight        = FW_NORMAL;\r
-    txt->lfont.lfWidth         = 0; \r
-    txt->lfont.lfEscapement    = 0; \r
-    txt->lfont.lfOrientation   = 0; \r
-    txt->lfont.lfItalic        = FALSE; \r
-    txt->lfont.lfUnderline     = FALSE; \r
-    txt->lfont.lfStrikeOut     = FALSE; \r
-    txt->lfont.lfOutPrecision  = OUT_DEFAULT_PRECIS; \r
-    txt->lfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; \r
-    txt->lfont.lfQuality       = PROOF_QUALITY; \r
-    txt->lfont.lfPitchAndFamily= DEFAULT_PITCH | FF_DONTCARE ; \r
-    _stprintf( txt->lfont.lfFaceName, _T("Arial")); //use TCHAR mappings <Cesar M>\r
-\r
-    // initial colors\r
-    txt->fcolor = RGB( 255,255,160 );  // default foreground: light goldyellow\r
-    txt->bcolor = RGB(   0, 80,160 );  // default background: light blue\r
-\r
-    // background\r
-    txt->opaque    = TRUE;  // text has a non-transparent background;\r
-       txt->smooth    = TRUE;\r
-    txt->b_opacity = 0.0;   // default: opaque background\r
-    txt->b_outline = 0;     // default: no outline (OUTLINE NOT IMPLEMENTED AT THIS TIME)\r
-    txt->b_round   = 20;    // default: rounding radius is 20% of the rectangle height\r
-    // the text \r
-    _stprintf( txt->text, _T("Sample Text 01234õû")); // text use TCHAR mappings <Cesar M>\r
-    txt->align = DT_CENTER;\r
-    return;\r
-}\r
-\r
-#if CXIMAGE_SUPPORT_LAYERS\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImage::LayerDrawAll(HDC hdc, const RECT& rect, RECT* pClipRect, bool bSmooth)\r
-{\r
-       return LayerDrawAll(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pClipRect,bSmooth);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-long CxImage::LayerDrawAll(HDC hdc, long x, long y, long cx, long cy, RECT* pClipRect, bool bSmooth)\r
-{\r
-       long n=0;\r
-       CxImage* pLayer;\r
-       while(pLayer=GetLayer(n++)){\r
-               if (pLayer->Draw(hdc,x+pLayer->info.xOffset,y+pLayer->info.yOffset,cx,cy,pClipRect,bSmooth)==0)\r
-                       return 0;\r
-               if (pLayer->LayerDrawAll(hdc,x+pLayer->info.xOffset,y+pLayer->info.yOffset,cx,cy,pClipRect,bSmooth)==0)\r
-                       return 0;\r
-       }\r
-       return 1;\r
-}\r
-#endif //CXIMAGE_SUPPORT_LAYERS\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-#endif //CXIMAGE_SUPPORT_WINDOWS\r
-////////////////////////////////////////////////////////////////////////////////\r
+// xImaWnd.cpp : Windows functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 6.0.0 02/Feb/2008
+ */
+
+#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;           }
+};
+
+int BytesPerLine(int nWidth, int nBitsPerPixel)
+{
+    return ( (nWidth * nBitsPerPixel + 31) & (~31) ) / 8;
+}
+
+int NumColorEntries(int nBitsPerPixel, int nCompression, DWORD biClrUsed)
+{
+       int 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 <= (DWORD)nColors)
+               return biClrUsed;
+       
+       return nColors;
+}
+
+int GetDIBits(
+  HDC hdc,           // handle to DC
+  HBITMAP hbmp,      // handle to bitmap
+  UINT uStartScan,   // first scan line to set
+  UINT cScanLines,   // number of scan lines to copy
+  LPVOID lpvBits,    // array for bitmap bits
+  LPBITMAPINFO lpbi, // bitmap data buffer
+  UINT uUsage        // RGB or palette index
+)
+{
+       UINT    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
+////////////////////////////////////////////////////////////////////////////////
+long CxImage::Blt(HDC pDC, long x, long 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){
+                       BYTE* pDst=(BYTE*)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;
+
+       DWORD dwSize = GlobalSize(hMem);
+       if (!dwSize) return false;
+
+       BYTE *lpVoid;                                           //pointer to the bitmap
+       lpVoid = (BYTE *)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(lpVoid);
+                       return false;
+               }
+               //preserve DPI
+               SetXDPI((long)floor(head.biXPelsPerMeter * 254.0 / 10000.0 + 0.5));
+               SetYDPI((long)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
+                       DWORD bf[3];
+                       memcpy(bf,lpVoid+pHead->biSize,12);
+                       // transform into RGB
+                       Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)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
+                       int nColors = DibNumColors(pHead);
+                       if (bIsOldBmp) {
+                               /* get pointer to BITMAPCOREINFO (old style 1.x) */
+                               LPBITMAPCOREINFO lpbmc = (LPBITMAPCOREINFO)lpVoid;
+                               for (int 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 = (BYTE)0;
+                               }
+                       } else {
+                               /* get pointer to BITMAPINFO (new style 3.x) */
+                               LPBITMAPINFO lpbmi = (LPBITMAPINFO)lpVoid;
+                               for (int 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 = (BYTE)0;
+                               }
+                       }
+               }
+
+               // <Michael Gandyra>
+               DWORD dwCompression = pHead->biCompression;
+               // compressed bitmap ?
+               if(dwCompression!=BI_RGB || pHead->biBitCount==32 || pHead->biBitCount ==16) {
+                       // get the bitmap bits
+                       LPSTR lpDIBBits = (LPSTR)((BYTE*)pHead + *(DWORD*)pHead + (WORD)(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
+                                               DWORD bf[3];
+                                               memcpy(bf,lpVoid+pHead->biSize,12);
+                                               // transform into RGB
+                                               Bitfield2RGB(lpVoid+pHead->biSize+12,bf[0],bf[1],bf[2],(BYTE)pHead->biBitCount);
+                                       } else {
+                                               // "unknown compression";
+                                               GlobalUnlock(lpVoid);
+                                               return false;
+                                       }
+                               }
+                               break;
+                       case 16 :
+                               {
+                                       // get the bitfield masks
+                                       long offset=0;
+                                       DWORD 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:
+                                               {
+                                                       BYTE status_byte = 0;
+                                                       BYTE second_byte = 0;
+                                                       int scanline = 0;
+                                                       int 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
+                                                                                       BYTE delta_x;
+                                                                                       BYTE delta_y;
+                                                                                       delta_x = *(lpDIBBits++);
+                                                                                       delta_y = *(lpDIBBits++);
+                                                                                       // apply them
+                                                                                       bits       += delta_x / 2;
+                                                                                       scanline   += delta_y;
+                                                                                       break;
+                                                                               }
+                                                                       default :
+                                                                               second_byte = *(lpDIBBits++);
+                                                                               BYTE* sline = iter.GetRow(scanline);
+                                                                               for (int i = 0; i < status_byte; i++) {
+                                                                                       if ((BYTE*)(sline+bits) < (BYTE*)(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) = (BYTE)(second_byte & 0x0f)<<4;
+                                                                                                       else
+                                                                                                               *(sline + bits) = (BYTE)(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 :
+                                                                       {
+                                                                               BYTE* sline = iter.GetRow(scanline);
+                                                                               second_byte = *(lpDIBBits++);
+                                                                               for (unsigned i = 0; i < status_byte; i++) {
+                                                                                       if ((BYTE*)(sline+bits) < (BYTE*)(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) = (BYTE)(second_byte & 0x0f)<<4;
+                                                                                                       else
+                                                                                                               *(sline + bits) = (BYTE)(second_byte & 0xf0);
+                                                                                               }
+                                                                                       }
+                                                                                       low_nibble = !low_nibble;
+                                                                               }
+                                                                       }
+                                                                       break;
+                                                               };
+                                                       }
+                                               }
+                                               break;
+                                       case BI_RLE8 :
+                                               {
+                                                       BYTE status_byte = 0;
+                                                       BYTE second_byte = 0;
+                                                       int scanline = 0;
+                                                       int 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
+                                                                                       BYTE delta_x;
+                                                                                       BYTE delta_y;
+                                                                                       delta_x = *(lpDIBBits++);
+                                                                                       delta_y = *(lpDIBBits++);
+                                                                                       // apply them
+                                                                                       bits     += delta_x;
+                                                                                       scanline += delta_y;
+                                                                               }
+                                                                               break;
+                                                                       default :
+                                                                               int nNumBytes = sizeof(BYTE) * 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 {
+                                                                       BYTE *sline = iter.GetRow(scanline);
+                                                                       second_byte = *(lpDIBBits++);
+                                                                       for (unsigned i = 0; i < status_byte; i++) {
+                                                                               if ((DWORD)bits<info.dwEffWidth){
+                                                                                       *(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(lpVoid);
+                                                       return false;
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                       //normal bitmap (not compressed)
+                       memcpy(pDib,lpVoid,GetSize());
+               }
+
+               GlobalUnlock(lpVoid);
+
+               if (bTopDownDib) Flip();
+
+               return true;
+       }
+       return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Transfer the image in a  bitmap handle
+ * \param hdc: target device context (the screen, usually)
+ * \return bitmap handle, or NULL if an error occurs.
+ */
+HBITMAP CxImage::MakeBitmap(HDC hdc)
+{
+       if (!pDib)
+               return NULL;
+
+       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;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Bitmap resource constructor
+ * \param hbmp : bitmap resource handle
+ * \param hpal : (optional) palette, useful for 8bpp DC 
+ * \return true if everything is ok
+ */
+bool CxImage::CreateFromHBITMAP(HBITMAP hbmp, HPALETTE hpal)
+{
+       if (!Destroy())
+               return false;
+
+       if (hbmp) { 
+        BITMAP bm;
+               // get informations about the bitmap
+        GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm);
+               // 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
+ * \return true if everything is ok
+ * \author []; changes [Arlen Albert Keshabian]
+ */
+#if !defined (_WIN32_WCE)
+bool CxImage::CreateFromHICON(HICON hico)
+{
+       if (!Destroy() || !hico)
+               return false;
+
+       bool l_bResult = true;
+
+       ICONINFO iinfo;
+       GetIconInfo(hico,&iinfo);
+
+       BITMAP l_Bitmap;
+       GetObject(iinfo.hbmColor, sizeof(BITMAP), &l_Bitmap);
+
+       if(l_Bitmap.bmBitsPixel == 32)
+       {
+               BITMAPINFO l_BitmapInfo;
+               l_BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+               l_BitmapInfo.bmiHeader.biWidth = l_Bitmap.bmWidth;
+               l_BitmapInfo.bmiHeader.biHeight = l_Bitmap.bmHeight;
+               l_BitmapInfo.bmiHeader.biPlanes = l_Bitmap.bmPlanes;
+               l_BitmapInfo.bmiHeader.biBitCount = l_Bitmap.bmBitsPixel;
+               l_BitmapInfo.bmiHeader.biCompression = BI_RGB;
+
+               RGBQUAD *l_pRawBytes = new RGBQUAD[l_Bitmap.bmWidth * l_Bitmap.bmHeight];
+
+               HDC dc = ::GetDC(NULL);
+
+               if(dc)
+               {
+                       if(GetDIBits(dc, iinfo.hbmColor, 0, l_Bitmap.bmHeight, l_pRawBytes, &l_BitmapInfo, DIB_RGB_COLORS))
+                               l_bResult = CreateFromArray((BYTE*)l_pRawBytes, l_Bitmap.bmWidth, l_Bitmap.bmHeight, l_Bitmap.bmBitsPixel, l_Bitmap.bmWidthBytes, false);
+                       else
+                               l_bResult = false;
+
+                       ::ReleaseDC(NULL, dc);
+               }
+               else
+                       l_bResult = false;
+
+               delete [] l_pRawBytes;
+       }
+       else
+       {
+               l_bResult = CreateFromHBITMAP(iinfo.hbmColor);
+#if CXIMAGE_SUPPORT_ALPHA
+               if(l_bResult)
+               {
+                       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
+////////////////////////////////////////////////////////////////////////////////
+long CxImage::Draw(HDC hdc, const RECT& rect, RECT* pClipRect, bool bSmooth)
+{
+       return Draw(hdc, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, pClipRect,bSmooth);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * 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.
+ * \return true if everything is ok
+ */
+long CxImage::Draw(HDC hdc, long x, long y, long cx, long 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]
+       int 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));
+
+       long destw = paintbox.right - paintbox.left;
+       long 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;
+                       BYTE *pbase;    //points to the final dib
+                       BYTE *pdst;             //current pixel from pbase
+                       BYTE *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){
+                               long xx,yy;
+                               long sx,sy;
+                               float dx,dy;
+                               BYTE *psrc;
+
+                               long ew = ((((24 * destw) + 31) / 32) * 4);
+                               long ymax = paintbox.bottom;
+                               long 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,(long)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,(long)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();
+               long* pc = (long*)&c;
+               long* pct= (long*)&ct;
+               long cit = GetTransIndex();
+               long 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;
+
+               BYTE *pbase;    //points to the final dib
+               BYTE *pdst;             //current pixel from pbase
+               BYTE *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){
+                       long xx,yy,alphaoffset,ix,iy;
+                       BYTE a,a1,*psrc;
+                       long ew = ((((24 * destw) + 31) / 32) * 4);
+                       long ymax = paintbox.bottom;
+                       long 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;
+                               long sx,sy;
+                               
+                               for(yy=0;yy<desth;yy++){
+                                       dy = head.biHeight-(ymax-yy-y)*fy;
+                                       sy = max(0L,(long)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,(long)floor(dx));
+
+                                               if (bAlpha) a=pAlpha[alphaoffset+sx]; else a=255;
+                                               a =(BYTE)((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 = (BYTE)((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=(BYTE)~a;
+                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8); 
+                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8); 
+                                                               *pdst++=(BYTE)((*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 = (BYTE)((a*(1+info.nAlphaMax))>>8);
+
+                                               if (head.biClrUsed){
+                                                       ci = GetPixelIndex(ix,iy);
+                                                       c = GetPaletteColor((BYTE)ci);
+                                                       if (info.bAlphaPaletteEnabled){
+                                                               a = (BYTE)((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=(BYTE)~a;
+                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbBlue)>>8); 
+                                                               *pdst++=(BYTE)((*pdst * a1 + a * c.rgbGreen)>>8); 
+                                                               *pdst++=(BYTE)((*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;
+}
+////////////////////////////////////////////////////////////////////////////////
+long 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
+ */
+long CxImage::Draw2(HDC hdc, long x, long y, long cx, long 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]
+       int 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 int 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
+                       int nWidth = head.biWidth;
+                       int 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((BYTE)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;
+}
+////////////////////////////////////////////////////////////////////////////////
+long CxImage::Stretch(HDC hdc, const RECT& rect, DWORD 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
+ */
+long CxImage::Stretch(HDC hdc, long xoffset, long yoffset, long xsize, long ysize, DWORD 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
+ */
+long CxImage::Tile(HDC hdc, RECT *rc)
+{
+       if((pDib)&&(hdc)&&(rc)) {
+               int w = rc->right - rc->left;
+               int h = rc->bottom - rc->top;
+               int x,y,z;
+               int bx=head.biWidth;
+               int 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
+long CxImage::DrawString(HDC hdc, long x, long y, const TCHAR* text, RGBQUAD color, const TCHAR* font, long lSize, long lWeight, BYTE bItalic, BYTE bUnderline, bool bSetAlpha)
+//long CxImage::DrawString(HDC hdc, long x, long y, const char* text, RGBQUAD color, const char* font, long lSize, long lWeight, BYTE bItalic, BYTE 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};
+               //long len = (long)strlen(text);
+               long len = (long)_tcslen(text); // For UNICODE support
+               ::DrawText(TmpDC,text,len,&pos,DT_CALCRECT);
+               pos.right+=pos.bottom; //for italics
+
+               //Preparing Bitmap Info
+               long width=pos.right;
+               long 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;
+               BYTE *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 (long ix=0;ix<width;ix++){
+                       for (long 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>
+long CxImage::DrawStringEx(HDC hdc, long x, long 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
+    long i=0, numlines=1, len=(long)_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
+       int frame = 0, roundR = 0;
+    if ( pTextType->opaque )
+    {
+        roundR= (int)(pos.bottom/numlines * pTextType->b_round / 100 ) ;
+        frame = (int)(/*3.5 + */0.29289*roundR ) ;
+        pos.right += pos.bottom/numlines/3 ; // JUST FOR BEAUTY
+    }
+
+       //Preparing Bitmap Info
+       long width=pos.right +frame*2;
+       long 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;
+       BYTE *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 (pTextType->smooth==FALSE){
+               itext.Threshold(128);
+       } else {
+               //itext.TextBlur();
+       }
+
+    //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
+    long ix,iy;
+    if ( pTextType->opaque )
+    {
+        int ixf=0; 
+        for (ix=0;ix<width;ix++)
+        {
+            if ( ix<=roundR )
+                ixf = (int)(.5+roundR-sqrt((float)(roundR*roundR-(ix-roundR)*(ix-roundR))));
+            else if ( ix>=width-roundR-1 )
+                ixf = (int)(.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 = (unsigned char)(pTextType->b_opacity * pcolor.rgbBlue + (1.0-pTextType->b_opacity) * p_backcolor.rgbBlue );
+                        bcolor.rgbRed = (unsigned char)(pTextType->b_opacity * pcolor.rgbRed + (1.0-pTextType->b_opacity) * p_backcolor.rgbRed ) ;
+                        bcolor.rgbGreen = (unsigned char)(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  = (unsigned char)(a * (pcolor.rgbBlue  - p_forecolor.rgbBlue)  + p_forecolor.rgbBlue );
+                pcolor.rgbRed   = (unsigned char)(a * (pcolor.rgbRed   - p_forecolor.rgbRed)   + p_forecolor.rgbRed ) ;
+                pcolor.rgbGreen = (unsigned char)(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
+////////////////////////////////////////////////////////////////////////////////
+long 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);
+}
+////////////////////////////////////////////////////////////////////////////////
+long CxImage::LayerDrawAll(HDC hdc, long x, long y, long cx, long cy, RECT* pClipRect, bool bSmooth)
+{
+       long 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
+////////////////////////////////////////////////////////////////////////////////
index 0cb7e1d8e6317ade39f0578ab4501274a40c4715..f111af6e5aadba76aa7a2455a44c384c49f93072 100644 (file)
-#if !defined(__xiofile_h)\r
-#define __xiofile_h\r
-\r
-#include "xfile.h"\r
-//#include <TCHAR.h>\r
-\r
-class DLL_EXP CxIOFile : public CxFile\r
-       {\r
-public:\r
-       CxIOFile(FILE* fp = NULL)\r
-       {\r
-               m_fp = fp;\r
-               m_bCloseFile = (bool)(fp==0);\r
-       }\r
-\r
-       ~CxIOFile()\r
-       {\r
-               Close();\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       bool Open(LPCTSTR filename, LPCTSTR mode)\r
-       {\r
-               if (m_fp) return false; // Can't re-open without closing first\r
-\r
-               m_fp = _tfopen(filename, mode);\r
-               if (!m_fp) return false;\r
-\r
-               m_bCloseFile = true;\r
-\r
-               return true;\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual bool Close()\r
-       {\r
-               int iErr = 0;\r
-               if ( (m_fp) && (m_bCloseFile) ){ \r
-                       iErr = fclose(m_fp);\r
-                       m_fp = NULL;\r
-               }\r
-               return (bool)(iErr==0);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual size_t  Read(void *buffer, size_t size, size_t count)\r
-       {\r
-               if (!m_fp) return 0;\r
-               return fread(buffer, size, count, m_fp);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual size_t  Write(const void *buffer, size_t size, size_t count)\r
-       {\r
-               if (!m_fp) return 0;\r
-               return fwrite(buffer, size, count, m_fp);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual bool Seek(long offset, int origin)\r
-       {\r
-               if (!m_fp) return false;\r
-               return (bool)(fseek(m_fp, offset, origin) == 0);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual long Tell()\r
-       {\r
-               if (!m_fp) return 0;\r
-               return ftell(m_fp);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual long    Size()\r
-       {\r
-               if (!m_fp) return -1;\r
-               long pos,size;\r
-               pos = ftell(m_fp);\r
-               fseek(m_fp, 0, SEEK_END);\r
-               size = ftell(m_fp);\r
-               fseek(m_fp, pos,SEEK_SET);\r
-               return size;\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual bool    Flush()\r
-       {\r
-               if (!m_fp) return false;\r
-               return (bool)(fflush(m_fp) == 0);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual bool    Eof()\r
-       {\r
-               if (!m_fp) return true;\r
-               return (bool)(feof(m_fp) != 0);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual long    Error()\r
-       {\r
-               if (!m_fp) return -1;\r
-               return ferror(m_fp);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual bool PutC(unsigned char c)\r
-       {\r
-               if (!m_fp) return false;\r
-               return (bool)(fputc(c, m_fp) == c);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual long    GetC()\r
-       {\r
-               if (!m_fp) return EOF;\r
-               return getc(m_fp);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual char *  GetS(char *string, int n)\r
-       {\r
-               if (!m_fp) return NULL;\r
-               return fgets(string,n,m_fp);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-       virtual long    Scanf(const char *format, void* output)\r
-       {\r
-               if (!m_fp) return EOF;\r
-               return fscanf(m_fp, format, output);\r
-       }\r
-//////////////////////////////////////////////////////////\r
-protected:\r
-       FILE *m_fp;\r
-       bool m_bCloseFile;\r
-       };\r
-\r
-#endif\r
+#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(LPCTSTR filename, LPCTSTR mode)
+       {
+               if (m_fp) return false; // Can't re-open without closing first
+
+               m_fp = _tfopen(filename, mode);
+               if (!m_fp) return false;
+
+               m_bCloseFile = true;
+
+               return true;
+       }
+//////////////////////////////////////////////////////////
+       virtual bool Close()
+       {
+               int 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(long offset, int origin)
+       {
+               if (!m_fp) return false;
+               return (bool)(fseek(m_fp, offset, origin) == 0);
+       }
+//////////////////////////////////////////////////////////
+       virtual long Tell()
+       {
+               if (!m_fp) return 0;
+               return ftell(m_fp);
+       }
+//////////////////////////////////////////////////////////
+       virtual long    Size()
+       {
+               if (!m_fp) return -1;
+               long 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 long    Error()
+       {
+               if (!m_fp) return -1;
+               return ferror(m_fp);
+       }
+//////////////////////////////////////////////////////////
+       virtual bool PutC(unsigned char c)
+       {
+               if (!m_fp) return false;
+               return (bool)(fputc(c, m_fp) == c);
+       }
+//////////////////////////////////////////////////////////
+       virtual long    GetC()
+       {
+               if (!m_fp) return EOF;
+               return getc(m_fp);
+       }
+//////////////////////////////////////////////////////////
+       virtual char *  GetS(char *string, int n)
+       {
+               if (!m_fp) return NULL;
+               return fgets(string,n,m_fp);
+       }
+//////////////////////////////////////////////////////////
+       virtual long    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
index 22348b92e8ebc9a516b9a7467a960b34d977de3b..af8db945a31d82ae91b590eebd8f8e713e31df31 100644 (file)
-#include "xmemfile.h"\r
-\r
-//////////////////////////////////////////////////////////\r
-CxMemFile::CxMemFile(BYTE* pBuffer, DWORD size)\r
-{\r
-       m_pBuffer = pBuffer;\r
-       m_Position = 0;\r
-       m_Size = m_Edge = size;\r
-       m_bFreeOnClose = (bool)(pBuffer==0);\r
-}\r
-//////////////////////////////////////////////////////////\r
-CxMemFile::~CxMemFile()\r
-{\r
-       Close();\r
-}\r
-//////////////////////////////////////////////////////////\r
-bool CxMemFile::Close()\r
-{\r
-       if ( (m_pBuffer) && (m_bFreeOnClose) ){\r
-               free(m_pBuffer);\r
-               m_pBuffer = NULL;\r
-               m_Size = 0;\r
-       }\r
-       return true;\r
-}\r
-//////////////////////////////////////////////////////////\r
-bool CxMemFile::Open()\r
-{\r
-       if (m_pBuffer) return false;    // Can't re-open without closing first\r
-\r
-       m_Position = m_Size = m_Edge = 0;\r
-       m_pBuffer=(BYTE*)malloc(1);\r
-       m_bFreeOnClose = true;\r
-\r
-       return (m_pBuffer!=0);\r
-}\r
-//////////////////////////////////////////////////////////\r
-BYTE* CxMemFile::GetBuffer(bool bDetachBuffer)\r
-{\r
-       //can only detach, avoid inadvertantly attaching to\r
-       // memory that may not be ours [Jason De Arte]\r
-       if( bDetachBuffer )\r
-               m_bFreeOnClose = false;\r
-       return m_pBuffer;\r
-}\r
-//////////////////////////////////////////////////////////\r
-size_t CxMemFile::Read(void *buffer, size_t size, size_t count)\r
-{\r
-       if (buffer==NULL) return 0;\r
-\r
-       if (m_pBuffer==NULL) return 0;\r
-       if (m_Position >= (long)m_Size) return 0;\r
-\r
-       long nCount = (long)(count*size);\r
-       if (nCount == 0) return 0;\r
-\r
-       long nRead;\r
-       if (m_Position + nCount > (long)m_Size)\r
-               nRead = (m_Size - m_Position);\r
-       else\r
-               nRead = nCount;\r
-\r
-       memcpy(buffer, m_pBuffer + m_Position, nRead);\r
-       m_Position += nRead;\r
-\r
-       return (size_t)(nRead/size);\r
-}\r
-//////////////////////////////////////////////////////////\r
-size_t CxMemFile::Write(const void *buffer, size_t size, size_t count)\r
-{\r
-       if (m_pBuffer==NULL) return 0;\r
-       if (buffer==NULL) return 0;\r
-\r
-       long nCount = (long)(count*size);\r
-       if (nCount == 0) return 0;\r
-\r
-       if (m_Position + nCount > m_Edge){\r
-               if (!Alloc(m_Position + nCount)){\r
-                       return false;\r
-               }\r
-       }\r
-\r
-       memcpy(m_pBuffer + m_Position, buffer, nCount);\r
-\r
-       m_Position += nCount;\r
-\r
-       if (m_Position > (long)m_Size) m_Size = m_Position;\r
-       \r
-       return count;\r
-}\r
-//////////////////////////////////////////////////////////\r
-bool CxMemFile::Seek(long offset, int origin)\r
-{\r
-       if (m_pBuffer==NULL) return false;\r
-       long lNewPos = m_Position;\r
-\r
-       if (origin == SEEK_SET)          lNewPos = offset;\r
-       else if (origin == SEEK_CUR) lNewPos += offset;\r
-       else if (origin == SEEK_END) lNewPos = m_Size + offset;\r
-       else return false;\r
-\r
-       if (lNewPos < 0) lNewPos = 0;\r
-\r
-       m_Position = lNewPos;\r
-       return true;\r
-}\r
-//////////////////////////////////////////////////////////\r
-long CxMemFile::Tell()\r
-{\r
-       if (m_pBuffer==NULL) return -1;\r
-       return m_Position;\r
-}\r
-//////////////////////////////////////////////////////////\r
-long CxMemFile::Size()\r
-{\r
-       if (m_pBuffer==NULL) return -1;\r
-       return m_Size;\r
-}\r
-//////////////////////////////////////////////////////////\r
-bool CxMemFile::Flush()\r
-{\r
-       if (m_pBuffer==NULL) return false;\r
-       return true;\r
-}\r
-//////////////////////////////////////////////////////////\r
-bool CxMemFile::Eof()\r
-{\r
-       if (m_pBuffer==NULL) return true;\r
-       return (m_Position >= (long)m_Size);\r
-}\r
-//////////////////////////////////////////////////////////\r
-long CxMemFile::Error()\r
-{\r
-       if (m_pBuffer==NULL) return -1;\r
-       return (m_Position > (long)m_Size);\r
-}\r
-//////////////////////////////////////////////////////////\r
-bool CxMemFile::PutC(unsigned char c)\r
-{\r
-       if (m_pBuffer==NULL) return false;\r
-\r
-       if (m_Position >= m_Edge){\r
-               if (!Alloc(m_Position + 1)){\r
-                       return false;\r
-               }\r
-       }\r
-\r
-       m_pBuffer[m_Position++] = c;\r
-\r
-       if (m_Position > (long)m_Size) m_Size = m_Position;\r
-       \r
-       return true;\r
-}\r
-//////////////////////////////////////////////////////////\r
-long CxMemFile::GetC()\r
-{\r
-       if (Eof()) return EOF;\r
-       return *(BYTE*)((BYTE*)m_pBuffer + m_Position++);\r
-}\r
-//////////////////////////////////////////////////////////\r
-char * CxMemFile::GetS(char *string, int n)\r
-{\r
-       n--;\r
-       long c,i=0;\r
-       while (i<n){\r
-               c = GetC();\r
-               if (c == EOF) return 0;\r
-               string[i++] = (char)c;\r
-               if (c == '\n') break;\r
-       }\r
-       string[i] = 0;\r
-       return string;\r
-}\r
-//////////////////////////////////////////////////////////\r
-long   CxMemFile::Scanf(const char *format, void* output)\r
-{\r
-       return 0;\r
-}\r
-//////////////////////////////////////////////////////////\r
-bool CxMemFile::Alloc(DWORD dwNewLen)\r
-{\r
-       if (dwNewLen > (DWORD)m_Edge)\r
-       {\r
-               // find new buffer size\r
-               DWORD dwNewBufferSize = (DWORD)(((dwNewLen>>16)+1)<<16);\r
-\r
-               // allocate new buffer\r
-               if (m_pBuffer == NULL) m_pBuffer = (BYTE*)malloc(dwNewBufferSize);\r
-               else    m_pBuffer = (BYTE*)realloc(m_pBuffer, dwNewBufferSize);\r
-               // I own this buffer now (caller knows nothing about it)\r
-               m_bFreeOnClose = true;\r
-\r
-               m_Edge = dwNewBufferSize;\r
-       }\r
-       return (m_pBuffer!=0);\r
-}\r
-//////////////////////////////////////////////////////////\r
-void CxMemFile::Free()\r
-{\r
-       Close();\r
-}\r
-//////////////////////////////////////////////////////////\r
+#include "xmemfile.h"
+
+//////////////////////////////////////////////////////////
+CxMemFile::CxMemFile(BYTE* pBuffer, DWORD size)
+{
+       m_pBuffer = pBuffer;
+       m_Position = 0;
+       m_Size = m_Edge = size;
+       m_bFreeOnClose = (bool)(pBuffer==0);
+}
+//////////////////////////////////////////////////////////
+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=(BYTE*)malloc(1);
+       m_bFreeOnClose = true;
+
+       return (m_pBuffer!=0);
+}
+//////////////////////////////////////////////////////////
+BYTE* 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 >= (long)m_Size) return 0;
+
+       long nCount = (long)(count*size);
+       if (nCount == 0) return 0;
+
+       long nRead;
+       if (m_Position + nCount > (long)m_Size)
+               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)
+{
+       if (m_pBuffer==NULL) return 0;
+       if (buffer==NULL) return 0;
+
+       long nCount = (long)(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 > (long)m_Size) m_Size = m_Position;
+       
+       return count;
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::Seek(long offset, int origin)
+{
+       if (m_pBuffer==NULL) return false;
+       long 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;
+}
+//////////////////////////////////////////////////////////
+long CxMemFile::Tell()
+{
+       if (m_pBuffer==NULL) return -1;
+       return m_Position;
+}
+//////////////////////////////////////////////////////////
+long 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_Position >= (long)m_Size);
+}
+//////////////////////////////////////////////////////////
+long CxMemFile::Error()
+{
+       if (m_pBuffer==NULL) return -1;
+       return (m_Position > (long)m_Size);
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::PutC(unsigned char c)
+{
+       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 > (long)m_Size) m_Size = m_Position;
+       
+       return true;
+}
+//////////////////////////////////////////////////////////
+long CxMemFile::GetC()
+{
+       if (Eof()) return EOF;
+       return *(BYTE*)((BYTE*)m_pBuffer + m_Position++);
+}
+//////////////////////////////////////////////////////////
+char * CxMemFile::GetS(char *string, int n)
+{
+       n--;
+       long 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;
+}
+//////////////////////////////////////////////////////////
+long   CxMemFile::Scanf(const char *format, void* output)
+{
+       return 0;
+}
+//////////////////////////////////////////////////////////
+bool CxMemFile::Alloc(DWORD dwNewLen)
+{
+       if (dwNewLen > (DWORD)m_Edge)
+       {
+               // find new buffer size
+               DWORD dwNewBufferSize = (DWORD)(((dwNewLen>>16)+1)<<16);
+
+               // allocate new buffer
+               if (m_pBuffer == NULL) m_pBuffer = (BYTE*)malloc(dwNewBufferSize);
+               else    m_pBuffer = (BYTE*)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();
+}
+//////////////////////////////////////////////////////////
index ac4c412007097841b6ee59f7bdc611d73464fd61..f87e4f9b1106f61879344e438f939a06c90f4393 100644 (file)
@@ -1,41 +1,41 @@
-#if !defined(__xmemfile_h)\r
-#define __xmemfile_h\r
-\r
-#include "xfile.h"\r
-\r
-//////////////////////////////////////////////////////////\r
-class DLL_EXP CxMemFile : public CxFile\r
-{\r
-public:\r
-       CxMemFile(BYTE* pBuffer = NULL, DWORD size = 0);\r
-       ~CxMemFile();\r
-\r
-       bool Open();\r
-       BYTE* GetBuffer(bool bDetachBuffer = true);\r
-\r
-       virtual bool    Close();\r
-       virtual size_t  Read(void *buffer, size_t size, size_t count);\r
-       virtual size_t  Write(const void *buffer, size_t size, size_t count);\r
-       virtual bool    Seek(long offset, int origin);\r
-       virtual long    Tell();\r
-       virtual long    Size();\r
-       virtual bool    Flush();\r
-       virtual bool    Eof();\r
-       virtual long    Error();\r
-       virtual bool    PutC(unsigned char c);\r
-       virtual long    GetC();\r
-       virtual char *  GetS(char *string, int n);\r
-       virtual long    Scanf(const char *format, void* output);\r
-\r
-protected:\r
-       bool    Alloc(DWORD nBytes);\r
-       void    Free();\r
-\r
-       BYTE*   m_pBuffer;\r
-       DWORD   m_Size;\r
-       bool    m_bFreeOnClose;\r
-       long    m_Position;     //current position\r
-       long    m_Edge;         //buffer size\r
-};\r
-\r
-#endif\r
+#if !defined(__xmemfile_h)
+#define __xmemfile_h
+
+#include "xfile.h"
+
+//////////////////////////////////////////////////////////
+class DLL_EXP CxMemFile : public CxFile
+{
+public:
+       CxMemFile(BYTE* pBuffer = NULL, DWORD size = 0);
+       ~CxMemFile();
+
+       bool Open();
+       BYTE* 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(long offset, int origin);
+       virtual long    Tell();
+       virtual long    Size();
+       virtual bool    Flush();
+       virtual bool    Eof();
+       virtual long    Error();
+       virtual bool    PutC(unsigned char c);
+       virtual long    GetC();
+       virtual char *  GetS(char *string, int n);
+       virtual long    Scanf(const char *format, void* output);
+
+protected:
+       bool    Alloc(DWORD nBytes);
+       void    Free();
+
+       BYTE*   m_pBuffer;
+       DWORD   m_Size;
+       bool    m_bFreeOnClose;
+       long    m_Position;     //current position
+       long    m_Edge;         //buffer size
+};
+
+#endif
index f06ba513e281772b911ccb6eb54144913ba8b364..7f87ae22272fe5c69ac865325b00438ed7a5389d 100644 (file)
@@ -1,4 +1,4 @@
-// Icon with lowest ID value placed first to ensure application icon\r
-// remains consistent on all systems.\r
-IDI_ICON1               ICON                    "icons/ducky.ico"\r
-\r
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1               ICON                    "icons/ducky.ico"
+
index 1b432638e810915c48d252090aa6526823e45ce0..12928afa2d82ca079a02fa4c1d5bbf9e2eaaab42 100644 (file)
-/*=========================================================================\r
-  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv\r
-\r
-  Authors belong to:\r
-  - University of LYON              http://www.universite-lyon.fr/\r
-  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr\r
-  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr\r
-\r
-  This software is distributed WITHOUT ANY WARRANTY; without even\r
-  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
-  PURPOSE.  See the copyright notices for more information.\r
-\r
-  It is distributed under dual licence\r
-\r
-  - BSD        See included LICENSE.txt file\r
-  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html\r
-  ======================================================================-====*/\r
-\r
-#include "vvSlicerManager.h"\r
-#include "vvSlicer.h"\r
-#include "vvImage.h"\r
-#include "vvSlicerManagerCommand.h"\r
-#include "vvInteractorStyleNavigator.h"\r
-#include "vvLandmarks.h"\r
-#include "vvMesh.h"\r
-#include "vvBlendImageActor.h"\r
-\r
-#include <vtkVersion.h>\r
-#include <vtkStreamingDemandDrivenPipeline.h>\r
-#include <vtkInformation.h>\r
-#include <vtkImageActor.h>\r
-#include <vtkImageData.h>\r
-#include <vtkRenderWindow.h>\r
-#include <vtkRendererCollection.h>\r
-#include <vtkRenderWindowInteractor.h>\r
-#include <vtkImageMapToWindowLevelColors.h>\r
-#include <vtkWindowLevelLookupTable.h>\r
-#include <vtkColorTransferFunction.h>\r
-#include <vtkImageClip.h>\r
-#include <vtkLODActor.h>\r
-#include <vtkPointData.h>\r
-#include <vtksys/SystemTools.hxx>\r
-#include <vtkCamera.h>\r
-\r
-#include <qfileinfo.h>\r
-#include <QMessageBox>\r
-//----------------------------------------------------------------------------\r
-vvSlicerManager::vvSlicerManager(int numberOfSlicers)\r
-{ \r
-\r
-  connect(this, SIGNAL(callAddLandmark(float,float,float,float)), this, SLOT(AddLandmark(float,float,float,float)));\r
-\r
-  mFileName = "";\r
-  mId = "";\r
-  mVFName = "";\r
-  mOverlayName = "";\r
-  mFusionName = "";\r
-  mVFId = "";\r
-  mLastError = "";\r
-  mType = vvImageReader::UNDEFINEDIMAGETYPE;\r
-  mColorMap = 0;\r
-  mPreset = 0;\r
-  mOverlayColor = 130;\r
-\r
-  mFusionOpacity = 30;\r
-  mFusionThresOpacity = 1;\r
-  mFusionColorMap = 3;\r
-  mFusionWindow = 1000;\r
-  mFusionLevel = 1000;\r
-  mFusionShowLegend = true;\r
-  \r
-  mFusionSequenceInvolvementCode = -1;\r
-  mFusionSequenceIndexLinkedManager = -1;\r
-  mFusionSequenceFrameIndex = -1;\r
-  mFusionSequenceNbFrames = 0;\r
-  mFusionSequenceSpatialSyncFlag = false;\r
-  mFusionSequenceTemporalSyncFlag = false;\r
-\r
-  mLandmarks = NULL;\r
-  mLinkedId.resize(0);\r
-\r
-  for ( int i = 0; i < numberOfSlicers; i++) {\r
-    mSlicers.push_back(vtkSmartPointer<vvSlicer>::New());\r
-    mSlicers[i]->SetSlicerNumber(i);\r
-  }\r
-  mSelectedSlicer = -1;\r
-  \r
-  mPreviousSlice.resize(numberOfSlicers, 0);\r
-  mPreviousTSlice.resize(numberOfSlicers, 0);\r
-  mSlicingPreset = WORLD_SLICING;\r
-\r
-  \r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-vvSlicerManager::~vvSlicerManager()\r
-{ \r
-  if (mLandmarks)\r
-    delete mLandmarks;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//------------------------------------------------------------------------------\r
-void vvSlicerManager::SetFilename(std::string filename, int number)\r
-{ \r
-  mFileName = filename;\r
-  mFileName = vtksys::SystemTools::GetFilenameName(mFileName);\r
-  mBaseFileName = vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(mFileName));\r
-  mBaseFileNameNumber = number;\r
-\r
-  mFileName = mBaseFileName;\r
-  if (number != 0) {\r
-    mFileName.append("_"+clitk::toString(number));\r
-  }\r
-  mFileName.append(vtksys::SystemTools::GetFilenameLastExtension(filename));\r
-\r
-  for(unsigned int i=0; i<mSlicers.size(); i++) {\r
-    mSlicers[i]->SetFileName(mFileName);//vtksys::SystemTools::GetFilenameWithoutLastExtension(filename));\r
-  }\r
-  \r
-}\r
-//------------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::AddContour(vvMesh::Pointer contour,bool propagate)\r
-{ \r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->AddContour(contour,propagate);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::ToggleContourSuperposition()\r
-{ \r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++)\r
-    mSlicers[i]->ToggleContourSuperposition();\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-std::string vvSlicerManager::GetListOfAbsoluteFilePathInOneString(const std::string &actorType)\r
-{ \r
-  vvImageReader *reader = NULL;\r
-\r
-  if(actorType=="image")\r
-    reader = mReader;\r
-  else if(actorType=="overlay")\r
-    reader = mOverlayReader;\r
-  else if(actorType=="fusion")\r
-    reader = mFusionReader;\r
-  else if(actorType=="vector")\r
-    reader = mVectorReader;\r
-  else if(actorType=="fusionSequence")\r
-       reader = mFusionSequenceReader;\r
-\r
-  if(!reader)\r
-    return "";\r
-\r
-  std::string list;\r
-  for(unsigned int i=0; i<reader->GetInputFilenames().size(); i++){\r
-    QFileInfo fileinfo(reader->GetInputFilenames()[i].c_str()); //Do not show the path\r
-    if(i)\r
-      list += '\n';\r
-    list += fileinfo.absoluteFilePath().toStdString();\r
-  }\r
-  return list;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-bool vvSlicerManager::SetImage(std::string filename, vvImageReader::LoadedImageType type, int n, unsigned int slice)\r
-{ \r
-  mType = type;\r
-  if (mReader.IsNull())\r
-    mReader = vvImageReader::New();\r
-  std::vector<std::string> filenames;\r
-  filenames.push_back(filename);\r
-  mReader->SetInputFilenames(filenames);\r
-  mReader->SetSlice(slice); // Only used for SLICED type\r
-  mReader->Update(type);\r
-\r
-  SetFilename(filename, n);\r
-  //  mFileName = vtksys::SystemTools::GetFilenameName(mFileName);\r
-  //mBaseFileName = vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(mFileName));\r
-  //mBaseFileNameNumber = n;\r
-\r
-  if (mReader->GetLastError().size() == 0) {\r
-    mImage=mReader->GetOutput();\r
-    for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-      mSlicers[i]->SetFileName(vtksys::SystemTools::GetFilenameWithoutLastExtension(filename));\r
-      mSlicers[i]->SetImage(mReader->GetOutput());\r
-    }\r
-  } else {\r
-    mLastError = mReader->GetLastError();\r
-    return false;\r
-  }\r
-  // if (n!=0) {\r
-  //   mFileName.append("_"+clitk::toString(n));\r
-  // }\r
-  return true;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetImage(vvImage::Pointer image)\r
-{ \r
-  mImage=image;\r
-  for (unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetImage(image);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-bool vvSlicerManager::SetImages(std::vector<std::string> filenames, vvImageReader::LoadedImageType type, int n)\r
-{ \r
-  mType = type;\r
-  std::string fileWithoutExtension = vtksys::SystemTools::GetFilenameWithoutExtension(filenames[0]);\r
-  if (type == vvImageReader::DICOM)\r
-    fileWithoutExtension += "_dicom";\r
-  else if (type == vvImageReader::MERGED)\r
-    fileWithoutExtension += "_merged";\r
-  else if (type == vvImageReader::MERGEDWITHTIME)\r
-    fileWithoutExtension += "_merged_wt";\r
-\r
-  mFileName = vtksys::SystemTools::GetFilenameName(mFileName);\r
-  mFileName = fileWithoutExtension + vtksys::SystemTools::GetFilenameExtension(filenames[0]);\r
-  if (mReader.IsNull())\r
-    mReader = vvImageReader::New();\r
-  mReader->SetInputFilenames(filenames);\r
-  mReader->Update(type);\r
-\r
-  mBaseFileName = vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(mFileName));\r
-  mBaseFileNameNumber = n;\r
-\r
-  if (mReader->GetLastError().size() == 0) {\r
-    mImage=mReader->GetOutput();\r
-    for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-      mSlicers[i]->SetFileName(fileWithoutExtension);\r
-      mSlicers[i]->SetImage(mReader->GetOutput());\r
-    }\r
-  } else {\r
-    mLastError = mReader->GetLastError();\r
-    return false;\r
-  }\r
-  if (n!=0) {\r
-    mFileName.append("_"+clitk::toString(n));\r
-  }\r
-  return true;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-bool vvSlicerManager::SetOverlay(std::vector<std::string> filenames,int dim, std::string component, vvImageReader::LoadedImageType type)\r
-{ \r
-  mOverlayName = filenames[0];\r
-  mOverlayComponent = component;\r
-  if (dim > mImage->GetNumberOfDimensions()) {\r
-    mLastError = " Overlay dimension cannot be greater than reference image!";\r
-    return false;\r
-  }\r
-  if (mOverlayReader.IsNull())\r
-    mOverlayReader = vvImageReader::New();\r
-  mOverlayReader->SetInputFilenames(filenames);\r
-  mOverlayReader->Update(type);\r
-  if (mOverlayReader->GetLastError().size() == 0) {\r
-    for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-      mSlicers[i]->SetOverlay(mOverlayReader->GetOutput());\r
-    }\r
-  } else {\r
-    mLastError = mOverlayReader->GetLastError();\r
-    return false;\r
-  }\r
-  return true;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-bool vvSlicerManager::SetFusion(std::vector<std::string> filenames,int dim, std::string component, vvImageReader::LoadedImageType type)\r
-{ \r
-  mFusionName = filenames[0];\r
-  mFusionComponent = component;\r
-  if (dim > mImage->GetNumberOfDimensions()) {\r
-    mLastError = " Fusion dimension cannot be greater than reference image!";\r
-    return false;\r
-  }\r
-  if (mFusionReader.IsNull())\r
-    mFusionReader = vvImageReader::New();\r
-  mFusionReader->SetInputFilenames(filenames);\r
-  mFusionReader->Update(type);\r
-  if (mFusionReader->GetLastError().size() == 0) {\r
-    for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-      mSlicers[i]->SetFusion(mFusionReader->GetOutput());\r
-    }\r
-  } else {\r
-    mLastError = mFusionReader->GetLastError();\r
-    return false;\r
-  }\r
-  double *fusRange = mFusionReader->GetOutput()->GetVTKImages()[0]->GetScalarRange();\r
-  mFusionLevel = (fusRange[0]+fusRange[1])/2;\r
-  mFusionWindow = fusRange[1]-fusRange[0];\r
-\r
-  return true;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-//this function is called by vvMainWindow::AddFusionSequence for the primary sequence (CT), while the given files constitute the secondary sequence.\r
-bool vvSlicerManager::SetFusionSequence(std::vector<std::string> filenames, int dim, std::string component, vvImageReader::LoadedImageType type)\r
-{ \r
-       mFusionSequenceInvolvementCode = 0;\r
-\r
-       mFusionName = filenames[0];\r
-       mFusionComponent = component;\r
-\r
-       if (dim > mImage->GetNumberOfDimensions()) {\r
-               mLastError = " Fusion Sequence dimension cannot be greater than reference image!";\r
-               return false;\r
-       }\r
-\r
-       if (mFusionSequenceReader.IsNull())\r
-               mFusionSequenceReader = vvImageReader::New();\r
-\r
-       mFusionSequenceReader->SetInputFilenames(filenames);\r
-       mFusionSequenceReader->Update(type);\r
-\r
-\r
-       if (mFusionSequenceReader->GetLastError().size() == 0) {\r
-               for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-                       mSlicers[i]->SetFusion(mFusionSequenceReader->GetOutput(), mFusionSequenceInvolvementCode);\r
-               }\r
-       } else {\r
-               mLastError = mFusionSequenceReader->GetLastError();\r
-               return false;\r
-       }\r
-       double *fusRange = mFusionSequenceReader->GetOutput()->GetVTKImages()[0]->GetScalarRange();\r
-       mFusionLevel = (fusRange[0]+fusRange[1])/2;\r
-       mFusionWindow = fusRange[1]-fusRange[0];\r
-\r
-       //store the initial transform matrices of each frame, and reset them to identity\r
-       mFusionSequenceListInitialTransformMatrices.clear();\r
-       for (unsigned i=0 ; i<mFusionSequenceReader->GetOutput()->GetTransform().size() ; i++) {\r
-               AddFusionSequenceInitialTransformMatrices( mFusionSequenceReader->GetOutput()->GetTransform()[i]->GetMatrix() );\r
-               mFusionSequenceReader->GetOutput()->GetTransform()[i]->Identity();\r
-               mFusionSequenceReader->GetOutput()->GetTransform()[i]->Update();\r
-       }\r
-\r
-       //adjust the time slider in the overlay panel\r
-       mFusionSequenceNbFrames = mFusionSequenceReader->GetOutput()->GetTransform().size(); \r
-       mFusionSequenceFrameIndex = std::max<int>( 0, std::min<int>(mFusionSequenceFrameIndex, mFusionSequenceNbFrames));\r
-\r
-       return true;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-bool vvSlicerManager::SetVF(std::string filename)\r
-{ \r
-  if (mVectorReader.IsNull())\r
-    mVectorReader = vvImageReader::New();\r
-  mVectorReader->SetInputFilename(filename);\r
-  \r
-  if (mType == vvImageReader::IMAGEWITHTIME)\r
-    mVectorReader->Update(vvImageReader::VECTORFIELDWITHTIME);\r
-  else\r
-    mVectorReader->Update(vvImageReader::VECTORFIELD);\r
-  if (mVectorReader->GetLastError().size() != 0) {\r
-    mLastError = mVectorReader->GetLastError();\r
-    return false;\r
-  } else\r
-    return SetVF(mVectorReader->GetOutput(),filename);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-bool vvSlicerManager::SetVF(vvImage::Pointer vf,std::string filename)\r
-{ \r
-  if (vf->GetNumberOfDimensions() > mImage->GetNumberOfDimensions()) {\r
-    mLastError = "Sorry, vector field dimension cannot be greater then reference image.";\r
-    return false;\r
-  }\r
-  if (vf->GetNumberOfDimensions() == 4) {\r
-    if (vf->GetSpacing()[3] != mImage->GetSpacing()[3]) {\r
-      mLastError = "Sorry, vector field time spacing cannot be different from time spacing of the reference image.";\r
-      return false;\r
-    }\r
-    if (vf->GetOrigin()[3] != mImage->GetOrigin()[3]) {\r
-      mLastError = "Sorry, vector field time origin cannot be different from time origin of the reference image.";\r
-      return false;\r
-    }\r
-  }\r
-  mVF=vf;\r
-  mVFName = filename;\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetVF(vf);\r
-  }\r
-  return true;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-vvSlicer* vvSlicerManager::GetSlicer(int i)\r
-{ \r
-  return mSlicers[i];\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::UpdateSlicer(int num, bool state)\r
-{ \r
-  if (mSlicers[num]->GetImage()) {\r
-    mSlicers[num]->SetDisplayMode(state);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetSlicerWindow(int i, vtkRenderWindow* RW)\r
-{ \r
-  mSlicers[i]->SetRenderWindow(i,RW);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetInteractorStyleNavigator(int i, vtkInteractorStyle* style)\r
-{ \r
-  vvSlicerManagerCommand *smc = vvSlicerManagerCommand::New();\r
-  smc->SM = this;\r
-  smc->SetSlicerNumber(i);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->SetInteractorStyle(style);\r
-\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::KeyPressEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::WindowLevelEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::EndWindowLevelEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::StartWindowLevelEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::PickEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::StartPickEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::LeaveEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::UserEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::MouseWheelForwardEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::MouseWheelBackwardEvent, smc);\r
-  // mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-  //   GetInteractorStyle()->AddObserver(vtkCommand::LeftButtonReleaseEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::EndPickEvent, smc);\r
-  mSlicers[i]->GetRenderWindow()->GetInteractor()->\r
-    GetInteractorStyle()->AddObserver(vtkCommand::EndInteractionEvent, smc);\r
-  smc->Delete();\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::LeftButtonReleaseEvent(int slicer)\r
-{ \r
-  emit LeftButtonReleaseSignal(slicer);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::EmitMousePositionUpdated(int slicer)\r
-{ \r
-  emit MousePositionUpdatedSignal(slicer);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::EmitKeyPressed(std::string KeyPress)\r
-{ \r
-  emit KeyPressedSignal(KeyPress);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetSliceOrientation(int slicer, int orientation)\r
-{ \r
-  mSlicers[slicer]->SetSliceOrientation(orientation);\r
-  emit UpdateOrientation(slicer, orientation);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-int vvSlicerManager::GetTSlice()\r
-{ \r
-  return mSlicers[0]->GetTSlice();\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetTSlice(int slice, bool updateLinkedImages)\r
-{ \r
-       if (!updateLinkedImages) { //for fusionSequence, TMax / MaxCurrentTSlice are irrelevant.\r
-               for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-                       mSlicers[i]->SetTSlice(slice, updateLinkedImages);\r
-                       UpdateTSlice(i);\r
-               }\r
-               return;\r
-       }\r
-\r
-  if (slice < 0)\r
-    slice = 0;\r
-  else if (slice > mSlicers[0]->GetTMax())\r
-    slice = mSlicers[0]->GetTMax();\r
-  if (mLandmarks)\r
-    mLandmarks->SetTime(slice);\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    if (slice != mSlicers[i]->GetMaxCurrentTSlice()) {\r
-      mSlicers[i]->SetTSlice(slice, updateLinkedImages);\r
-      UpdateTSlice(i);\r
-    }\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetFusionSequenceTSlice(int slice)\r
-{ \r
-       for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-               mSlicers[i]->SetFusionSequenceTSlice(slice);\r
-               UpdateTSlice(i);\r
-       }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetNextTSlice(int originating_slicer)\r
-{ \r
-  int t = mSlicers[0]->GetMaxCurrentTSlice();\r
-  t++;\r
-  if (t > mSlicers[0]->GetTMax())\r
-    t = 0;\r
-  emit UpdateTSlice(originating_slicer,t, mFusionSequenceInvolvementCode);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetPreviousTSlice(int originating_slicer)\r
-{ \r
-  int t = mSlicers[0]->GetMaxCurrentTSlice();\r
-  t--;\r
-  if (t < 0)\r
-    t = mSlicers[0]->GetTMax();\r
-  emit UpdateTSlice(originating_slicer,t, mFusionSequenceInvolvementCode);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::ToggleInterpolation()\r
-{ \r
-  bool interpolate=!(mSlicers[0]->GetImageActor()->GetInterpolate());\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->GetImageActor()->SetInterpolate(interpolate);\r
-    if (mSlicers[i]->GetOverlayActor())\r
-      mSlicers[i]->GetOverlayActor()->SetInterpolate(interpolate);\r
-    if (mSlicers[i]->GetFusionActor())\r
-      mSlicers[i]->GetFusionActor()->SetInterpolate(interpolate);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetTSliceInSlicer(int tslice, int slicer)\r
-{ \r
-  if (tslice < 0)\r
-    tslice = 0;\r
-  else if (tslice > mSlicers[slicer]->GetTMax())\r
-    tslice = mSlicers[slicer]->GetTMax();\r
-  if (mLandmarks)\r
-    mLandmarks->SetTime(tslice);\r
-\r
-  if (mSlicers[slicer]->GetMaxCurrentTSlice() == tslice) return;\r
-\r
-  mSlicers[slicer]->SetTSlice(tslice);\r
-\r
-  if(mSlicingPreset==VOXELS_SLICING) {\r
-    vtkMatrix4x4 *imageTransformInverse = vtkMatrix4x4::New();\r
-    mImage->GetTransform()[mSlicers[slicer]->GetTSlice()]->GetInverse(imageTransformInverse);\r
-    this->GetSlicer(slicer)->GetSlicingTransform()->SetMatrix(imageTransformInverse);\r
-    imageTransformInverse->Delete();\r
-  }\r
-\r
-  UpdateTSlice(slicer);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetColorWindow(double s)\r
-{ \r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetColorWindow(s);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetColorLevel(double s)\r
-{ \r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetColorLevel(s);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetOverlayColorWindow(double s)\r
-{ \r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetOverlayColorWindow(s);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetOverlayColorLevel(double s)\r
-{ \r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetOverlayColorLevel(s);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetLinkOverlayWindowLevel(bool b)\r
-{ \r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetLinkOverlayWindowLevel(b);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetCursorAndCornerAnnotationVisibility(int s)\r
-{ \r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetCursorVisibility(s);\r
-    mSlicers[i]->SetCornerAnnotationVisibility(s);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetOpacity(int i, double factor)\r
-{ \r
-  mSlicers[i]->SetOpacity(1/factor);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::UpdateViews(int current,int slicer)\r
-{ \r
-  double p[3], pt[3];\r
-  p[0] = mSlicers[slicer]->GetCurrentPosition()[0];\r
-  p[1] = mSlicers[slicer]->GetCurrentPosition()[1];\r
-  p[2] = mSlicers[slicer]->GetCurrentPosition()[2];\r
-  mSlicers[slicer]->GetSlicingTransform()->GetInverse()->TransformPoint(p, pt);\r
-\r
-  double x = (pt[0] - mSlicers[slicer]->GetInput()->GetOrigin()[0])\r
-    /mSlicers[slicer]->GetInput()->GetSpacing()[0];\r
-  double y = (pt[1] - mSlicers[slicer]->GetInput()->GetOrigin()[1])\r
-    /mSlicers[slicer]->GetInput()->GetSpacing()[1];\r
-  double z = (pt[2] - mSlicers[slicer]->GetInput()->GetOrigin()[2])\r
-    /mSlicers[slicer]->GetInput()->GetSpacing()[2];\r
-#if VTK_MAJOR_VERSION <= 5\r
-  if (x >= mSlicers[slicer]->GetInput()->GetWholeExtent()[0]-0.5 &&\r
-      x <= mSlicers[slicer]->GetInput()->GetWholeExtent()[1]+0.5 &&\r
-      y >= mSlicers[slicer]->GetInput()->GetWholeExtent()[2]-0.5 &&\r
-      y <= mSlicers[slicer]->GetInput()->GetWholeExtent()[3]+0.5 &&\r
-      z >= mSlicers[slicer]->GetInput()->GetWholeExtent()[4]-0.5 &&\r
-      z <= mSlicers[slicer]->GetInput()->GetWholeExtent()[5]+0.5)\r
-#else\r
-int extentImageReslice[6];\r
-mSlicers[slicer]->GetRegisterExtent(extentImageReslice);\r
-  if (x >= extentImageReslice[0]-0.5 &&\r
-      x <= extentImageReslice[1]+0.5 &&\r
-      y >= extentImageReslice[2]-0.5 &&\r
-      y <= extentImageReslice[3]+0.5 &&\r
-      z >= extentImageReslice[4]-0.5 &&\r
-      z <= extentImageReslice[5]+0.5)\r
-#endif\r
-  {\r
-    mSlicers[slicer]->UpdateCursorPosition();\r
-    mSlicers[slicer]->SetCursorColor(10,212,255);\r
-    mSelectedSlicer = slicer;\r
-\r
-    switch (mSlicers[slicer]->GetSliceOrientation()) {\r
-    case vtkImageViewer2::SLICE_ORIENTATION_XY:\r
-      if (mSlicers[slicer]->GetSlice() != (int)lrint(z))\r
-        mSlicers[slicer]->SetSlice((int)lrint(z));\r
-      break;\r
-\r
-    case vtkImageViewer2::SLICE_ORIENTATION_XZ:\r
-      if (mSlicers[slicer]->GetSlice() != (int)lrint(y))\r
-        mSlicers[slicer]->SetSlice((int)lrint(y));\r
-      break;\r
-\r
-    case vtkImageViewer2::SLICE_ORIENTATION_YZ:\r
-      if (mSlicers[slicer]->GetSlice() != (int)lrint(x))\r
-        mSlicers[slicer]->SetSlice((int)lrint(x));\r
-      break;\r
-    }\r
-    mSlicers[slicer]->Render();\r
-\r
-    for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-      if (i != (unsigned int)slicer\r
-          && mSlicers[i]->GetRenderer()->GetDraw()\r
-          && mSlicers[i]->GetRenderWindow()->GetSize()[0] > 2\r
-          && mSlicers[i]->GetRenderWindow()->GetSize()[1] > 2) {\r
-        mSlicers[i]->SetCurrentPosition(p[0], p[1], p[2], mSlicers[slicer]->GetMaxCurrentTSlice());\r
-        mSlicers[i]->UpdateCursorPosition();\r
-        if (current) { //do not display corner annotation if image is the one picked\r
-          mSlicers[i]->SetCurrentPosition(-VTK_DOUBLE_MAX,-VTK_DOUBLE_MAX,\r
-                                          -VTK_DOUBLE_MAX, mSlicers[slicer]->GetMaxCurrentTSlice());\r
-          mSlicers[i]->SetCursorColor(255,10,212);\r
-        } else {\r
-          mSlicers[i]->SetCursorColor(150,10,282);\r
-        }\r
-        switch (mSlicers[i]->GetSliceOrientation()) {\r
-        case vtkImageViewer2::SLICE_ORIENTATION_XY:\r
-          if (mSlicers[i]->GetSlice() != (int)lrint(z))\r
-            mSlicers[i]->SetSlice((int)lrint(z));\r
-          break;\r
-\r
-        case vtkImageViewer2::SLICE_ORIENTATION_XZ:\r
-          if (mSlicers[i]->GetSlice() != (int)lrint(y))\r
-            mSlicers[i]->SetSlice((int)lrint(y));\r
-          break;\r
-\r
-        case vtkImageViewer2::SLICE_ORIENTATION_YZ:\r
-          if (mSlicers[i]->GetSlice() != (int)lrint(x))\r
-            mSlicers[i]->SetSlice((int)lrint(x));\r
-          break;\r
-        }\r
-        \r
-        mSlicers[i]->Render();\r
-        \r
-        UpdateSlice(i);\r
-        UpdateTSlice(i);\r
-      }\r
-    }\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::UpdateLinked(int slicer)\r
-{ \r
-  double p[3], pt[3];\r
-  p[0] = mSlicers[slicer]->GetCurrentPosition()[0];\r
-  p[1] = mSlicers[slicer]->GetCurrentPosition()[1];\r
-  p[2] = mSlicers[slicer]->GetCurrentPosition()[2];\r
-  mSlicers[slicer]->GetSlicingTransform()->GetInverse()->TransformPoint(p, pt);\r
-  double x = (pt[0] - mSlicers[slicer]->GetInput()->GetOrigin()[0]) / mSlicers[slicer]->GetInput()->GetSpacing()[0];\r
-  double y = (pt[1] - mSlicers[slicer]->GetInput()->GetOrigin()[1]) / mSlicers[slicer]->GetInput()->GetSpacing()[1];\r
-  double z = (pt[2] - mSlicers[slicer]->GetInput()->GetOrigin()[2]) / mSlicers[slicer]->GetInput()->GetSpacing()[2];\r
-#if VTK_MAJOR_VERSION <= 5\r
-  if (x >= mSlicers[slicer]->GetInput()->GetWholeExtent()[0]-0.5 &&\r
-      x <= mSlicers[slicer]->GetInput()->GetWholeExtent()[1]+0.5 &&\r
-      y >= mSlicers[slicer]->GetInput()->GetWholeExtent()[2]-0.5 &&\r
-      y <= mSlicers[slicer]->GetInput()->GetWholeExtent()[3]+0.5 &&\r
-      z >= mSlicers[slicer]->GetInput()->GetWholeExtent()[4]-0.5 &&\r
-      z <= mSlicers[slicer]->GetInput()->GetWholeExtent()[5]+0.5)\r
-#else\r
-int extentImageReslice[6];\r
-mSlicers[slicer]->GetRegisterExtent(extentImageReslice);\r
-  if (x >= extentImageReslice[0]-0.5 &&\r
-      x <= extentImageReslice[1]+0.5 &&\r
-      y >= extentImageReslice[2]-0.5 &&\r
-      y <= extentImageReslice[3]+0.5 &&\r
-      z >= extentImageReslice[4]-0.5 &&\r
-      z <= extentImageReslice[5]+0.5)\r
-#endif\r
-  {\r
-    for (std::list<std::string>::const_iterator i = mLinkedId.begin(); i != mLinkedId.end(); i++) {\r
-               if (this->IsInvolvedInFusionSequence()) {\r
-                       //this SlicerManager is involved in fusionSequence => do not synchronize the times\r
-                       emit UpdateLinkManager(*i, slicer, p[0], p[1], p[2], -1);\r
-               }\r
-               else {\r
-                       emit UpdateLinkManager(*i, slicer, p[0], p[1], p[2], mSlicers[slicer]->GetMaxCurrentTSlice());\r
-               }\r
-    }\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::UpdateLinkedNavigation(vvSlicer *refSlicer, bool bPropagate)\r
-{ \r
-  vtkCamera *refCam = refSlicer->GetRenderer()->GetActiveCamera();\r
-\r
-  double refPosition[3];\r
-  refCam->GetPosition(refPosition);\r
-  refPosition[refSlicer->GetSliceOrientation()] = refSlicer->GetSlice() *\r
-      refSlicer->GetInput()->GetSpacing()[refSlicer->GetSliceOrientation()] +\r
-      refSlicer->GetInput()->GetOrigin()[refSlicer->GetSliceOrientation()];\r
-\r
-  refSlicer->GetSlicingTransform()->TransformPoint(refPosition, refPosition);\r
-  mSlicers[0]->GetSlicingTransform()->GetInverse()->TransformPoint(refPosition, refPosition);\r
-\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    vtkCamera *camera = mSlicers[i]->GetRenderer()->GetActiveCamera();\r
-    camera->SetParallelScale(refCam->GetParallelScale());\r
-\r
-    double position[3], focal[3];\r
-    camera->GetPosition(position);\r
-    camera->GetFocalPoint(focal);\r
-\r
-    for(int j=0; j<3; j++) {\r
-      if(j!=mSlicers[i]->GetSliceOrientation()) {\r
-        position[j] = refPosition[j];\r
-        focal[j]    = refPosition[j];\r
-      }\r
-    }\r
-\r
-    camera->SetFocalPoint(focal);\r
-    camera->SetPosition(position);\r
-\r
-    //Fix for bug #243\r
-    mSlicers[i]->ForceUpdateDisplayExtent();\r
-  }\r
-  \r
-  Render();\r
-  if(bPropagate)\r
-    for (std::list<std::string>::const_iterator i = mLinkedId.begin(); i != mLinkedId.end(); i++)\r
-      emit UpdateLinkedNavigation(*i, this, refSlicer);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-double vvSlicerManager::GetColorWindow() const\r
-{ \r
-  if (mSlicers.size())\r
-    return mSlicers[0]->GetColorWindow();\r
-  return -1;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-double vvSlicerManager::GetColorLevel() const\r
-{ \r
-  if (mSlicers.size())\r
-    return mSlicers[0]->GetColorLevel();\r
-  return -1;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-double vvSlicerManager::GetOverlayColorWindow() const\r
-{ \r
-  if (mSlicers.size())\r
-    return mSlicers[0]->GetOverlayColorWindow();\r
-  return -1;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-double vvSlicerManager::GetOverlayColorLevel() const\r
-{ \r
-  if (mSlicers.size())\r
-    return mSlicers[0]->GetOverlayColorLevel();\r
-  return -1;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-bool vvSlicerManager::GetLinkOverlayWindowLevel() const\r
-{ \r
-  if (mSlicers.size())\r
-    return mSlicers[0]->GetLinkOverlayWindowLevel();\r
-  return -1;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//------------------------------------------------------------------------------\r
-void vvSlicerManager::ResetTransformationToIdentity(const std::string actorType)\r
-{ \r
-  if(actorType == "image")\r
-    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)\r
-      this->GetImage()->GetTransform()[i]->Identity();\r
-  else if(actorType == "overlay")\r
-    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)\r
-      this->GetSlicer(0)->GetOverlay()->GetTransform()[i]->Identity();\r
-  else if(actorType == "fusion")\r
-    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)\r
-      this->GetSlicer(0)->GetFusion()->GetTransform()[i]->Identity();\r
-  else if(actorType == "fusionSequence") //TODO: Check what should really be done here\r
-    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)\r
-      this->GetSlicer(0)->GetFusion()->GetTransform()[i]->Identity();\r
-  else if(actorType == "vf")\r
-    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)\r
-      this->GetVF()->GetTransform()[i]->Identity();\r
-  else\r
-    return;\r
-\r
-  for(int i=0; i< this->GetNumberOfSlicers(); i++){\r
-    this->GetSlicer(i)->ForceUpdateDisplayExtent();\r
-    this->GetSlicer(i)->ResetCamera();\r
-    this->GetSlicer(i)->Render();\r
-  }\r
-}\r
-//------------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::Render()\r
-{ \r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->Render();\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::GenerateDefaultLookupTable()\r
-{ \r
-  SetPreset(mPreset);\r
-  SetColorMap(mColorMap);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::Reload()\r
-{ \r
-  mReader->Update(mType);\r
-  mImage=mReader->GetOutput();\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetImage(mImage);\r
-  }\r
-  \r
-  //if this image is the primary sequence of a fusion sequence, then the main transform matrix should be updated.\r
-  if (this->IsMainSequenceOfFusionSequence()) {\r
-         SetFusionSequenceMainTransformMatrix( mImage->GetTransform()[0]->GetMatrix() );\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::ReloadFusion()\r
-{ \r
-  mFusionReader->Update(mImage->GetNumberOfDimensions(),mFusionComponent.c_str(),mType);\r
-\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetFusion(mFusionReader->GetOutput());\r
-    mSlicers[i]->Render();\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-//the secondary sequence is being reloaded.\r
-void vvSlicerManager::ReloadFusionSequence()\r
-{ \r
-  //  this is to keep the slice thickness, which needs to be artificially increased for visualization\r
-  double sp_x, sp_y, sp_z;\r
-  this->GetImage()->GetVTKImages()[0]->GetSpacing(sp_x, sp_y, sp_z);\r
-\r
-  mFusionSequenceReader->Update(mImage->GetNumberOfDimensions(),mFusionComponent.c_str(),vvImageReader::MERGEDWITHTIME);\r
-\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetFusion(mFusionSequenceReader->GetOutput(), 1);\r
-    mSlicers[i]->Render();\r
-  }\r
-\r
-  //Update the slider\r
-  mFusionSequenceNbFrames = mFusionSequenceReader->GetOutput()->GetTransform().size();\r
-  if (mFusionSequenceFrameIndex>=mFusionSequenceNbFrames) {\r
-         mFusionSequenceFrameIndex=0;\r
-  }\r
-\r
-  //Update the list of initial transforms\r
-  mFusionSequenceListInitialTransformMatrices.clear();\r
-  for (unsigned i=0 ; i<mFusionSequenceNbFrames ; i++) {\r
-         this->AddFusionSequenceInitialTransformMatrices( mFusionSequenceReader->GetOutput()->GetTransform()[i]->GetMatrix() );\r
-  }\r
-\r
-  //  also update the slice thickness\r
-  for (unsigned i=0 ; i<this->GetImage()->GetTransform().size() ; i++) {\r
-    sp_x = this->GetImage()->GetVTKImages()[i]->GetSpacing()[0];\r
-    sp_y = this->GetImage()->GetVTKImages()[i]->GetSpacing()[1];\r
-    this->GetImage()->GetVTKImages()[i]->SetSpacing( sp_x, sp_y, sp_z);\r
-  }\r
-\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::ReloadOverlay()\r
-{ \r
-  mOverlayReader->Update(mImage->GetNumberOfDimensions(),mOverlayComponent.c_str(),mType);\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetOverlay(mOverlayReader->GetOutput());\r
-    mSlicers[i]->Render();\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::ReloadVF()\r
-{ \r
-  mVectorReader->Update(vvImageReader::VECTORFIELD); //deletes the old images through the VF::Init() function\r
-  mVF=mVectorReader->GetOutput();\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetVF(mVF);\r
-    mSlicers[i]->Render();\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::RemoveActor(const std::string& actor_type, int overlay_index)\r
-{ \r
-  if (actor_type =="overlay")\r
-    mOverlayReader = NULL;\r
-\r
-  if (actor_type =="fusion")\r
-    mFusionReader = NULL;\r
-\r
-  if (actor_type =="fusionSequence") {\r
-    mFusionSequenceReader = NULL;\r
-  }\r
-\r
-  for (unsigned int i = 0; i < mSlicers.size(); i++)\r
-    mSlicers[i]->RemoveActor(actor_type,overlay_index);\r
-\r
-  if (actor_type=="vector") {\r
-    mVF=NULL;\r
-    mVectorReader=NULL;\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::RemoveActors()\r
-{ \r
-  ///This method leaks a few objects. See RemoveActor for what a\r
-  ///correct implementation would look like\r
-  //DS -> probably due to the reader (now released in the\r
-  //RemoveActor() function. (I hope)\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-    mSlicers[i]->SetDisplayMode(0);\r
-    mSlicers[i]->GetRenderer()->RemoveActor(mSlicers[i]->GetImageActor());\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::UpdateInfoOnCursorPosition(int slicer)\r
-{ \r
-  //  int view = mSlicers[slicer]->GetSliceOrientation();\r
-  //  int slice = mSlicers[slicer]->GetSlice();\r
-  double x = mSlicers[slicer]->GetCurrentPosition()[0];\r
-  double y = mSlicers[slicer]->GetCurrentPosition()[1];\r
-  double z = mSlicers[slicer]->GetCurrentPosition()[2];\r
-  double xyz[3], xyzTransform[3];\r
-  xyz[0] = x;\r
-  xyz[1] = y;\r
-  xyz[2] = z;\r
-  mSlicers[slicer]->GetSlicingTransform()->GetInverse()->TransformPoint(xyz, xyzTransform);\r
-  double X = (xyzTransform[0] - mSlicers[slicer]->GetInput()->GetOrigin()[0])/mSlicers[slicer]->GetInput()->GetSpacing()[0];\r
-  double Y = (xyzTransform[1] - mSlicers[slicer]->GetInput()->GetOrigin()[1])/mSlicers[slicer]->GetInput()->GetSpacing()[1];\r
-  double Z = (xyzTransform[2] - mSlicers[slicer]->GetInput()->GetOrigin()[2])/mSlicers[slicer]->GetInput()->GetSpacing()[2];\r
-  double value = -VTK_DOUBLE_MAX;\r
-  int displayVec = 0;\r
-  double xVec=0, yVec=0, zVec=0, valueVec=0;\r
-  int displayOver = 0;\r
-  int displayFus = 0;\r
-  double valueOver=0, valueFus=0;\r
-#if VTK_MAJOR_VERSION <= 5\r
-    if (X >= mSlicers[slicer]->GetInput()->GetWholeExtent()[0] -0.5 &&\r
-      X <= mSlicers[slicer]->GetInput()->GetWholeExtent()[1] +0.5 &&\r
-      Y >= mSlicers[slicer]->GetInput()->GetWholeExtent()[2] -0.5 &&\r
-      Y <= mSlicers[slicer]->GetInput()->GetWholeExtent()[3] +0.5 &&\r
-      Z >= mSlicers[slicer]->GetInput()->GetWholeExtent()[4] -0.5 &&\r
-      Z <= mSlicers[slicer]->GetInput()->GetWholeExtent()[5] +0.5)\r
-#else\r
-int extentImageReslice[6];\r
-mSlicers[slicer]->GetRegisterExtent(extentImageReslice);\r
-    if (X >= extentImageReslice[0] -0.5 &&\r
-      X <= extentImageReslice[1] +0.5 &&\r
-      Y >= extentImageReslice[2] -0.5 &&\r
-      Y <= extentImageReslice[3] +0.5 &&\r
-      Z >= extentImageReslice[4] -0.5 &&\r
-      Z <= extentImageReslice[5] +0.5)\r
-#endif\r
-    {\r
-    value = this->GetScalarComponentAsDouble(mSlicers[slicer]->GetInput(), X, Y, Z);\r
-\r
-    if (mSlicers[slicer]->GetVFActor() ) {\r
-      displayVec = 1;\r
-      unsigned int currentTime = mSlicers[slicer]->GetMaxCurrentTSlice();\r
-      vtkImageData *vf = NULL;\r
-\r
-      if (mSlicers[slicer]->GetVF()->GetVTKImages().size() > currentTime)\r
-        vf = mSlicers[slicer]->GetVF()->GetVTKImages()[currentTime];\r
-      else\r
-        vf = mSlicers[slicer]->GetVF()->GetVTKImages()[0];\r
-\r
-      if (vf) {\r
-        double Xvf = (x - vf->GetOrigin()[0])/ vf->GetSpacing()[0];\r
-        double Yvf = (y - vf->GetOrigin()[1])/ vf->GetSpacing()[1];\r
-        double Zvf = (z - vf->GetOrigin()[2])/ vf->GetSpacing()[2];\r
-        xVec = this->GetScalarComponentAsDouble( vf, Xvf, Yvf, Zvf, 0);\r
-        yVec = this->GetScalarComponentAsDouble( vf, Xvf, Yvf, Zvf, 1);\r
-        zVec = this->GetScalarComponentAsDouble( vf, Xvf, Yvf, Zvf, 2);\r
-        valueVec = sqrt(xVec*xVec + yVec*yVec + zVec*zVec);\r
-      }\r
-    }\r
-    if (mSlicers[slicer]->GetOverlayActor() ) {\r
-      displayOver = 1;\r
-      vtkImageData *overlay = dynamic_cast<vtkImageData*>(mSlicers[slicer]->GetOverlayMapper()->GetInput());\r
-      double Xover = (x - overlay->GetOrigin()[0]) / overlay->GetSpacing()[0];\r
-      double Yover = (y - overlay->GetOrigin()[1]) / overlay->GetSpacing()[1];\r
-      double Zover = (z - overlay->GetOrigin()[2]) / overlay->GetSpacing()[2];\r
-      valueOver = this->GetScalarComponentAsDouble(overlay, Xover, Yover, Zover);\r
-    }\r
-\r
-       if ( mSlicers[slicer]->GetFusionActor() ) {\r
-               displayFus = 1;\r
-               vtkImageData *fusion = dynamic_cast<vtkImageData*>(mSlicers[slicer]->GetFusionMapper()->GetInput());\r
-               double Xover = (x - fusion->GetOrigin()[0]) / fusion->GetSpacing()[0];\r
-               double Yover = (y - fusion->GetOrigin()[1]) / fusion->GetSpacing()[1];\r
-               double Zover = (z - fusion->GetOrigin()[2]) / fusion->GetSpacing()[2];\r
-               valueFus = this->GetScalarComponentAsDouble(fusion, Xover, Yover, Zover);\r
-       }\r
-       else if (this->IsInvolvedInFusionSequence()) { \r
-    //if the cursor moves over the 'independent' version of the secondary sequence\r
-    //do not update the panel, just keep it as it is.\r
-               displayFus = 1;\r
-               valueFus = std::numeric_limits<double>::quiet_NaN();\r
-       }\r
-\r
-    emit UpdatePosition(mSlicers[slicer]->GetCursorVisibility(),\r
-                        x,y,z,X,Y,Z,value);\r
-    emit UpdateVector(displayVec,xVec, yVec, zVec, valueVec);\r
-    emit UpdateOverlay(displayOver,valueOver,value);\r
-    emit UpdateFusion(displayFus,valueFus);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::Activated()\r
-{ \r
-  emit currentImageChanged(mId);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::Picked()\r
-{ \r
-  emit currentPickedImageChanged(mId);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::UpdateWindowLevel()\r
-{ \r
-  emit WindowLevelChanged();\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::UpdateSlice(int slicer)\r
-{ \r
-  if (mPreviousSlice[slicer] == mSlicers[slicer]->GetSlice()) {\r
-    //DD("============= NOTHING");\r
-    return;\r
-  }\r
-  emit UpdateSlice(slicer, mSlicers[slicer]->GetSlice());\r
-  mSlicers[slicer]->Render(); // DS <-- I add this, this could/must be the only Render ...\r
-  mPreviousSlice[slicer] = mSlicers[slicer]->GetSlice();\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::UpdateTSlice(int slicer)\r
-{ \r
-  int slice = mSlicers[slicer]->GetSlice();\r
-\r
-  int tslice = mSlicers[slicer]->GetMaxCurrentTSlice();\r
-  //if (this->IsInvolvedInFusionSequence()) tslice = mSlicers[slicer]->GetTSlice(); //actually, this is handled by the Slicer\r
-\r
-  if (mPreviousSlice[slicer] == slice) {\r
-    if (mPreviousTSlice[slicer] == tslice) {\r
-      //      DD("************** NOTHING ***********");\r
-      return;\r
-    }\r
-  }\r
-  mPreviousSlice[slicer] = slice;\r
-  mPreviousTSlice[slicer] = tslice;\r
-\r
-  emit UpdateTSlice(slicer, tslice, mFusionSequenceInvolvementCode);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::UpdateSliceRange(int slicer)\r
-{ \r
-  emit UpdateSliceRange(slicer,\r
-                        mSlicers[slicer]->GetSliceRange()[0], mSlicers[slicer]->GetSliceRange()[1],\r
-                        0,mSlicers[slicer]->GetTMax());\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetSlicingPreset(SlicingPresetType preset)\r
-{ \r
-  if(mSlicingPreset==preset)\r
-    return;\r
-\r
-  vtkMatrix4x4 *imageTransformInverse = vtkMatrix4x4::New();\r
-  mImage->GetTransform()[this->GetTSlice()]->GetInverse(imageTransformInverse);\r
-\r
-  for(int i=0; i< this->GetNumberOfSlicers(); i++){\r
-    vvSlicer *s = this->GetSlicer(i);\r
-    switch(preset)\r
-    {\r
-    case WORLD_SLICING:\r
-      s->GetSlicingTransform()->Identity();\r
-      break;\r
-    case VOXELS_SLICING:\r
-      s->GetSlicingTransform()->SetMatrix(imageTransformInverse);\r
-      break;\r
-    default:\r
-      imageTransformInverse->Delete();\r
-      return;\r
-    }\r
-    s->ForceUpdateDisplayExtent();\r
-#if VTK_MAJOR_VERSION <= 5\r
-    s->SetSlice((s->GetInput()->GetWholeExtent()[s->GetSliceOrientation()*2+1]\r
-                +s->GetInput()->GetWholeExtent()[s->GetSliceOrientation()*2])/2.0);\r
-#else\r
-    int extentImageReslice[6];\r
-    s->GetRegisterExtent(extentImageReslice);\r
-    s->SetSlice((extentImageReslice[s->GetSliceOrientation()*2+1]\r
-                +extentImageReslice[s->GetSliceOrientation()*2])/2.0);\r
-#endif\r
-    s->ResetCamera();\r
-    s->Render();\r
-  }\r
-\r
-  imageTransformInverse->Delete();\r
-  mSlicingPreset = preset;\r
-}\r
-\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetPreset(int preset)\r
-{ \r
-\r
-  //vtkLookupTable* LUT = static_cast<vtkLookupTable*>(mSlicers[0]->GetWindowLevel()->GetLookupTable());\r
-  double window = mSlicers[0]->GetColorWindow();\r
-  double level = mSlicers[0]->GetColorLevel();\r
-\r
-  std::string component_type=mImage->GetScalarTypeAsITKString();\r
-  switch (preset) {\r
-  case WL_AUTO:\r
-    double range[2];\r
-    mImage->GetScalarRange(range);\r
-    window = range[1] - range[0];\r
-    level = (range[1] + range[0])* 0.5;\r
-    break;\r
-  case WL_HOUNSFIELD:\r
-    window = 2000;\r
-    level = 0;\r
-    break;\r
-  case WL_SOFTTISSUE:\r
-    window = 400;\r
-    level = 20;\r
-    break;\r
-  case WL_LUNGS: // lungs (same as FOCAL)\r
-    window = 1700;\r
-    level = -300;\r
-    break;\r
-  case WL_BONES:\r
-    window = 1000;\r
-    level = 500;\r
-    break;\r
-  case WL_HEAD:\r
-    window = 200;\r
-    level = 70;\r
-    break;\r
-  case WL_BINARY:\r
-    window = 1;\r
-    level = 0.5;\r
-    break;\r
-  case WL_USER:\r
-    break;\r
-  case WL_VENTILATION:\r
-    window=1.;\r
-    level=0.;\r
-    break;\r
-  }\r
-  mPreset = preset;\r
-  this->SetColorWindow(window);\r
-  this->SetColorLevel(level);\r
-\r
-  //if (LUT)\r
-  //{\r
-  //    SetColorMap(-1);\r
-  //}\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetLocalColorWindowing(const int slicer, const bool bCtrlKey)\r
-{ \r
-  double min, max;\r
-  if(bCtrlKey && this->mSlicers[slicer]->GetFusion()) {\r
-    int t = mSlicers[slicer]->GetFusionTSlice();\r
-    this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max,\r
-                                                          this->mSlicers[slicer]->GetFusion()->GetVTKImages()[t],\r
-                                                          this->mSlicers[slicer]->GetConcatenatedFusionTransform());\r
-    this->SetFusionWindow(max-min);\r
-    this->SetFusionLevel(0.5*(min+max));\r
-    this->SetColorMap(mColorMap);\r
-  }\r
-  else if(bCtrlKey && this->mSlicers[slicer]->GetOverlay()) {\r
-    int t = mSlicers[slicer]->GetOverlayTSlice();\r
-    this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max,\r
-                                                          this->mSlicers[slicer]->GetOverlay()->GetVTKImages()[t],\r
-                                                          this->mSlicers[slicer]->GetConcatenatedOverlayTransform());\r
-    if(this->mSlicers[slicer]->GetLinkOverlayWindowLevel()){\r
-      this->SetColorWindow(max-min);\r
-      this->SetColorLevel(0.5*(min+max));\r
-    } else {\r
-      this->SetOverlayColorWindow(max-min);\r
-      this->SetOverlayColorLevel(0.5*(min+max));\r
-    }\r
-  }\r
-  else {\r
-    int t = this->GetTSlice();\r
-    this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max,\r
-                                                          this->mSlicers[slicer]->GetImage()->GetVTKImages()[t],\r
-                                                          this->mSlicers[slicer]->GetConcatenatedTransform());\r
-    this->SetColorWindow(max-min);\r
-    this->SetColorLevel(0.5*(min+max));\r
-    this->SetPreset(WL_USER);\r
-  }\r
-  this->Render();\r
-  this->UpdateWindowLevel();\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::SetColorMap(int colormap)\r
-{ \r
-  double range[2];\r
-\r
-  range[0] = mSlicers[0]->GetInput()->GetScalarRange()[0];\r
-  range[1] = mSlicers[0]->GetInput()->GetScalarRange()[1];\r
-\r
-  double window = mSlicers[0]->GetWindowLevel()->GetWindow();\r
-  double level = mSlicers[0]->GetWindowLevel()->GetLevel();\r
-\r
-  vtkLookupTable* LUT = static_cast<vtkLookupTable*>(mSlicers[0]->GetWindowLevel()->GetLookupTable());\r
-  switch (colormap) {\r
-  case -1:\r
-    break;\r
-  case 0:\r
-    LUT = NULL;\r
-    break;\r
-  case 1:\r
-    if (LUT == NULL)\r
-      LUT = vtkLookupTable::New();\r
-    LUT->SetValueRange(0,1);\r
-    LUT->SetSaturationRange(1,1);\r
-    LUT->SetHueRange(0,0.18);\r
-    break;\r
-  case 2:\r
-    if (LUT == NULL)\r
-      LUT = vtkLookupTable::New();\r
-    LUT->SetValueRange(0,1);\r
-    LUT->SetSaturationRange(1,1);\r
-    LUT->SetHueRange(0.4,0.80);\r
-    break;\r
-  case 3:\r
-    if (LUT == NULL)\r
-      LUT = vtkLookupTable::New();\r
-    LUT->SetValueRange(0.5,1);\r
-    LUT->SetSaturationRange(1,1);\r
-    LUT->SetHueRange(0.666,0);\r
-    break;\r
-  case 4:\r
-    if (LUT == NULL)\r
-      LUT = vtkLookupTable::New();\r
-    LUT->SetValueRange(1,1);\r
-    LUT->SetSaturationRange(1,1);\r
-    LUT->SetHueRange(0,1);\r
-    LUT->SetAlphaRange(1, 1);\r
-    break;\r
-  case 5:\r
-    if (LUT == NULL)\r
-      LUT = vtkLookupTable::New();\r
-    LUT->SetValueRange(1,1);\r
-    LUT->SetSaturationRange(1,1);\r
-    LUT->SetHueRange(1,0.1);\r
-    //LUT->SetRampToLinear();\r
-    break;\r
-  }\r
-  if (LUT) {\r
-    LUT->SetTableRange(level-fabs(window)/2,level+fabs(window)/2);\r
-    LUT->Build();\r
-  }\r
-  vtkWindowLevelLookupTable* fusLUT = NULL;\r
-\r
-  //FUSION / FUSION SEQUENCE\r
-  if (mSlicers[0]->GetFusion()) { // && mFusionColorMap >= 0) {\r
-    fusLUT = vtkWindowLevelLookupTable::New();\r
-    double fusRange [2];\r
-    fusRange[0] = mFusionLevel - mFusionWindow/2;\r
-    fusRange[1] = mFusionLevel + mFusionWindow/2;\r
-\r
-    //check whether it is actually a fusionSequence or a fusion, before invoking mFusionReader...\r
-    double* frange;\r
-    if (this->IsInvolvedInFusionSequence()) \r
-      frange = mFusionSequenceReader->GetOutput()->GetVTKImages()[0]->GetScalarRange();\r
-    else\r
-      frange = mFusionReader->GetOutput()->GetVTKImages()[0]->GetScalarRange();\r
-\r
-    fusLUT->SetTableRange(frange);\r
-    fusLUT->SetValueRange(1,1);\r
-    fusLUT->SetSaturationRange(1,1);\r
-    fusLUT->SetAlphaRange(1, 1);\r
-    fusLUT->SetWindow(mFusionWindow);\r
-    fusLUT->SetLevel(mFusionLevel);\r
-    if (mFusionColorMap == 1)\r
-      fusLUT->SetHueRange(0,0.18);\r
-    else if (mFusionColorMap == 2)\r
-      fusLUT->SetHueRange(0.4,0.80);\r
-    else if (mFusionColorMap == 3)\r
-    {\r
-      fusLUT->SetHueRange(0.666, 0);\r
-      fusLUT->SetValueRange(0.5, 1);\r
-    }\r
-    else if (mFusionColorMap == 4)\r
-      fusLUT->SetHueRange(0,1);\r
-    else if (mFusionColorMap <= 0)\r
-    {\r
-      fusLUT->SetValueRange(0,1);\r
-      fusLUT->SetSaturationRange(0,0);\r
-    }\r
-\r
-    fusLUT->ForceBuild();\r
-    double v[4];\r
-    // set color table transparency\r
-    //double alpha_range=(double)mFusionThresOpacity/10;\r
-    double range_end = fusRange[0] + (double)mFusionThresOpacity*(fusRange[1] - fusRange[0])/100;\r
-    double curr_value = fusRange[0];\r
-    int nvalues = fusLUT->GetNumberOfTableValues();\r
-    for (double i = 0; curr_value < range_end; i++) {  \r
-      fusLUT->GetTableValue(i, v);\r
-      v[3] = 0;\r
-      //if (curr_value >= -alpha_range && curr_value <= alpha_range) v[3] = pow(fabs(curr_value/alpha_range),2);\r
-      //else v[3] = 1;\r
-      fusLUT->SetTableValue(i, v);\r
-      curr_value += (fusRange[1] - fusRange[0])/nvalues;\r
-    }\r
-  }\r
-  for ( unsigned int i = 0; i < mSlicers.size(); i++) {\r
-\r
-    if (mSlicers[i]->GetOverlay()) {\r
-      vtkLookupTable* supLUT = vtkLookupTable::New();\r
-      supLUT->SetTableRange(range[0],range[1]);\r
-      supLUT->SetValueRange(1,1);\r
-      supLUT->SetSaturationRange(1,1);\r
-      supLUT->SetHueRange(double(mOverlayColor)/360,double(mOverlayColor)/360);\r
-      supLUT->Build();\r
-      vtkLookupTable* invLUT = vtkLookupTable::New();\r
-      invLUT->SetTableRange(range[0],range[1]);\r
-      invLUT->SetValueRange(1,1);\r
-      invLUT->SetSaturationRange(1,1);\r
-      invLUT->SetHueRange(double((mOverlayColor+180)%360)/360,double((mOverlayColor+180)%360)/360);\r
-      invLUT->Build();\r
-      mSlicers[i]->GetWindowLevel()->SetLookupTable(supLUT);\r
-      mSlicers[i]->GetOverlayMapper()->SetLookupTable(invLUT);\r
-      invLUT->Delete();\r
-      supLUT->Delete();\r
-    } else if (mSlicers[i]->GetOverlay()) {\r
-      mSlicers[i]->GetWindowLevel()->SetLookupTable(LUT);\r
-    } else {\r
-      mSlicers[i]->GetWindowLevel()->SetLookupTable(LUT);\r
-    }\r
-\r
-    if (mSlicers[i]->GetFusion()) {\r
-      mSlicers[i]->ShowFusionLegend(mFusionShowLegend);\r
-      mSlicers[i]->GetFusionMapper()->SetLookupTable(fusLUT);\r
-      mSlicers[i]->GetFusionActor()->SetOpacity(double(mFusionOpacity)/100);\r
-    }\r
-  }\r
-  if (fusLUT)\r
-    fusLUT->Delete();\r
-  if (colormap >= 0)\r
-    mColorMap = colormap;\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-\r
-//----------------------------------------------------------------------------\r
-vvLandmarks* vvSlicerManager::GetLandmarks()\r
-{ \r
-  if (mLandmarks == NULL) {\r
-    mLandmarks = new vvLandmarks(mSlicers[0]->GetTMax()+1);\r
-    for (unsigned int i = 0; i < mSlicers.size(); i++)\r
-      mSlicers[i]->SetLandmarks(mLandmarks);\r
-  }\r
-  return mLandmarks;\r
-}\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::AddNewLandmark(float x,float y,float z,float t)\r
-{ \r
-    emit callAddLandmark(x,y,z,t);\r
-}\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::AddLandmark(float x,float y,float z,float t)\r
-{ \r
-  double x_index = (x - mSlicers[0]->GetInput()->GetOrigin()[0])/mSlicers[0]->GetInput()->GetSpacing()[0];\r
-  double y_index = (y - mSlicers[0]->GetInput()->GetOrigin()[1])/mSlicers[0]->GetInput()->GetSpacing()[1];\r
-  double z_index = (z - mSlicers[0]->GetInput()->GetOrigin()[2])/mSlicers[0]->GetInput()->GetSpacing()[2];\r
-#if VTK_MAJOR_VERSION <= 5\r
-  if (x_index >= mSlicers[0]->GetInput()->GetWholeExtent()[0]-0.5 &&\r
-      x_index <= mSlicers[0]->GetInput()->GetWholeExtent()[1]+0.5 &&\r
-      y_index >= mSlicers[0]->GetInput()->GetWholeExtent()[2]-0.5 &&\r
-      y_index <= mSlicers[0]->GetInput()->GetWholeExtent()[3]+0.5 &&\r
-      z_index >= mSlicers[0]->GetInput()->GetWholeExtent()[4]-0.5 &&\r
-      z_index <= mSlicers[0]->GetInput()->GetWholeExtent()[5]+0.5)\r
-#else\r
-  int extentImageReslice[6];\r
-  mSlicers[0]->GetRegisterExtent(extentImageReslice);\r
-  if (x_index >= extentImageReslice[0]-0.5 &&\r
-      x_index <= extentImageReslice[1]+0.5 &&\r
-      y_index >= extentImageReslice[2]-0.5 &&\r
-      y_index <= extentImageReslice[3]+0.5 &&\r
-      z_index >= extentImageReslice[4]-0.5 &&\r
-      z_index <= extentImageReslice[5]+0.5)\r
-#endif\r
-  {\r
-    double value = this->GetScalarComponentAsDouble(mSlicers[mSelectedSlicer]->GetInput(), x_index, y_index, z_index); //Value in selected Slicer (not 0): bug #2848\r
-    this->GetLandmarks()->AddLandmark(x,y,z,t,value);\r
-    emit LandmarkAdded();\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::AddLandmarkProfile(float x,float y,float z,float t)\r
-{ \r
-  double x_index = (x - mSlicers[0]->GetInput()->GetOrigin()[0])/mSlicers[0]->GetInput()->GetSpacing()[0];\r
-  double y_index = (y - mSlicers[0]->GetInput()->GetOrigin()[1])/mSlicers[0]->GetInput()->GetSpacing()[1];\r
-  double z_index = (z - mSlicers[0]->GetInput()->GetOrigin()[2])/mSlicers[0]->GetInput()->GetSpacing()[2];\r
-#if VTK_MAJOR_VERSION <= 5\r
-  if (x_index >= mSlicers[0]->GetInput()->GetWholeExtent()[0]-0.5 &&\r
-      x_index <= mSlicers[0]->GetInput()->GetWholeExtent()[1]+0.5 &&\r
-      y_index >= mSlicers[0]->GetInput()->GetWholeExtent()[2]-0.5 &&\r
-      y_index <= mSlicers[0]->GetInput()->GetWholeExtent()[3]+0.5 &&\r
-      z_index >= mSlicers[0]->GetInput()->GetWholeExtent()[4]-0.5 &&\r
-      z_index <= mSlicers[0]->GetInput()->GetWholeExtent()[5]+0.5)\r
-#else\r
-  int extentImageReslice[6];\r
-  mSlicers[0]->GetRegisterExtent(extentImageReslice);\r
-  if (x_index >= extentImageReslice[0]-0.5 &&\r
-      x_index <= extentImageReslice[1]+0.5 &&\r
-      y_index >= extentImageReslice[2]-0.5 &&\r
-      y_index <= extentImageReslice[3]+0.5 &&\r
-      z_index >= extentImageReslice[4]-0.5 &&\r
-      z_index <= extentImageReslice[5]+0.5)\r
-#endif\r
-  {\r
-    double value = this->GetScalarComponentAsDouble(mSlicers[mSelectedSlicer]->GetInput(), x_index, y_index, z_index); //Value in selected Slicer (not 0): bug #2848\r
-    this->GetLandmarks()->AddLandmark(x,y,z,t,value);\r
-  }\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::PrevImage(int slicer)\r
-{ \r
-  emit ChangeImageWithIndexOffset(this, slicer, -1);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::NextImage(int slicer)\r
-{ \r
-  emit ChangeImageWithIndexOffset(this, slicer,  1);\r
-}\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-void vvSlicerManager::VerticalSliderHasChanged(int slicer, int slice)\r
-{ \r
-  emit AVerticalSliderHasChanged(slicer, slice);\r
-}\r
-\r
-//----------------------------------------------------------------------------\r
-\r
-//----------------------------------------------------------------------------\r
-double vvSlicerManager::GetScalarComponentAsDouble(vtkImageData *image, double X, double Y, double Z, int component)\r
-{ \r
-  int ix, iy, iz;\r
-  return mSlicers[0]->GetScalarComponentAsDouble(image, X, Y, Z, ix, iy, iz, component);\r
-}\r
-//----------------------------------------------------------------------------\r
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to:
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+  ======================================================================-====*/
+
+#include "vvSlicerManager.h"
+#include "vvSlicer.h"
+#include "vvImage.h"
+#include "vvSlicerManagerCommand.h"
+#include "vvInteractorStyleNavigator.h"
+#include "vvLandmarks.h"
+#include "vvMesh.h"
+#include "vvBlendImageActor.h"
+
+#include <vtkVersion.h>
+#include <vtkStreamingDemandDrivenPipeline.h>
+#include <vtkInformation.h>
+#include <vtkImageActor.h>
+#include <vtkImageData.h>
+#include <vtkRenderWindow.h>
+#include <vtkRendererCollection.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkImageMapToWindowLevelColors.h>
+#include <vtkWindowLevelLookupTable.h>
+#include <vtkColorTransferFunction.h>
+#include <vtkImageClip.h>
+#include <vtkLODActor.h>
+#include <vtkPointData.h>
+#include <vtksys/SystemTools.hxx>
+#include <vtkCamera.h>
+
+#include <qfileinfo.h>
+#include <QMessageBox>
+//----------------------------------------------------------------------------
+vvSlicerManager::vvSlicerManager(int numberOfSlicers)
+{ 
+
+  connect(this, SIGNAL(callAddLandmark(float,float,float,float)), this, SLOT(AddLandmark(float,float,float,float)));
+
+  mFileName = "";
+  mId = "";
+  mVFName = "";
+  mOverlayName = "";
+  mFusionName = "";
+  mVFId = "";
+  mLastError = "";
+  mType = vvImageReader::UNDEFINEDIMAGETYPE;
+  mColorMap = 0;
+  mPreset = 0;
+  mOverlayColor = 130;
+
+  mFusionOpacity = 30;
+  mFusionThresOpacity = 1;
+  mFusionColorMap = 3;
+  mFusionWindow = 1000;
+  mFusionLevel = 1000;
+  mFusionShowLegend = true;
+  
+  mFusionSequenceInvolvementCode = -1;
+  mFusionSequenceIndexLinkedManager = -1;
+  mFusionSequenceFrameIndex = -1;
+  mFusionSequenceNbFrames = 0;
+  mFusionSequenceSpatialSyncFlag = false;
+  mFusionSequenceTemporalSyncFlag = false;
+
+  mLandmarks = NULL;
+  mLinkedId.resize(0);
+
+  for ( int i = 0; i < numberOfSlicers; i++) {
+    mSlicers.push_back(vtkSmartPointer<vvSlicer>::New());
+    mSlicers[i]->SetSlicerNumber(i);
+  }
+  mSelectedSlicer = -1;
+  
+  mPreviousSlice.resize(numberOfSlicers, 0);
+  mPreviousTSlice.resize(numberOfSlicers, 0);
+  mSlicingPreset = WORLD_SLICING;
+
+  
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+vvSlicerManager::~vvSlicerManager()
+{ 
+  if (mLandmarks)
+    delete mLandmarks;
+}
+//----------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+void vvSlicerManager::SetFilename(std::string filename, int number)
+{ 
+  mFileName = filename;
+  mFileName = vtksys::SystemTools::GetFilenameName(mFileName);
+  mBaseFileName = vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(mFileName));
+  mBaseFileNameNumber = number;
+
+  mFileName = mBaseFileName;
+  if (number != 0) {
+    mFileName.append("_"+clitk::toString(number));
+  }
+  mFileName.append(vtksys::SystemTools::GetFilenameLastExtension(filename));
+
+  for(unsigned int i=0; i<mSlicers.size(); i++) {
+    mSlicers[i]->SetFileName(mFileName);//vtksys::SystemTools::GetFilenameWithoutLastExtension(filename));
+  }
+  
+}
+//------------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::AddContour(vvMesh::Pointer contour,bool propagate)
+{ 
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->AddContour(contour,propagate);
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::ToggleContourSuperposition()
+{ 
+  for ( unsigned int i = 0; i < mSlicers.size(); i++)
+    mSlicers[i]->ToggleContourSuperposition();
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+std::string vvSlicerManager::GetListOfAbsoluteFilePathInOneString(const std::string &actorType)
+{ 
+  vvImageReader *reader = NULL;
+
+  if(actorType=="image")
+    reader = mReader;
+  else if(actorType=="overlay")
+    reader = mOverlayReader;
+  else if(actorType=="fusion")
+    reader = mFusionReader;
+  else if(actorType=="vector")
+    reader = mVectorReader;
+  else if(actorType=="fusionSequence")
+       reader = mFusionSequenceReader;
+
+  if(!reader)
+    return "";
+
+  std::string list;
+  for(unsigned int i=0; i<reader->GetInputFilenames().size(); i++){
+    QFileInfo fileinfo(reader->GetInputFilenames()[i].c_str()); //Do not show the path
+    if(i)
+      list += '\n';
+    list += fileinfo.absoluteFilePath().toStdString();
+  }
+  return list;
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+bool vvSlicerManager::SetImage(std::string filename, vvImageReader::LoadedImageType type, int n, unsigned int slice)
+{ 
+  mType = type;
+  if (mReader.IsNull())
+    mReader = vvImageReader::New();
+  std::vector<std::string> filenames;
+  filenames.push_back(filename);
+  mReader->SetInputFilenames(filenames);
+  mReader->SetSlice(slice); // Only used for SLICED type
+  mReader->Update(type);
+
+  SetFilename(filename, n);
+  //  mFileName = vtksys::SystemTools::GetFilenameName(mFileName);
+  //mBaseFileName = vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(mFileName));
+  //mBaseFileNameNumber = n;
+
+  if (mReader->GetLastError().size() == 0) {
+    mImage=mReader->GetOutput();
+    for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+      mSlicers[i]->SetFileName(vtksys::SystemTools::GetFilenameWithoutLastExtension(filename));
+      mSlicers[i]->SetImage(mReader->GetOutput());
+    }
+  } else {
+    mLastError = mReader->GetLastError();
+    return false;
+  }
+  // if (n!=0) {
+  //   mFileName.append("_"+clitk::toString(n));
+  // }
+  return true;
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetImage(vvImage::Pointer image)
+{ 
+  mImage=image;
+  for (unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetImage(image);
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+bool vvSlicerManager::SetImages(std::vector<std::string> filenames, vvImageReader::LoadedImageType type, int n)
+{ 
+  mType = type;
+  std::string fileWithoutExtension = vtksys::SystemTools::GetFilenameWithoutExtension(filenames[0]);
+  if (type == vvImageReader::DICOM)
+    fileWithoutExtension += "_dicom";
+  else if (type == vvImageReader::MERGED)
+    fileWithoutExtension += "_merged";
+  else if (type == vvImageReader::MERGEDWITHTIME)
+    fileWithoutExtension += "_merged_wt";
+
+  mFileName = vtksys::SystemTools::GetFilenameName(mFileName);
+  mFileName = fileWithoutExtension + vtksys::SystemTools::GetFilenameExtension(filenames[0]);
+  if (mReader.IsNull())
+    mReader = vvImageReader::New();
+  mReader->SetInputFilenames(filenames);
+  mReader->Update(type);
+
+  mBaseFileName = vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(mFileName));
+  mBaseFileNameNumber = n;
+
+  if (mReader->GetLastError().size() == 0) {
+    mImage=mReader->GetOutput();
+    for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+      mSlicers[i]->SetFileName(fileWithoutExtension);
+      mSlicers[i]->SetImage(mReader->GetOutput());
+    }
+  } else {
+    mLastError = mReader->GetLastError();
+    return false;
+  }
+  if (n!=0) {
+    mFileName.append("_"+clitk::toString(n));
+  }
+  return true;
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+bool vvSlicerManager::SetOverlay(std::vector<std::string> filenames,int dim, std::string component, vvImageReader::LoadedImageType type)
+{ 
+  mOverlayName = filenames[0];
+  mOverlayComponent = component;
+  if (dim > mImage->GetNumberOfDimensions()) {
+    mLastError = " Overlay dimension cannot be greater than reference image!";
+    return false;
+  }
+  if (mOverlayReader.IsNull())
+    mOverlayReader = vvImageReader::New();
+  mOverlayReader->SetInputFilenames(filenames);
+  mOverlayReader->Update(type);
+  if (mOverlayReader->GetLastError().size() == 0) {
+    for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+      mSlicers[i]->SetOverlay(mOverlayReader->GetOutput());
+    }
+  } else {
+    mLastError = mOverlayReader->GetLastError();
+    return false;
+  }
+  return true;
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+bool vvSlicerManager::SetFusion(std::vector<std::string> filenames,int dim, std::string component, vvImageReader::LoadedImageType type)
+{ 
+  mFusionName = filenames[0];
+  mFusionComponent = component;
+  if (dim > mImage->GetNumberOfDimensions()) {
+    mLastError = " Fusion dimension cannot be greater than reference image!";
+    return false;
+  }
+  if (mFusionReader.IsNull())
+    mFusionReader = vvImageReader::New();
+  mFusionReader->SetInputFilenames(filenames);
+  mFusionReader->Update(type);
+  if (mFusionReader->GetLastError().size() == 0) {
+    for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+      mSlicers[i]->SetFusion(mFusionReader->GetOutput());
+    }
+  } else {
+    mLastError = mFusionReader->GetLastError();
+    return false;
+  }
+  double *fusRange = mFusionReader->GetOutput()->GetVTKImages()[0]->GetScalarRange();
+  mFusionLevel = (fusRange[0]+fusRange[1])/2;
+  mFusionWindow = fusRange[1]-fusRange[0];
+
+  return true;
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+//this function is called by vvMainWindow::AddFusionSequence for the primary sequence (CT), while the given files constitute the secondary sequence.
+bool vvSlicerManager::SetFusionSequence(std::vector<std::string> filenames, int dim, std::string component, vvImageReader::LoadedImageType type)
+{ 
+       mFusionSequenceInvolvementCode = 0;
+
+       mFusionName = filenames[0];
+       mFusionComponent = component;
+
+       if (dim > mImage->GetNumberOfDimensions()) {
+               mLastError = " Fusion Sequence dimension cannot be greater than reference image!";
+               return false;
+       }
+
+       if (mFusionSequenceReader.IsNull())
+               mFusionSequenceReader = vvImageReader::New();
+
+       mFusionSequenceReader->SetInputFilenames(filenames);
+       mFusionSequenceReader->Update(type);
+
+
+       if (mFusionSequenceReader->GetLastError().size() == 0) {
+               for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+                       mSlicers[i]->SetFusion(mFusionSequenceReader->GetOutput(), mFusionSequenceInvolvementCode);
+               }
+       } else {
+               mLastError = mFusionSequenceReader->GetLastError();
+               return false;
+       }
+       double *fusRange = mFusionSequenceReader->GetOutput()->GetVTKImages()[0]->GetScalarRange();
+       mFusionLevel = (fusRange[0]+fusRange[1])/2;
+       mFusionWindow = fusRange[1]-fusRange[0];
+
+       //store the initial transform matrices of each frame, and reset them to identity
+       mFusionSequenceListInitialTransformMatrices.clear();
+       for (unsigned i=0 ; i<mFusionSequenceReader->GetOutput()->GetTransform().size() ; i++) {
+               AddFusionSequenceInitialTransformMatrices( mFusionSequenceReader->GetOutput()->GetTransform()[i]->GetMatrix() );
+               mFusionSequenceReader->GetOutput()->GetTransform()[i]->Identity();
+               mFusionSequenceReader->GetOutput()->GetTransform()[i]->Update();
+       }
+
+       //adjust the time slider in the overlay panel
+       mFusionSequenceNbFrames = mFusionSequenceReader->GetOutput()->GetTransform().size(); 
+       mFusionSequenceFrameIndex = std::max<int>( 0, std::min<int>(mFusionSequenceFrameIndex, mFusionSequenceNbFrames));
+
+       return true;
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+bool vvSlicerManager::SetVF(std::string filename)
+{ 
+  if (mVectorReader.IsNull())
+    mVectorReader = vvImageReader::New();
+  mVectorReader->SetInputFilename(filename);
+  
+  if (mType == vvImageReader::IMAGEWITHTIME)
+    mVectorReader->Update(vvImageReader::VECTORFIELDWITHTIME);
+  else
+    mVectorReader->Update(vvImageReader::VECTORFIELD);
+  if (mVectorReader->GetLastError().size() != 0) {
+    mLastError = mVectorReader->GetLastError();
+    return false;
+  } else
+    return SetVF(mVectorReader->GetOutput(),filename);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+bool vvSlicerManager::SetVF(vvImage::Pointer vf,std::string filename)
+{ 
+  if (vf->GetNumberOfDimensions() > mImage->GetNumberOfDimensions()) {
+    mLastError = "Sorry, vector field dimension cannot be greater then reference image.";
+    return false;
+  }
+  if (vf->GetNumberOfDimensions() == 4) {
+    if (vf->GetSpacing()[3] != mImage->GetSpacing()[3]) {
+      mLastError = "Sorry, vector field time spacing cannot be different from time spacing of the reference image.";
+      return false;
+    }
+    if (vf->GetOrigin()[3] != mImage->GetOrigin()[3]) {
+      mLastError = "Sorry, vector field time origin cannot be different from time origin of the reference image.";
+      return false;
+    }
+  }
+  mVF=vf;
+  mVFName = filename;
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetVF(vf);
+  }
+  return true;
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+vvSlicer* vvSlicerManager::GetSlicer(int i)
+{ 
+  return mSlicers[i];
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::UpdateSlicer(int num, bool state)
+{ 
+  if (mSlicers[num]->GetImage()) {
+    mSlicers[num]->SetDisplayMode(state);
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetSlicerWindow(int i, vtkRenderWindow* RW)
+{ 
+  mSlicers[i]->SetRenderWindow(i,RW);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetInteractorStyleNavigator(int i, vtkInteractorStyle* style)
+{ 
+  vvSlicerManagerCommand *smc = vvSlicerManagerCommand::New();
+  smc->SM = this;
+  smc->SetSlicerNumber(i);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->SetInteractorStyle(style);
+
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::KeyPressEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::WindowLevelEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::EndWindowLevelEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::StartWindowLevelEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::PickEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::StartPickEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::LeaveEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::UserEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::MouseWheelForwardEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::MouseWheelBackwardEvent, smc);
+  // mSlicers[i]->GetRenderWindow()->GetInteractor()->
+  //   GetInteractorStyle()->AddObserver(vtkCommand::LeftButtonReleaseEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::EndPickEvent, smc);
+  mSlicers[i]->GetRenderWindow()->GetInteractor()->
+    GetInteractorStyle()->AddObserver(vtkCommand::EndInteractionEvent, smc);
+  smc->Delete();
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::LeftButtonReleaseEvent(int slicer)
+{ 
+  emit LeftButtonReleaseSignal(slicer);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::EmitMousePositionUpdated(int slicer)
+{ 
+  emit MousePositionUpdatedSignal(slicer);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::EmitKeyPressed(std::string KeyPress)
+{ 
+  emit KeyPressedSignal(KeyPress);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetSliceOrientation(int slicer, int orientation)
+{ 
+  mSlicers[slicer]->SetSliceOrientation(orientation);
+  emit UpdateOrientation(slicer, orientation);
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+int vvSlicerManager::GetTSlice()
+{ 
+  return mSlicers[0]->GetTSlice();
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetTSlice(int slice, bool updateLinkedImages)
+{ 
+       if (!updateLinkedImages) { //for fusionSequence, TMax / MaxCurrentTSlice are irrelevant.
+               for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+                       mSlicers[i]->SetTSlice(slice, updateLinkedImages);
+                       UpdateTSlice(i);
+               }
+               return;
+       }
+
+  if (slice < 0)
+    slice = 0;
+  else if (slice > mSlicers[0]->GetTMax())
+    slice = mSlicers[0]->GetTMax();
+  if (mLandmarks)
+    mLandmarks->SetTime(slice);
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    if (slice != mSlicers[i]->GetMaxCurrentTSlice()) {
+      mSlicers[i]->SetTSlice(slice, updateLinkedImages);
+      UpdateTSlice(i);
+    }
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetFusionSequenceTSlice(int slice)
+{ 
+       for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+               mSlicers[i]->SetFusionSequenceTSlice(slice);
+               UpdateTSlice(i);
+       }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetNextTSlice(int originating_slicer)
+{ 
+  int t = mSlicers[0]->GetMaxCurrentTSlice();
+  t++;
+  if (t > mSlicers[0]->GetTMax())
+    t = 0;
+  emit UpdateTSlice(originating_slicer,t, mFusionSequenceInvolvementCode);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetPreviousTSlice(int originating_slicer)
+{ 
+  int t = mSlicers[0]->GetMaxCurrentTSlice();
+  t--;
+  if (t < 0)
+    t = mSlicers[0]->GetTMax();
+  emit UpdateTSlice(originating_slicer,t, mFusionSequenceInvolvementCode);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::ToggleInterpolation()
+{ 
+  bool interpolate=!(mSlicers[0]->GetImageActor()->GetInterpolate());
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->GetImageActor()->SetInterpolate(interpolate);
+    if (mSlicers[i]->GetOverlayActor())
+      mSlicers[i]->GetOverlayActor()->SetInterpolate(interpolate);
+    if (mSlicers[i]->GetFusionActor())
+      mSlicers[i]->GetFusionActor()->SetInterpolate(interpolate);
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetTSliceInSlicer(int tslice, int slicer)
+{ 
+  if (tslice < 0)
+    tslice = 0;
+  else if (tslice > mSlicers[slicer]->GetTMax())
+    tslice = mSlicers[slicer]->GetTMax();
+  if (mLandmarks)
+    mLandmarks->SetTime(tslice);
+
+  if (mSlicers[slicer]->GetMaxCurrentTSlice() == tslice) return;
+
+  mSlicers[slicer]->SetTSlice(tslice);
+
+  if(mSlicingPreset==VOXELS_SLICING) {
+    vtkMatrix4x4 *imageTransformInverse = vtkMatrix4x4::New();
+    mImage->GetTransform()[mSlicers[slicer]->GetTSlice()]->GetInverse(imageTransformInverse);
+    this->GetSlicer(slicer)->GetSlicingTransform()->SetMatrix(imageTransformInverse);
+    imageTransformInverse->Delete();
+  }
+
+  UpdateTSlice(slicer);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetColorWindow(double s)
+{ 
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetColorWindow(s);
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetColorLevel(double s)
+{ 
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetColorLevel(s);
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetOverlayColorWindow(double s)
+{ 
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetOverlayColorWindow(s);
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetOverlayColorLevel(double s)
+{ 
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetOverlayColorLevel(s);
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetLinkOverlayWindowLevel(bool b)
+{ 
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetLinkOverlayWindowLevel(b);
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetCursorAndCornerAnnotationVisibility(int s)
+{ 
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetCursorVisibility(s);
+    mSlicers[i]->SetCornerAnnotationVisibility(s);
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetOpacity(int i, double factor)
+{ 
+  mSlicers[i]->SetOpacity(1/factor);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::UpdateViews(int current,int slicer)
+{ 
+  double p[3], pt[3];
+  p[0] = mSlicers[slicer]->GetCurrentPosition()[0];
+  p[1] = mSlicers[slicer]->GetCurrentPosition()[1];
+  p[2] = mSlicers[slicer]->GetCurrentPosition()[2];
+  mSlicers[slicer]->GetSlicingTransform()->GetInverse()->TransformPoint(p, pt);
+
+  double x = (pt[0] - mSlicers[slicer]->GetInput()->GetOrigin()[0])
+    /mSlicers[slicer]->GetInput()->GetSpacing()[0];
+  double y = (pt[1] - mSlicers[slicer]->GetInput()->GetOrigin()[1])
+    /mSlicers[slicer]->GetInput()->GetSpacing()[1];
+  double z = (pt[2] - mSlicers[slicer]->GetInput()->GetOrigin()[2])
+    /mSlicers[slicer]->GetInput()->GetSpacing()[2];
+#if VTK_MAJOR_VERSION <= 5
+  if (x >= mSlicers[slicer]->GetInput()->GetWholeExtent()[0]-0.5 &&
+      x <= mSlicers[slicer]->GetInput()->GetWholeExtent()[1]+0.5 &&
+      y >= mSlicers[slicer]->GetInput()->GetWholeExtent()[2]-0.5 &&
+      y <= mSlicers[slicer]->GetInput()->GetWholeExtent()[3]+0.5 &&
+      z >= mSlicers[slicer]->GetInput()->GetWholeExtent()[4]-0.5 &&
+      z <= mSlicers[slicer]->GetInput()->GetWholeExtent()[5]+0.5)
+#else
+int extentImageReslice[6];
+mSlicers[slicer]->GetRegisterExtent(extentImageReslice);
+  if (x >= extentImageReslice[0]-0.5 &&
+      x <= extentImageReslice[1]+0.5 &&
+      y >= extentImageReslice[2]-0.5 &&
+      y <= extentImageReslice[3]+0.5 &&
+      z >= extentImageReslice[4]-0.5 &&
+      z <= extentImageReslice[5]+0.5)
+#endif
+  {
+    mSlicers[slicer]->UpdateCursorPosition();
+    mSlicers[slicer]->SetCursorColor(10,212,255);
+    mSelectedSlicer = slicer;
+
+    switch (mSlicers[slicer]->GetSliceOrientation()) {
+    case vtkImageViewer2::SLICE_ORIENTATION_XY:
+      if (mSlicers[slicer]->GetSlice() != (int)lrint(z))
+        mSlicers[slicer]->SetSlice((int)lrint(z));
+      break;
+
+    case vtkImageViewer2::SLICE_ORIENTATION_XZ:
+      if (mSlicers[slicer]->GetSlice() != (int)lrint(y))
+        mSlicers[slicer]->SetSlice((int)lrint(y));
+      break;
+
+    case vtkImageViewer2::SLICE_ORIENTATION_YZ:
+      if (mSlicers[slicer]->GetSlice() != (int)lrint(x))
+        mSlicers[slicer]->SetSlice((int)lrint(x));
+      break;
+    }
+    mSlicers[slicer]->Render();
+
+    for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+      if (i != (unsigned int)slicer
+          && mSlicers[i]->GetRenderer()->GetDraw()
+          && mSlicers[i]->GetRenderWindow()->GetSize()[0] > 2
+          && mSlicers[i]->GetRenderWindow()->GetSize()[1] > 2) {
+        mSlicers[i]->SetCurrentPosition(p[0], p[1], p[2], mSlicers[slicer]->GetMaxCurrentTSlice());
+        mSlicers[i]->UpdateCursorPosition();
+        if (current) { //do not display corner annotation if image is the one picked
+          mSlicers[i]->SetCurrentPosition(-VTK_DOUBLE_MAX,-VTK_DOUBLE_MAX,
+                                          -VTK_DOUBLE_MAX, mSlicers[slicer]->GetMaxCurrentTSlice());
+          mSlicers[i]->SetCursorColor(255,10,212);
+        } else {
+          mSlicers[i]->SetCursorColor(150,10,282);
+        }
+        switch (mSlicers[i]->GetSliceOrientation()) {
+        case vtkImageViewer2::SLICE_ORIENTATION_XY:
+          if (mSlicers[i]->GetSlice() != (int)lrint(z))
+            mSlicers[i]->SetSlice((int)lrint(z));
+          break;
+
+        case vtkImageViewer2::SLICE_ORIENTATION_XZ:
+          if (mSlicers[i]->GetSlice() != (int)lrint(y))
+            mSlicers[i]->SetSlice((int)lrint(y));
+          break;
+
+        case vtkImageViewer2::SLICE_ORIENTATION_YZ:
+          if (mSlicers[i]->GetSlice() != (int)lrint(x))
+            mSlicers[i]->SetSlice((int)lrint(x));
+          break;
+        }
+        
+        mSlicers[i]->Render();
+        
+        UpdateSlice(i);
+        UpdateTSlice(i);
+      }
+    }
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::UpdateLinked(int slicer)
+{ 
+  double p[3], pt[3];
+  p[0] = mSlicers[slicer]->GetCurrentPosition()[0];
+  p[1] = mSlicers[slicer]->GetCurrentPosition()[1];
+  p[2] = mSlicers[slicer]->GetCurrentPosition()[2];
+  mSlicers[slicer]->GetSlicingTransform()->GetInverse()->TransformPoint(p, pt);
+  double x = (pt[0] - mSlicers[slicer]->GetInput()->GetOrigin()[0]) / mSlicers[slicer]->GetInput()->GetSpacing()[0];
+  double y = (pt[1] - mSlicers[slicer]->GetInput()->GetOrigin()[1]) / mSlicers[slicer]->GetInput()->GetSpacing()[1];
+  double z = (pt[2] - mSlicers[slicer]->GetInput()->GetOrigin()[2]) / mSlicers[slicer]->GetInput()->GetSpacing()[2];
+#if VTK_MAJOR_VERSION <= 5
+  if (x >= mSlicers[slicer]->GetInput()->GetWholeExtent()[0]-0.5 &&
+      x <= mSlicers[slicer]->GetInput()->GetWholeExtent()[1]+0.5 &&
+      y >= mSlicers[slicer]->GetInput()->GetWholeExtent()[2]-0.5 &&
+      y <= mSlicers[slicer]->GetInput()->GetWholeExtent()[3]+0.5 &&
+      z >= mSlicers[slicer]->GetInput()->GetWholeExtent()[4]-0.5 &&
+      z <= mSlicers[slicer]->GetInput()->GetWholeExtent()[5]+0.5)
+#else
+int extentImageReslice[6];
+mSlicers[slicer]->GetRegisterExtent(extentImageReslice);
+  if (x >= extentImageReslice[0]-0.5 &&
+      x <= extentImageReslice[1]+0.5 &&
+      y >= extentImageReslice[2]-0.5 &&
+      y <= extentImageReslice[3]+0.5 &&
+      z >= extentImageReslice[4]-0.5 &&
+      z <= extentImageReslice[5]+0.5)
+#endif
+  {
+    for (std::list<std::string>::const_iterator i = mLinkedId.begin(); i != mLinkedId.end(); i++) {
+               if (this->IsInvolvedInFusionSequence()) {
+                       //this SlicerManager is involved in fusionSequence => do not synchronize the times
+                       emit UpdateLinkManager(*i, slicer, p[0], p[1], p[2], -1);
+               }
+               else {
+                       emit UpdateLinkManager(*i, slicer, p[0], p[1], p[2], mSlicers[slicer]->GetMaxCurrentTSlice());
+               }
+    }
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::UpdateLinkedNavigation(vvSlicer *refSlicer, bool bPropagate)
+{ 
+  vtkCamera *refCam = refSlicer->GetRenderer()->GetActiveCamera();
+
+  double refPosition[3];
+  refCam->GetPosition(refPosition);
+  refPosition[refSlicer->GetSliceOrientation()] = refSlicer->GetSlice() *
+      refSlicer->GetInput()->GetSpacing()[refSlicer->GetSliceOrientation()] +
+      refSlicer->GetInput()->GetOrigin()[refSlicer->GetSliceOrientation()];
+
+  refSlicer->GetSlicingTransform()->TransformPoint(refPosition, refPosition);
+  mSlicers[0]->GetSlicingTransform()->GetInverse()->TransformPoint(refPosition, refPosition);
+
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    vtkCamera *camera = mSlicers[i]->GetRenderer()->GetActiveCamera();
+    camera->SetParallelScale(refCam->GetParallelScale());
+
+    double position[3], focal[3];
+    camera->GetPosition(position);
+    camera->GetFocalPoint(focal);
+
+    for(int j=0; j<3; j++) {
+      if(j!=mSlicers[i]->GetSliceOrientation()) {
+        position[j] = refPosition[j];
+        focal[j]    = refPosition[j];
+      }
+    }
+
+    camera->SetFocalPoint(focal);
+    camera->SetPosition(position);
+
+    //Fix for bug #243
+    mSlicers[i]->ForceUpdateDisplayExtent();
+  }
+  
+  Render();
+  if(bPropagate)
+    for (std::list<std::string>::const_iterator i = mLinkedId.begin(); i != mLinkedId.end(); i++)
+      emit UpdateLinkedNavigation(*i, this, refSlicer);
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+double vvSlicerManager::GetColorWindow() const
+{ 
+  if (mSlicers.size())
+    return mSlicers[0]->GetColorWindow();
+  return -1;
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+double vvSlicerManager::GetColorLevel() const
+{ 
+  if (mSlicers.size())
+    return mSlicers[0]->GetColorLevel();
+  return -1;
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+double vvSlicerManager::GetOverlayColorWindow() const
+{ 
+  if (mSlicers.size())
+    return mSlicers[0]->GetOverlayColorWindow();
+  return -1;
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+double vvSlicerManager::GetOverlayColorLevel() const
+{ 
+  if (mSlicers.size())
+    return mSlicers[0]->GetOverlayColorLevel();
+  return -1;
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+bool vvSlicerManager::GetLinkOverlayWindowLevel() const
+{ 
+  if (mSlicers.size())
+    return mSlicers[0]->GetLinkOverlayWindowLevel();
+  return -1;
+}
+//----------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+void vvSlicerManager::ResetTransformationToIdentity(const std::string actorType)
+{ 
+  if(actorType == "image")
+    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)
+      this->GetImage()->GetTransform()[i]->Identity();
+  else if(actorType == "overlay")
+    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)
+      this->GetSlicer(0)->GetOverlay()->GetTransform()[i]->Identity();
+  else if(actorType == "fusion")
+    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)
+      this->GetSlicer(0)->GetFusion()->GetTransform()[i]->Identity();
+  else if(actorType == "fusionSequence") //TODO: Check what should really be done here
+    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)
+      this->GetSlicer(0)->GetFusion()->GetTransform()[i]->Identity();
+  else if(actorType == "vf")
+    for(unsigned int i=0; i<this->GetImage()->GetTransform().size(); i++)
+      this->GetVF()->GetTransform()[i]->Identity();
+  else
+    return;
+
+  for(int i=0; i< this->GetNumberOfSlicers(); i++){
+    this->GetSlicer(i)->ForceUpdateDisplayExtent();
+    this->GetSlicer(i)->ResetCamera();
+    this->GetSlicer(i)->Render();
+  }
+}
+//------------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::Render()
+{ 
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->Render();
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::GenerateDefaultLookupTable()
+{ 
+  SetPreset(mPreset);
+  SetColorMap(mColorMap);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::Reload()
+{ 
+  mReader->Update(mType);
+  mImage=mReader->GetOutput();
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetImage(mImage);
+  }
+  
+  //if this image is the primary sequence of a fusion sequence, then the main transform matrix should be updated.
+  if (this->IsMainSequenceOfFusionSequence()) {
+         SetFusionSequenceMainTransformMatrix( mImage->GetTransform()[0]->GetMatrix() );
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::ReloadFusion()
+{ 
+  mFusionReader->Update(mImage->GetNumberOfDimensions(),mFusionComponent.c_str(),mType);
+
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetFusion(mFusionReader->GetOutput());
+    mSlicers[i]->Render();
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+//the secondary sequence is being reloaded.
+void vvSlicerManager::ReloadFusionSequence()
+{ 
+  //  this is to keep the slice thickness, which needs to be artificially increased for visualization
+  double sp_x, sp_y, sp_z;
+  this->GetImage()->GetVTKImages()[0]->GetSpacing(sp_x, sp_y, sp_z);
+
+  mFusionSequenceReader->Update(mImage->GetNumberOfDimensions(),mFusionComponent.c_str(),vvImageReader::MERGEDWITHTIME);
+
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetFusion(mFusionSequenceReader->GetOutput(), 1);
+    mSlicers[i]->Render();
+  }
+
+  //Update the slider
+  mFusionSequenceNbFrames = mFusionSequenceReader->GetOutput()->GetTransform().size();
+  if (mFusionSequenceFrameIndex>=mFusionSequenceNbFrames) {
+         mFusionSequenceFrameIndex=0;
+  }
+
+  //Update the list of initial transforms
+  mFusionSequenceListInitialTransformMatrices.clear();
+  for (unsigned i=0 ; i<mFusionSequenceNbFrames ; i++) {
+         this->AddFusionSequenceInitialTransformMatrices( mFusionSequenceReader->GetOutput()->GetTransform()[i]->GetMatrix() );
+  }
+
+  //  also update the slice thickness
+  for (unsigned i=0 ; i<this->GetImage()->GetTransform().size() ; i++) {
+    sp_x = this->GetImage()->GetVTKImages()[i]->GetSpacing()[0];
+    sp_y = this->GetImage()->GetVTKImages()[i]->GetSpacing()[1];
+    this->GetImage()->GetVTKImages()[i]->SetSpacing( sp_x, sp_y, sp_z);
+  }
+
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::ReloadOverlay()
+{ 
+  mOverlayReader->Update(mImage->GetNumberOfDimensions(),mOverlayComponent.c_str(),mType);
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetOverlay(mOverlayReader->GetOutput());
+    mSlicers[i]->Render();
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::ReloadVF()
+{ 
+  mVectorReader->Update(vvImageReader::VECTORFIELD); //deletes the old images through the VF::Init() function
+  mVF=mVectorReader->GetOutput();
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetVF(mVF);
+    mSlicers[i]->Render();
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::RemoveActor(const std::string& actor_type, int overlay_index)
+{ 
+  if (actor_type =="overlay")
+    mOverlayReader = NULL;
+
+  if (actor_type =="fusion")
+    mFusionReader = NULL;
+
+  if (actor_type =="fusionSequence") {
+    mFusionSequenceReader = NULL;
+  }
+
+  for (unsigned int i = 0; i < mSlicers.size(); i++)
+    mSlicers[i]->RemoveActor(actor_type,overlay_index);
+
+  if (actor_type=="vector") {
+    mVF=NULL;
+    mVectorReader=NULL;
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::RemoveActors()
+{ 
+  ///This method leaks a few objects. See RemoveActor for what a
+  ///correct implementation would look like
+  //DS -> probably due to the reader (now released in the
+  //RemoveActor() function. (I hope)
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+    mSlicers[i]->SetDisplayMode(0);
+    mSlicers[i]->GetRenderer()->RemoveActor(mSlicers[i]->GetImageActor());
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::UpdateInfoOnCursorPosition(int slicer)
+{ 
+  //  int view = mSlicers[slicer]->GetSliceOrientation();
+  //  int slice = mSlicers[slicer]->GetSlice();
+  double x = mSlicers[slicer]->GetCurrentPosition()[0];
+  double y = mSlicers[slicer]->GetCurrentPosition()[1];
+  double z = mSlicers[slicer]->GetCurrentPosition()[2];
+  double xyz[3], xyzTransform[3];
+  xyz[0] = x;
+  xyz[1] = y;
+  xyz[2] = z;
+  mSlicers[slicer]->GetSlicingTransform()->GetInverse()->TransformPoint(xyz, xyzTransform);
+  double X = (xyzTransform[0] - mSlicers[slicer]->GetInput()->GetOrigin()[0])/mSlicers[slicer]->GetInput()->GetSpacing()[0];
+  double Y = (xyzTransform[1] - mSlicers[slicer]->GetInput()->GetOrigin()[1])/mSlicers[slicer]->GetInput()->GetSpacing()[1];
+  double Z = (xyzTransform[2] - mSlicers[slicer]->GetInput()->GetOrigin()[2])/mSlicers[slicer]->GetInput()->GetSpacing()[2];
+  double value = -VTK_DOUBLE_MAX;
+  int displayVec = 0;
+  double xVec=0, yVec=0, zVec=0, valueVec=0;
+  int displayOver = 0;
+  int displayFus = 0;
+  double valueOver=0, valueFus=0;
+#if VTK_MAJOR_VERSION <= 5
+    if (X >= mSlicers[slicer]->GetInput()->GetWholeExtent()[0] -0.5 &&
+      X <= mSlicers[slicer]->GetInput()->GetWholeExtent()[1] +0.5 &&
+      Y >= mSlicers[slicer]->GetInput()->GetWholeExtent()[2] -0.5 &&
+      Y <= mSlicers[slicer]->GetInput()->GetWholeExtent()[3] +0.5 &&
+      Z >= mSlicers[slicer]->GetInput()->GetWholeExtent()[4] -0.5 &&
+      Z <= mSlicers[slicer]->GetInput()->GetWholeExtent()[5] +0.5)
+#else
+int extentImageReslice[6];
+mSlicers[slicer]->GetRegisterExtent(extentImageReslice);
+    if (X >= extentImageReslice[0] -0.5 &&
+      X <= extentImageReslice[1] +0.5 &&
+      Y >= extentImageReslice[2] -0.5 &&
+      Y <= extentImageReslice[3] +0.5 &&
+      Z >= extentImageReslice[4] -0.5 &&
+      Z <= extentImageReslice[5] +0.5)
+#endif
+    {
+    value = this->GetScalarComponentAsDouble(mSlicers[slicer]->GetInput(), X, Y, Z);
+
+    if (mSlicers[slicer]->GetVFActor() ) {
+      displayVec = 1;
+      unsigned int currentTime = mSlicers[slicer]->GetMaxCurrentTSlice();
+      vtkImageData *vf = NULL;
+
+      if (mSlicers[slicer]->GetVF()->GetVTKImages().size() > currentTime)
+        vf = mSlicers[slicer]->GetVF()->GetVTKImages()[currentTime];
+      else
+        vf = mSlicers[slicer]->GetVF()->GetVTKImages()[0];
+
+      if (vf) {
+        double Xvf = (x - vf->GetOrigin()[0])/ vf->GetSpacing()[0];
+        double Yvf = (y - vf->GetOrigin()[1])/ vf->GetSpacing()[1];
+        double Zvf = (z - vf->GetOrigin()[2])/ vf->GetSpacing()[2];
+        xVec = this->GetScalarComponentAsDouble( vf, Xvf, Yvf, Zvf, 0);
+        yVec = this->GetScalarComponentAsDouble( vf, Xvf, Yvf, Zvf, 1);
+        zVec = this->GetScalarComponentAsDouble( vf, Xvf, Yvf, Zvf, 2);
+        valueVec = sqrt(xVec*xVec + yVec*yVec + zVec*zVec);
+      }
+    }
+    if (mSlicers[slicer]->GetOverlayActor() ) {
+      displayOver = 1;
+      vtkImageData *overlay = dynamic_cast<vtkImageData*>(mSlicers[slicer]->GetOverlayMapper()->GetInput());
+      double Xover = (x - overlay->GetOrigin()[0]) / overlay->GetSpacing()[0];
+      double Yover = (y - overlay->GetOrigin()[1]) / overlay->GetSpacing()[1];
+      double Zover = (z - overlay->GetOrigin()[2]) / overlay->GetSpacing()[2];
+      valueOver = this->GetScalarComponentAsDouble(overlay, Xover, Yover, Zover);
+    }
+
+       if ( mSlicers[slicer]->GetFusionActor() ) {
+               displayFus = 1;
+               vtkImageData *fusion = dynamic_cast<vtkImageData*>(mSlicers[slicer]->GetFusionMapper()->GetInput());
+               double Xover = (x - fusion->GetOrigin()[0]) / fusion->GetSpacing()[0];
+               double Yover = (y - fusion->GetOrigin()[1]) / fusion->GetSpacing()[1];
+               double Zover = (z - fusion->GetOrigin()[2]) / fusion->GetSpacing()[2];
+               valueFus = this->GetScalarComponentAsDouble(fusion, Xover, Yover, Zover);
+       }
+       else if (this->IsInvolvedInFusionSequence()) { 
+    //if the cursor moves over the 'independent' version of the secondary sequence
+    //do not update the panel, just keep it as it is.
+               displayFus = 1;
+               valueFus = std::numeric_limits<double>::quiet_NaN();
+       }
+
+    emit UpdatePosition(mSlicers[slicer]->GetCursorVisibility(),
+                        x,y,z,X,Y,Z,value);
+    emit UpdateVector(displayVec,xVec, yVec, zVec, valueVec);
+    emit UpdateOverlay(displayOver,valueOver,value);
+    emit UpdateFusion(displayFus,valueFus);
+  }
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::Activated()
+{ 
+  emit currentImageChanged(mId);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::Picked()
+{ 
+  emit currentPickedImageChanged(mId);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::UpdateWindowLevel()
+{ 
+  emit WindowLevelChanged();
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::UpdateSlice(int slicer)
+{ 
+  if (mPreviousSlice[slicer] == mSlicers[slicer]->GetSlice()) {
+    //DD("============= NOTHING");
+    return;
+  }
+  emit UpdateSlice(slicer, mSlicers[slicer]->GetSlice());
+  mSlicers[slicer]->Render(); // DS <-- I add this, this could/must be the only Render ...
+  mPreviousSlice[slicer] = mSlicers[slicer]->GetSlice();
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::UpdateTSlice(int slicer)
+{ 
+  int slice = mSlicers[slicer]->GetSlice();
+
+  int tslice = mSlicers[slicer]->GetMaxCurrentTSlice();
+  //if (this->IsInvolvedInFusionSequence()) tslice = mSlicers[slicer]->GetTSlice(); //actually, this is handled by the Slicer
+
+  if (mPreviousSlice[slicer] == slice) {
+    if (mPreviousTSlice[slicer] == tslice) {
+      //      DD("************** NOTHING ***********");
+      return;
+    }
+  }
+  mPreviousSlice[slicer] = slice;
+  mPreviousTSlice[slicer] = tslice;
+
+  emit UpdateTSlice(slicer, tslice, mFusionSequenceInvolvementCode);
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::UpdateSliceRange(int slicer)
+{ 
+  emit UpdateSliceRange(slicer,
+                        mSlicers[slicer]->GetSliceRange()[0], mSlicers[slicer]->GetSliceRange()[1],
+                        0,mSlicers[slicer]->GetTMax());
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetSlicingPreset(SlicingPresetType preset)
+{ 
+  if(mSlicingPreset==preset)
+    return;
+
+  vtkMatrix4x4 *imageTransformInverse = vtkMatrix4x4::New();
+  mImage->GetTransform()[this->GetTSlice()]->GetInverse(imageTransformInverse);
+
+  for(int i=0; i< this->GetNumberOfSlicers(); i++){
+    vvSlicer *s = this->GetSlicer(i);
+    switch(preset)
+    {
+    case WORLD_SLICING:
+      s->GetSlicingTransform()->Identity();
+      break;
+    case VOXELS_SLICING:
+      s->GetSlicingTransform()->SetMatrix(imageTransformInverse);
+      break;
+    default:
+      imageTransformInverse->Delete();
+      return;
+    }
+    s->ForceUpdateDisplayExtent();
+#if VTK_MAJOR_VERSION <= 5
+    s->SetSlice((s->GetInput()->GetWholeExtent()[s->GetSliceOrientation()*2+1]
+                +s->GetInput()->GetWholeExtent()[s->GetSliceOrientation()*2])/2.0);
+#else
+    int extentImageReslice[6];
+    s->GetRegisterExtent(extentImageReslice);
+    s->SetSlice((extentImageReslice[s->GetSliceOrientation()*2+1]
+                +extentImageReslice[s->GetSliceOrientation()*2])/2.0);
+#endif
+    s->ResetCamera();
+    s->Render();
+  }
+
+  imageTransformInverse->Delete();
+  mSlicingPreset = preset;
+}
+
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetPreset(int preset)
+{ 
+
+  //vtkLookupTable* LUT = static_cast<vtkLookupTable*>(mSlicers[0]->GetWindowLevel()->GetLookupTable());
+  double window = mSlicers[0]->GetColorWindow();
+  double level = mSlicers[0]->GetColorLevel();
+
+  std::string component_type=mImage->GetScalarTypeAsITKString();
+  switch (preset) {
+  case WL_AUTO:
+    double range[2];
+    mImage->GetScalarRange(range);
+    window = range[1] - range[0];
+    level = (range[1] + range[0])* 0.5;
+    break;
+  case WL_HOUNSFIELD:
+    window = 2000;
+    level = 0;
+    break;
+  case WL_SOFTTISSUE:
+    window = 400;
+    level = 20;
+    break;
+  case WL_LUNGS: // lungs (same as FOCAL)
+    window = 1700;
+    level = -300;
+    break;
+  case WL_BONES:
+    window = 1000;
+    level = 500;
+    break;
+  case WL_HEAD:
+    window = 200;
+    level = 70;
+    break;
+  case WL_BINARY:
+    window = 1;
+    level = 0.5;
+    break;
+  case WL_USER:
+    break;
+  case WL_VENTILATION:
+    window=1.;
+    level=0.;
+    break;
+  }
+  mPreset = preset;
+  this->SetColorWindow(window);
+  this->SetColorLevel(level);
+
+  //if (LUT)
+  //{
+  //    SetColorMap(-1);
+  //}
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetLocalColorWindowing(const int slicer, const bool bCtrlKey)
+{ 
+  double min, max;
+  if(bCtrlKey && this->mSlicers[slicer]->GetFusion()) {
+    int t = mSlicers[slicer]->GetFusionTSlice();
+    this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max,
+                                                          this->mSlicers[slicer]->GetFusion()->GetVTKImages()[t],
+                                                          this->mSlicers[slicer]->GetConcatenatedFusionTransform());
+    this->SetFusionWindow(max-min);
+    this->SetFusionLevel(0.5*(min+max));
+    this->SetColorMap(mColorMap);
+  }
+  else if(bCtrlKey && this->mSlicers[slicer]->GetOverlay()) {
+    int t = mSlicers[slicer]->GetOverlayTSlice();
+    this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max,
+                                                          this->mSlicers[slicer]->GetOverlay()->GetVTKImages()[t],
+                                                          this->mSlicers[slicer]->GetConcatenatedOverlayTransform());
+    if(this->mSlicers[slicer]->GetLinkOverlayWindowLevel()){
+      this->SetColorWindow(max-min);
+      this->SetColorLevel(0.5*(min+max));
+    } else {
+      this->SetOverlayColorWindow(max-min);
+      this->SetOverlayColorLevel(0.5*(min+max));
+    }
+  }
+  else {
+    int t = this->GetTSlice();
+    this->mSlicers[slicer]->GetExtremasAroundMousePointer(min, max,
+                                                          this->mSlicers[slicer]->GetImage()->GetVTKImages()[t],
+                                                          this->mSlicers[slicer]->GetConcatenatedTransform());
+    this->SetColorWindow(max-min);
+    this->SetColorLevel(0.5*(min+max));
+    this->SetPreset(WL_USER);
+  }
+  this->Render();
+  this->UpdateWindowLevel();
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::SetColorMap(int colormap)
+{ 
+  double range[2];
+
+  range[0] = mSlicers[0]->GetInput()->GetScalarRange()[0];
+  range[1] = mSlicers[0]->GetInput()->GetScalarRange()[1];
+
+  double window = mSlicers[0]->GetWindowLevel()->GetWindow();
+  double level = mSlicers[0]->GetWindowLevel()->GetLevel();
+
+  vtkLookupTable* LUT = static_cast<vtkLookupTable*>(mSlicers[0]->GetWindowLevel()->GetLookupTable());
+  switch (colormap) {
+  case -1:
+    break;
+  case 0:
+    LUT = NULL;
+    break;
+  case 1:
+    if (LUT == NULL)
+      LUT = vtkLookupTable::New();
+    LUT->SetValueRange(0,1);
+    LUT->SetSaturationRange(1,1);
+    LUT->SetHueRange(0,0.18);
+    break;
+  case 2:
+    if (LUT == NULL)
+      LUT = vtkLookupTable::New();
+    LUT->SetValueRange(0,1);
+    LUT->SetSaturationRange(1,1);
+    LUT->SetHueRange(0.4,0.80);
+    break;
+  case 3:
+    if (LUT == NULL)
+      LUT = vtkLookupTable::New();
+    LUT->SetValueRange(0.5,1);
+    LUT->SetSaturationRange(1,1);
+    LUT->SetHueRange(0.666,0);
+    break;
+  case 4:
+    if (LUT == NULL)
+      LUT = vtkLookupTable::New();
+    LUT->SetValueRange(1,1);
+    LUT->SetSaturationRange(1,1);
+    LUT->SetHueRange(0,1);
+    LUT->SetAlphaRange(1, 1);
+    break;
+  case 5:
+    if (LUT == NULL)
+      LUT = vtkLookupTable::New();
+    LUT->SetValueRange(1,1);
+    LUT->SetSaturationRange(1,1);
+    LUT->SetHueRange(1,0.1);
+    //LUT->SetRampToLinear();
+    break;
+  }
+  if (LUT) {
+    LUT->SetTableRange(level-fabs(window)/2,level+fabs(window)/2);
+    LUT->Build();
+  }
+  vtkWindowLevelLookupTable* fusLUT = NULL;
+
+  //FUSION / FUSION SEQUENCE
+  if (mSlicers[0]->GetFusion()) { // && mFusionColorMap >= 0) {
+    fusLUT = vtkWindowLevelLookupTable::New();
+    double fusRange [2];
+    fusRange[0] = mFusionLevel - mFusionWindow/2;
+    fusRange[1] = mFusionLevel + mFusionWindow/2;
+
+    //check whether it is actually a fusionSequence or a fusion, before invoking mFusionReader...
+    double* frange;
+    if (this->IsInvolvedInFusionSequence()) 
+      frange = mFusionSequenceReader->GetOutput()->GetVTKImages()[0]->GetScalarRange();
+    else
+      frange = mFusionReader->GetOutput()->GetVTKImages()[0]->GetScalarRange();
+
+    fusLUT->SetTableRange(frange);
+    fusLUT->SetValueRange(1,1);
+    fusLUT->SetSaturationRange(1,1);
+    fusLUT->SetAlphaRange(1, 1);
+    fusLUT->SetWindow(mFusionWindow);
+    fusLUT->SetLevel(mFusionLevel);
+    if (mFusionColorMap == 1)
+      fusLUT->SetHueRange(0,0.18);
+    else if (mFusionColorMap == 2)
+      fusLUT->SetHueRange(0.4,0.80);
+    else if (mFusionColorMap == 3)
+    {
+      fusLUT->SetHueRange(0.666, 0);
+      fusLUT->SetValueRange(0.5, 1);
+    }
+    else if (mFusionColorMap == 4)
+      fusLUT->SetHueRange(0,1);
+    else if (mFusionColorMap <= 0)
+    {
+      fusLUT->SetValueRange(0,1);
+      fusLUT->SetSaturationRange(0,0);
+    }
+
+    fusLUT->ForceBuild();
+    double v[4];
+    // set color table transparency
+    //double alpha_range=(double)mFusionThresOpacity/10;
+    double range_end = fusRange[0] + (double)mFusionThresOpacity*(fusRange[1] - fusRange[0])/100;
+    double curr_value = fusRange[0];
+    int nvalues = fusLUT->GetNumberOfTableValues();
+    for (double i = 0; curr_value < range_end; i++) {  
+      fusLUT->GetTableValue(i, v);
+      v[3] = 0;
+      //if (curr_value >= -alpha_range && curr_value <= alpha_range) v[3] = pow(fabs(curr_value/alpha_range),2);
+      //else v[3] = 1;
+      fusLUT->SetTableValue(i, v);
+      curr_value += (fusRange[1] - fusRange[0])/nvalues;
+    }
+  }
+  for ( unsigned int i = 0; i < mSlicers.size(); i++) {
+
+    if (mSlicers[i]->GetOverlay()) {
+      vtkLookupTable* supLUT = vtkLookupTable::New();
+      supLUT->SetTableRange(range[0],range[1]);
+      supLUT->SetValueRange(1,1);
+      supLUT->SetSaturationRange(1,1);
+      supLUT->SetHueRange(double(mOverlayColor)/360,double(mOverlayColor)/360);
+      supLUT->Build();
+      vtkLookupTable* invLUT = vtkLookupTable::New();
+      invLUT->SetTableRange(range[0],range[1]);
+      invLUT->SetValueRange(1,1);
+      invLUT->SetSaturationRange(1,1);
+      invLUT->SetHueRange(double((mOverlayColor+180)%360)/360,double((mOverlayColor+180)%360)/360);
+      invLUT->Build();
+      mSlicers[i]->GetWindowLevel()->SetLookupTable(supLUT);
+      mSlicers[i]->GetOverlayMapper()->SetLookupTable(invLUT);
+      invLUT->Delete();
+      supLUT->Delete();
+    } else if (mSlicers[i]->GetOverlay()) {
+      mSlicers[i]->GetWindowLevel()->SetLookupTable(LUT);
+    } else {
+      mSlicers[i]->GetWindowLevel()->SetLookupTable(LUT);
+    }
+
+    if (mSlicers[i]->GetFusion()) {
+      mSlicers[i]->ShowFusionLegend(mFusionShowLegend);
+      mSlicers[i]->GetFusionMapper()->SetLookupTable(fusLUT);
+      mSlicers[i]->GetFusionActor()->SetOpacity(double(mFusionOpacity)/100);
+    }
+  }
+  if (fusLUT)
+    fusLUT->Delete();
+  if (colormap >= 0)
+    mColorMap = colormap;
+}
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+vvLandmarks* vvSlicerManager::GetLandmarks()
+{ 
+  if (mLandmarks == NULL) {
+    mLandmarks = new vvLandmarks(mSlicers[0]->GetTMax()+1);
+    for (unsigned int i = 0; i < mSlicers.size(); i++)
+      mSlicers[i]->SetLandmarks(mLandmarks);
+  }
+  return mLandmarks;
+}
+//----------------------------------------------------------------------------
+void vvSlicerManager::AddNewLandmark(float x,float y,float z,float t)
+{ 
+    emit callAddLandmark(x,y,z,t);
+}
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::AddLandmark(float x,float y,float z,float t)
+{ 
+  double x_index = (x - mSlicers[0]->GetInput()->GetOrigin()[0])/mSlicers[0]->GetInput()->GetSpacing()[0];
+  double y_index = (y - mSlicers[0]->GetInput()->GetOrigin()[1])/mSlicers[0]->GetInput()->GetSpacing()[1];
+  double z_index = (z - mSlicers[0]->GetInput()->GetOrigin()[2])/mSlicers[0]->GetInput()->GetSpacing()[2];
+#if VTK_MAJOR_VERSION <= 5
+  if (x_index >= mSlicers[0]->GetInput()->GetWholeExtent()[0]-0.5 &&
+      x_index <= mSlicers[0]->GetInput()->GetWholeExtent()[1]+0.5 &&
+      y_index >= mSlicers[0]->GetInput()->GetWholeExtent()[2]-0.5 &&
+      y_index <= mSlicers[0]->GetInput()->GetWholeExtent()[3]+0.5 &&
+      z_index >= mSlicers[0]->GetInput()->GetWholeExtent()[4]-0.5 &&
+      z_index <= mSlicers[0]->GetInput()->GetWholeExtent()[5]+0.5)
+#else
+  int extentImageReslice[6];
+  mSlicers[0]->GetRegisterExtent(extentImageReslice);
+  if (x_index >= extentImageReslice[0]-0.5 &&
+      x_index <= extentImageReslice[1]+0.5 &&
+      y_index >= extentImageReslice[2]-0.5 &&
+      y_index <= extentImageReslice[3]+0.5 &&
+      z_index >= extentImageReslice[4]-0.5 &&
+      z_index <= extentImageReslice[5]+0.5)
+#endif
+  {
+    double value = this->GetScalarComponentAsDouble(mSlicers[mSelectedSlicer]->GetInput(), x_index, y_index, z_index); //Value in selected Slicer (not 0): bug #2848
+    this->GetLandmarks()->AddLandmark(x,y,z,t,value);
+    emit LandmarkAdded();
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::AddLandmarkProfile(float x,float y,float z,float t)
+{ 
+  double x_index = (x - mSlicers[0]->GetInput()->GetOrigin()[0])/mSlicers[0]->GetInput()->GetSpacing()[0];
+  double y_index = (y - mSlicers[0]->GetInput()->GetOrigin()[1])/mSlicers[0]->GetInput()->GetSpacing()[1];
+  double z_index = (z - mSlicers[0]->GetInput()->GetOrigin()[2])/mSlicers[0]->GetInput()->GetSpacing()[2];
+#if VTK_MAJOR_VERSION <= 5
+  if (x_index >= mSlicers[0]->GetInput()->GetWholeExtent()[0]-0.5 &&
+      x_index <= mSlicers[0]->GetInput()->GetWholeExtent()[1]+0.5 &&
+      y_index >= mSlicers[0]->GetInput()->GetWholeExtent()[2]-0.5 &&
+      y_index <= mSlicers[0]->GetInput()->GetWholeExtent()[3]+0.5 &&
+      z_index >= mSlicers[0]->GetInput()->GetWholeExtent()[4]-0.5 &&
+      z_index <= mSlicers[0]->GetInput()->GetWholeExtent()[5]+0.5)
+#else
+  int extentImageReslice[6];
+  mSlicers[0]->GetRegisterExtent(extentImageReslice);
+  if (x_index >= extentImageReslice[0]-0.5 &&
+      x_index <= extentImageReslice[1]+0.5 &&
+      y_index >= extentImageReslice[2]-0.5 &&
+      y_index <= extentImageReslice[3]+0.5 &&
+      z_index >= extentImageReslice[4]-0.5 &&
+      z_index <= extentImageReslice[5]+0.5)
+#endif
+  {
+    double value = this->GetScalarComponentAsDouble(mSlicers[mSelectedSlicer]->GetInput(), x_index, y_index, z_index); //Value in selected Slicer (not 0): bug #2848
+    this->GetLandmarks()->AddLandmark(x,y,z,t,value);
+  }
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::PrevImage(int slicer)
+{ 
+  emit ChangeImageWithIndexOffset(this, slicer, -1);
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::NextImage(int slicer)
+{ 
+  emit ChangeImageWithIndexOffset(this, slicer,  1);
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+void vvSlicerManager::VerticalSliderHasChanged(int slicer, int slice)
+{ 
+  emit AVerticalSliderHasChanged(slicer, slice);
+}
+
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+double vvSlicerManager::GetScalarComponentAsDouble(vtkImageData *image, double X, double Y, double Z, int component)
+{ 
+  int ix, iy, iz;
+  return mSlicers[0]->GetScalarComponentAsDouble(image, X, Y, Z, ix, iy, iz, component);
+}
+//----------------------------------------------------------------------------