diff --git a/FCLTDWF.Doc b/FCLTDWF.Doc
new file mode 100644
index 0000000..20622d0
Binary files /dev/null and b/FCLTDWF.Doc differ
diff --git a/Mouse.doc b/Mouse.doc
new file mode 100644
index 0000000..ec298db
Binary files /dev/null and b/Mouse.doc differ
diff --git a/Redistribute/.gitignore b/Redistribute/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/Redistribute/Dirinfo b/Redistribute/Dirinfo
new file mode 100644
index 0000000..d14f142
--- /dev/null
+++ b/Redistribute/Dirinfo
@@ -0,0 +1,29 @@
+Programma's gemaakt met Visual C++ 2005 zijn afhankelijk van
+
+ MSVCR80.DLL en
+ MSVCP80.DLL
+
+Daarvan zijn mij twee versies bekend
+ 8.0.50608.0
+ 8.0.50727.762
+
+De originele Visual C++ 2005 genereert afhankelijkheid naar de 8.0.50608.0 versie van de DLL's.
+Na Servicepack 1 is er een afhankelijkheid naar versie 8.0.50727.762
+
+De versienummer afhankelijkheid wordt geforceerd door de Manifest die embedded
+wordt in DLL's en of EXE's.
+
+'Zo maar' de goede DLL's in C:\Windows\System32 zetten werkt niet en vooral: hoort niet.
+Je wordt geacht (de goede) vcredist_86.exe te draaien die de DLL's installeert op de goede plek.
+
+Onder Windows 2000 doet hij dat inderdaad ook nog in C:\Windows\System32
+
+Onder Windows 2003 en XP worden ze netjes volgens de side-by-side methode
+geinstalleerd onder C:\Windows\WinSxS
+
+Als je de nieuwste van de twee installeert dan komt er onder c:\WINdows\winsxs\Policies
+nog een bestandje wat versie 8.0.50608.0 redirect naar 8.0.50727.762
+
+"c:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages\vcredist_x86\vcredist_x86.exe"
+
+gdiplus.dll is included in Windows XP and Windows Server 2003
\ No newline at end of file
diff --git a/Redistribute/vcredist_x86.exe b/Redistribute/vcredist_x86.exe
new file mode 100644
index 0000000..1421c29
Binary files /dev/null and b/Redistribute/vcredist_x86.exe differ
diff --git a/Redistribute/vcredist_x86_SP1_8.0.50727.762.exe b/Redistribute/vcredist_x86_SP1_8.0.50727.762.exe
new file mode 100644
index 0000000..47f87a0
Binary files /dev/null and b/Redistribute/vcredist_x86_SP1_8.0.50727.762.exe differ
diff --git a/RemoveAbout/.gitignore b/RemoveAbout/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/RemoveAbout/RemoveAbout.vcproj b/RemoveAbout/RemoveAbout.vcproj
new file mode 100644
index 0000000..52c304c
--- /dev/null
+++ b/RemoveAbout/RemoveAbout.vcproj
@@ -0,0 +1,188 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/RemoveAbout/RemoveAbout.vcproj.DIJKORAAD.jgl.user b/RemoveAbout/RemoveAbout.vcproj.DIJKORAAD.jgl.user
new file mode 100644
index 0000000..c1bd4d5
--- /dev/null
+++ b/RemoveAbout/RemoveAbout.vcproj.DIJKORAAD.jgl.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SLNKDWF.sln b/SLNKDWF.sln
new file mode 100644
index 0000000..9b28c61
--- /dev/null
+++ b/SLNKDWF.sln
@@ -0,0 +1,95 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SLNKDWFViewer", "Standalone\SLNKDWFViewer.vcproj", "{B2601E72-4FF4-4B9C-A89F-C2E7DACF36FD}"
+ ProjectSection(ProjectDependencies) = postProject
+ {6DFC9788-904C-4724-A734-06634061EF00} = {6DFC9788-904C-4724-A734-06634061EF00}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Viewer", "Viewer\Viewer.vcproj", "{6DFC9788-904C-4724-A734-06634061EF00}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CF524F70-4DDD-4040-803B-41B5DE7B1CF9} = {CF524F70-4DDD-4040-803B-41B5DE7B1CF9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WincmdViewer", "WincmdViewer\WINCDMDWF.vcproj", "{92F5EB69-069C-43EA-97E7-2F6507AA5873}"
+ ProjectSection(ProjectDependencies) = postProject
+ {6DFC9788-904C-4724-A734-06634061EF00} = {6DFC9788-904C-4724-A734-06634061EF00}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WincmdContent", "WincmdContent\filesys.vcproj", "{2F492A95-A23D-45C9-BBD9-E5B9325B22C1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {CF524F70-4DDD-4040-803B-41B5DE7B1CF9} = {CF524F70-4DDD-4040-803B-41B5DE7B1CF9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WincmdPacker", "WincmdPacker\WincmdPacker.vcproj", "{18EC7157-E263-458C-A41C-52E9538A642F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {6EA5FCEC-1DB0-4542-8E41-9423021BD460} = {6EA5FCEC-1DB0-4542-8E41-9423021BD460}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SLNKDWFStaticRO", "SlnkDWFImpl\SLNKDWFStaticRO.vcproj", "{CF524F70-4DDD-4040-803B-41B5DE7B1CF9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SLNKDWFCom", "SlnkDWFCom\SLNKDWF.vcproj", "{7F9F1060-C14D-4DD5-91D3-FA7263FECF5E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {89BE476D-6C02-4514-BFCE-256106D98713} = {89BE476D-6C02-4514-BFCE-256106D98713}
+ {6EA5FCEC-1DB0-4542-8E41-9423021BD460} = {6EA5FCEC-1DB0-4542-8E41-9423021BD460}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SLNKDWFStaticRW", "SlnkDWFImpl\SLNKDWFStaticRW.vcproj", "{6EA5FCEC-1DB0-4542-8E41-9423021BD460}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tiff", "SlnkDWFImpl\CxImage\tiff\Tiff.vcproj", "{B61F3CD8-D974-4127-8335-557650DA8B5E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B0573FCD-8E98-421C-8BA3-F47CEB1F1047}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RemoveAbout", "RemoveAbout\RemoveAbout.vcproj", "{89BE476D-6C02-4514-BFCE-256106D98713}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B2601E72-4FF4-4B9C-A89F-C2E7DACF36FD}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B2601E72-4FF4-4B9C-A89F-C2E7DACF36FD}.Debug|Win32.Build.0 = Debug|Win32
+ {B2601E72-4FF4-4B9C-A89F-C2E7DACF36FD}.Release|Win32.ActiveCfg = Release|Win32
+ {B2601E72-4FF4-4B9C-A89F-C2E7DACF36FD}.Release|Win32.Build.0 = Release|Win32
+ {6DFC9788-904C-4724-A734-06634061EF00}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6DFC9788-904C-4724-A734-06634061EF00}.Debug|Win32.Build.0 = Debug|Win32
+ {6DFC9788-904C-4724-A734-06634061EF00}.Release|Win32.ActiveCfg = Release|Win32
+ {6DFC9788-904C-4724-A734-06634061EF00}.Release|Win32.Build.0 = Release|Win32
+ {92F5EB69-069C-43EA-97E7-2F6507AA5873}.Debug|Win32.ActiveCfg = Debug|Win32
+ {92F5EB69-069C-43EA-97E7-2F6507AA5873}.Debug|Win32.Build.0 = Debug|Win32
+ {92F5EB69-069C-43EA-97E7-2F6507AA5873}.Release|Win32.ActiveCfg = Release|Win32
+ {92F5EB69-069C-43EA-97E7-2F6507AA5873}.Release|Win32.Build.0 = Release|Win32
+ {2F492A95-A23D-45C9-BBD9-E5B9325B22C1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2F492A95-A23D-45C9-BBD9-E5B9325B22C1}.Debug|Win32.Build.0 = Debug|Win32
+ {2F492A95-A23D-45C9-BBD9-E5B9325B22C1}.Release|Win32.ActiveCfg = Release|Win32
+ {2F492A95-A23D-45C9-BBD9-E5B9325B22C1}.Release|Win32.Build.0 = Release|Win32
+ {18EC7157-E263-458C-A41C-52E9538A642F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {18EC7157-E263-458C-A41C-52E9538A642F}.Debug|Win32.Build.0 = Debug|Win32
+ {18EC7157-E263-458C-A41C-52E9538A642F}.Release|Win32.ActiveCfg = Release|Win32
+ {18EC7157-E263-458C-A41C-52E9538A642F}.Release|Win32.Build.0 = Release|Win32
+ {CF524F70-4DDD-4040-803B-41B5DE7B1CF9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CF524F70-4DDD-4040-803B-41B5DE7B1CF9}.Debug|Win32.Build.0 = Debug|Win32
+ {CF524F70-4DDD-4040-803B-41B5DE7B1CF9}.Release|Win32.ActiveCfg = Release|Win32
+ {CF524F70-4DDD-4040-803B-41B5DE7B1CF9}.Release|Win32.Build.0 = Release|Win32
+ {7F9F1060-C14D-4DD5-91D3-FA7263FECF5E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7F9F1060-C14D-4DD5-91D3-FA7263FECF5E}.Debug|Win32.Build.0 = Debug|Win32
+ {7F9F1060-C14D-4DD5-91D3-FA7263FECF5E}.Release|Win32.ActiveCfg = Release|Win32
+ {7F9F1060-C14D-4DD5-91D3-FA7263FECF5E}.Release|Win32.Build.0 = Release|Win32
+ {6EA5FCEC-1DB0-4542-8E41-9423021BD460}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6EA5FCEC-1DB0-4542-8E41-9423021BD460}.Debug|Win32.Build.0 = Debug|Win32
+ {6EA5FCEC-1DB0-4542-8E41-9423021BD460}.Release|Win32.ActiveCfg = Release|Win32
+ {6EA5FCEC-1DB0-4542-8E41-9423021BD460}.Release|Win32.Build.0 = Release|Win32
+ {B61F3CD8-D974-4127-8335-557650DA8B5E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B61F3CD8-D974-4127-8335-557650DA8B5E}.Debug|Win32.Build.0 = Debug|Win32
+ {B61F3CD8-D974-4127-8335-557650DA8B5E}.Release|Win32.ActiveCfg = Release|Win32
+ {B61F3CD8-D974-4127-8335-557650DA8B5E}.Release|Win32.Build.0 = Release|Win32
+ {89BE476D-6C02-4514-BFCE-256106D98713}.Debug|Win32.ActiveCfg = Debug|Win32
+ {89BE476D-6C02-4514-BFCE-256106D98713}.Debug|Win32.Build.0 = Debug|Win32
+ {89BE476D-6C02-4514-BFCE-256106D98713}.Release|Win32.ActiveCfg = Release|Win32
+ {89BE476D-6C02-4514-BFCE-256106D98713}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/SlnkDWFCom/.gitignore b/SlnkDWFCom/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/SlnkDWFCom/About.cpp b/SlnkDWFCom/About.cpp
new file mode 100644
index 0000000..0565d49
--- /dev/null
+++ b/SlnkDWFCom/About.cpp
@@ -0,0 +1,96 @@
+// About.cpp : Implementation of CAbout
+
+#include "stdafx.h"
+#include "About.h"
+#include "SLNKDWFVersion.h"
+
+#define SECURITY_WIN32
+#include "Security.h"
+
+// CAbout
+extern HINSTANCE g_hInstance;
+
+// In release mode verwijderen we altijd About.obj om hercompile te forceren
+CString buildDATE(__DATE__);
+CString buildTIME(__TIME__);
+
+STDMETHODIMP CAbout::get_All(BSTR* pVal)
+{
+ char module[_MAX_PATH]; // HMODULE
+ GetModuleFileName(g_hInstance, module, sizeof(module)/sizeof(char));
+ char name[_MAX_PATH]; // HMODULE
+ ULONG cnt = sizeof(name)/sizeof(char);
+ if (!GetUserNameEx(NameSamCompatible, name, &cnt))
+ {
+ myTRACE("\nGetUserNameEx failed (%d): %s", GetLastError(), myGetLastErrorMsg());
+ }
+
+ CString result;
+ result.Format(" SLNKDWF: built on %s, %s"
+ "\n DLL: %s"
+ "\nUsercontext: %s", buildDATE, buildTIME, module, name);
+ (*pVal) = result.AllocSysString();
+
+ return S_OK;
+}
+
+STDMETHODIMP CAbout::get_DLLPath(BSTR* pVal)
+{
+ char module[_MAX_PATH]; // HMODULE
+ GetModuleFileName(g_hInstance, module, sizeof(module));
+
+ CString result;
+ result.Format("%s", module);
+ (*pVal) = result.AllocSysString();
+
+ return S_OK;
+}
+
+STDMETHODIMP CAbout::get_Buildtime(BSTR* pVal)
+{
+ CString result;
+ result.Format("%s, %s", buildDATE, buildTIME);
+ (*pVal) = result.AllocSysString();
+
+ return S_OK;
+}
+
+STDMETHODIMP CAbout::get_UserContext(BSTR* pVal)
+{
+ char name[_MAX_PATH]; // HMODULE
+ ULONG cnt = sizeof(name)/sizeof(char);
+ CString result;
+ if (!GetUserNameEx(NameSamCompatible, name, &cnt))
+ {
+ myTRACE("\nGetUserNameEx failed (%d): %s", GetLastError(), myGetLastErrorMsg());
+ result = "Unable to detect user";
+ }
+ else
+ result = name;
+
+ (*pVal) = result.AllocSysString();
+
+ return S_OK;
+}
+
+STDMETHODIMP CAbout::get_VersionMajor(LONG* pVal)
+{
+ (*pVal) = SLNK_MAJOR_VERSION;
+
+ return S_OK;
+}
+
+STDMETHODIMP CAbout::get_VersionMinor(LONG* pVal)
+{
+ (*pVal) = SLNK_MINOR_VERSION;
+
+ return S_OK;
+}
+
+STDMETHODIMP CAbout::get_VersionString(BSTR* pVal)
+{
+ CString result = SLNK_BUILDVERSION;
+ (*pVal) = result.AllocSysString();
+
+ return S_OK;
+}
diff --git a/SlnkDWFCom/About.h b/SlnkDWFCom/About.h
new file mode 100644
index 0000000..f1dadc5
--- /dev/null
+++ b/SlnkDWFCom/About.h
@@ -0,0 +1,52 @@
+// About.h : Declaration of the CAbout
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+
+
+// CAbout
+
+class ATL_NO_VTABLE CAbout :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IDispatchImpl
+{
+public:
+ CAbout()
+ {
+ }
+
+DECLARE_REGISTRY_RESOURCEID(IDR_ABOUT)
+
+
+BEGIN_COM_MAP(CAbout)
+ COM_INTERFACE_ENTRY(IAbout)
+ COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+public:
+
+ STDMETHOD(get_All)(BSTR* pVal);
+ STDMETHOD(get_DLLPath)(BSTR* pVal);
+ STDMETHOD(get_Buildtime)(BSTR* pVal);
+ STDMETHOD(get_UserContext)(BSTR* pVal);
+ STDMETHOD(get_VersionMajor)(LONG* pVal);
+ STDMETHOD(get_VersionMinor)(LONG* pVal);
+ STDMETHOD(get_VersionString)(BSTR* pVal);
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(About), CAbout)
diff --git a/SlnkDWFCom/About.rgs b/SlnkDWFCom/About.rgs
new file mode 100644
index 0000000..1b1e966
--- /dev/null
+++ b/SlnkDWFCom/About.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ SLNKDWF.About.1 = s 'About Class'
+ {
+ CLSID = s '{2BA64B82-1A96-4F15-9815-40B291B505EB}'
+ }
+ SLNKDWF.About = s 'About Class'
+ {
+ CLSID = s '{2BA64B82-1A96-4F15-9815-40B291B505EB}'
+ CurVer = s 'SLNKDWF.About.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {2BA64B82-1A96-4F15-9815-40B291B505EB} = s 'About Class'
+ {
+ ProgID = s 'SLNKDWF.About.1'
+ VersionIndependentProgID = s 'SLNKDWF.About'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/BoundingBox.cpp b/SlnkDWFCom/BoundingBox.cpp
new file mode 100644
index 0000000..45907ef
--- /dev/null
+++ b/SlnkDWFCom/BoundingBox.cpp
@@ -0,0 +1,17 @@
+// BoundingBox.cpp : Implementation of CBoundingBox
+
+#include "stdafx.h"
+#include "BoundingBox.h"
+
+
+// CBoundingBox
+
+STDMETHODIMP CBoundingBox::get_min(IDWGPoint** pVal)
+{
+ return m_minPoint->QueryInterface(IID_IDWGPoint, (void**)pVal);
+}
+
+STDMETHODIMP CBoundingBox::get_max(IDWGPoint** pVal)
+{
+ return m_maxPoint->QueryInterface(IID_IDWGPoint, (void**)pVal);
+};
diff --git a/SlnkDWFCom/BoundingBox.h b/SlnkDWFCom/BoundingBox.h
new file mode 100644
index 0000000..7e60835
--- /dev/null
+++ b/SlnkDWFCom/BoundingBox.h
@@ -0,0 +1,75 @@
+// BoundingBox.h : Declaration of the CBoundingBox
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+#include "DWGPoint.h"
+
+
+// CBoundingBox
+
+class ATL_NO_VTABLE CBoundingBox :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IDispatchImpl
+{
+public:
+ CBoundingBox()
+ {
+ }
+
+//REMOVED DECLARE_REGISTRY_RESOURCEID(IDR_BOUNDINGBOX)
+
+
+BEGIN_COM_MAP(CBoundingBox)
+ COM_INTERFACE_ENTRY(IBoundingBox)
+ COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ //
+ // Maak object m_minPoint
+ //
+ CComObject *pDWGPoint;
+ HRESULT hr = CComObject::CreateInstance(&pDWGPoint);
+ if(FAILED(hr)) return hr;
+
+ pDWGPoint->AddRef();
+ hr = pDWGPoint->QueryInterface(IID_IDWGPoint, (void **)&m_minPoint);
+ pDWGPoint->Release();
+ if(FAILED(hr)) return hr;
+
+ //
+ // Maak object m_maxPoint
+ //
+ hr = CComObject::CreateInstance(&pDWGPoint);
+ if(FAILED(hr)) return hr;
+
+ pDWGPoint->AddRef();
+ hr = pDWGPoint->QueryInterface(IID_IDWGPoint, (void **)&m_maxPoint);
+ pDWGPoint->Release();
+ if(FAILED(hr)) return hr;
+
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+private:
+ CComQIPtr m_minPoint;
+ CComQIPtr m_maxPoint;
+
+public:
+ STDMETHOD(get_min)(IDWGPoint** pVal);
+ STDMETHOD(get_max)(IDWGPoint** pVal);
+
+};
+
+//REMOVED OBJECT_ENTRY_AUTO(__uuidof(BoundingBox), CBoundingBox)
diff --git a/SlnkDWFCom/BoundingBox.rgs b/SlnkDWFCom/BoundingBox.rgs
new file mode 100644
index 0000000..f406ac5
--- /dev/null
+++ b/SlnkDWFCom/BoundingBox.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ SLNKDWF.BoundingBox.1 = s 'BoundingBox Class'
+ {
+ CLSID = s '{FCEF1E56-36FF-4F66-BEA5-FD08D860524F}'
+ }
+ SLNKDWF.BoundingBox = s 'BoundingBox Class'
+ {
+ CLSID = s '{FCEF1E56-36FF-4F66-BEA5-FD08D860524F}'
+ CurVer = s 'SLNKDWF.BoundingBox.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {FCEF1E56-36FF-4F66-BEA5-FD08D860524F} = s 'BoundingBox Class'
+ {
+ ProgID = s 'SLNKDWF.BoundingBox.1'
+ VersionIndependentProgID = s 'SLNKDWF.BoundingBox'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/DWFFile.cpp b/SlnkDWFCom/DWFFile.cpp
new file mode 100644
index 0000000..330c4bf
--- /dev/null
+++ b/SlnkDWFCom/DWFFile.cpp
@@ -0,0 +1,83 @@
+// DWFFile.cpp : Implementation of CDWFFile
+
+#include "stdafx.h"
+#include "assert.h"
+#include "DWFFile.h"
+
+#include "myEPlotSection.h"
+
+// CDWFFile
+
+STDMETHODIMP CDWFFile::InterfaceSupportsErrorInfo(REFIID riid)
+{
+ static const IID* arr[] =
+ {
+ &IID_IDWFFile
+ };
+
+ for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
+ {
+ if (InlineIsEqualGUID(*arr[i],riid))
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+//CDWFFile::~CDWFFile()
+//{
+// // It seems we never get here? Use FinalRelease
+//};
+
+HRESULT CDWFFile::FinalConstruct()
+{
+ m_EPlotSections.SetParent(this);
+ m_EPlotSections.SetOuterUnknown(GetControllingUnknown());
+ return m_EPlotSections.FinalConstruct();
+}
+
+// Omdat de tellingen gekoppeld zijn weten we zeker dat de refcount van
+// onze eigen objecten ook 0 zal zijn en is het dus veilig ze weg te gooien (toch...?)
+void CDWFFile::FinalRelease()
+{
+ m_EPlotSections.FinalRelease();
+}
+
+STDMETHODIMP CDWFFile::Open(BSTR DWFPath)
+{
+ try
+ {
+ if (CDWFFileImpl::Open(CString(DWFPath)))
+ {
+ return S_OK;
+ }
+ else
+ return E_FAIL;
+ }
+ catch (CString& e)
+ {
+ return myAtlReportError (GetObjectCLSID(), e);
+ }
+
+}
+
+STDMETHODIMP CDWFFile::get_PropertiesXML(BSTR* pVal)
+{
+ CString s;
+ if (CDWFFileImpl::get_PropertiesXML(s))
+ {
+ CComBSTR bstrString(s);
+ return bstrString.CopyTo(pVal);
+ }
+ else
+ return E_FAIL;
+
+ return S_OK;
+}
+
+STDMETHODIMP CDWFFile::get_EPlotSections(IEPlotSections **ppEPlotSections)
+{
+// if (!m_isOpen)
+// return myAtlReportError (GetObjectCLSID(), "\nDWF File is not opened");
+
+ return m_EPlotSections.QueryInterface(ppEPlotSections);
+}
diff --git a/SlnkDWFCom/DWFFile.h b/SlnkDWFCom/DWFFile.h
new file mode 100644
index 0000000..f37d368
--- /dev/null
+++ b/SlnkDWFCom/DWFFile.h
@@ -0,0 +1,55 @@
+// DWFFile.h : Declaration of the CDWFFile
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "DWFFileImpl.h"
+
+#include "ComObjectEmbed.h"
+#include "EPlotSections.h"
+
+#include "SLNKDWF.h"
+
+// CDWFFile
+
+class ATL_NO_VTABLE CDWFFile :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public ISupportErrorInfo,
+ public IDispatchImpl,
+ public CDWFFileImpl
+{
+public:
+ CDWFFile()
+ {
+ m_EPlotSections.InitImpl(&(CDWFFileImpl::m_EPlotSections));
+ }
+
+DECLARE_REGISTRY_RESOURCEID(IDR_DWFFILE)
+DECLARE_GET_CONTROLLING_UNKNOWN() //ADDED
+
+BEGIN_COM_MAP(CDWFFile)
+ COM_INTERFACE_ENTRY(IDWFFile)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(ISupportErrorInfo)
+END_COM_MAP()
+
+// ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct();
+
+ void FinalRelease();
+
+protected:
+ CComObjectEmbed m_EPlotSections;
+
+public:
+ STDMETHOD(Open)(BSTR DWFPath);
+ STDMETHOD(get_PropertiesXML)(BSTR* pVal);
+ STDMETHOD(get_EPlotSections)(IEPlotSections **ppEPlotSections);
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(myDWFFile), CDWFFile)
diff --git a/SlnkDWFCom/DWFFile.rgs b/SlnkDWFCom/DWFFile.rgs
new file mode 100644
index 0000000..a70ad9a
--- /dev/null
+++ b/SlnkDWFCom/DWFFile.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ SLNKDWF.DWFFile.1 = s 'DWFFile Class'
+ {
+ CLSID = s '{BE2BCD58-4971-49E6-9A70-CDDD5C01224D}'
+ }
+ SLNKDWF.DWFFile = s 'DWFFile Class'
+ {
+ CLSID = s '{BE2BCD58-4971-49E6-9A70-CDDD5C01224D}'
+ CurVer = s 'SLNKDWF.DWFFile.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {BE2BCD58-4971-49E6-9A70-CDDD5C01224D} = s 'DWFFile Class'
+ {
+ ProgID = s 'SLNKDWF.DWFFile.1'
+ VersionIndependentProgID = s 'SLNKDWF.DWFFile'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/DWGPoint.cpp b/SlnkDWFCom/DWGPoint.cpp
new file mode 100644
index 0000000..eb163a6
--- /dev/null
+++ b/SlnkDWFCom/DWGPoint.cpp
@@ -0,0 +1,32 @@
+// DWGPoint.cpp : Implementation of CDWGPoint
+
+#include "stdafx.h"
+#include "DWGPoint.h"
+
+
+// CDWGPoint
+
+STDMETHODIMP CDWGPoint::get_DwgX(DOUBLE* pVal)
+{
+ (*pVal) = m_DwgX;
+ return S_OK;
+}
+
+STDMETHODIMP CDWGPoint::put_DwgX(DOUBLE newVal)
+{
+ m_DwgX = newVal;
+ return S_OK;
+}
+STDMETHODIMP CDWGPoint::get_DwgY(DOUBLE* pVal)
+{
+ (*pVal) = m_DwgY;
+ return S_OK;
+}
+
+STDMETHODIMP CDWGPoint::put_DwgY(DOUBLE newVal)
+{
+ m_DwgY = newVal;
+ return S_OK;
+}
+
+
diff --git a/SlnkDWFCom/DWGPoint.h b/SlnkDWFCom/DWGPoint.h
new file mode 100644
index 0000000..000de15
--- /dev/null
+++ b/SlnkDWFCom/DWGPoint.h
@@ -0,0 +1,51 @@
+// DWGPoint.h : Declaration of the CDWGPoint
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+
+
+// CDWGPoint
+
+class ATL_NO_VTABLE CDWGPoint :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IDispatchImpl
+{
+public:
+ CDWGPoint()
+ {
+ }
+
+//REMOVED DECLARE_REGISTRY_RESOURCEID(IDR_DWGPOINT)
+
+
+BEGIN_COM_MAP(CDWGPoint)
+ COM_INTERFACE_ENTRY(IDWGPoint)
+ COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+protected:
+ double m_DwgX, m_DwgY;
+
+public:
+ STDMETHOD(get_DwgX)(DOUBLE* pVal);
+ STDMETHOD(put_DwgX)(DOUBLE newVal);
+ STDMETHOD(get_DwgY)(DOUBLE* pVal);
+ STDMETHOD(put_DwgY)(DOUBLE newVal);
+};
+
+//REMOVED OBJECT_ENTRY_AUTO(__uuidof(DWGPoint), CDWGPoint)
diff --git a/SlnkDWFCom/DWGPoint.rgs b/SlnkDWFCom/DWGPoint.rgs
new file mode 100644
index 0000000..e96e4b3
--- /dev/null
+++ b/SlnkDWFCom/DWGPoint.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ SLNKDWF.DWGPoint.1 = s 'DWGPoint Class'
+ {
+ CLSID = s '{96301A8D-1DC9-4900-B89D-C745C4CAEFF4}'
+ }
+ SLNKDWF.DWGPoint = s 'DWGPoint Class'
+ {
+ CLSID = s '{96301A8D-1DC9-4900-B89D-C745C4CAEFF4}'
+ CurVer = s 'SLNKDWF.DWGPoint.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {96301A8D-1DC9-4900-B89D-C745C4CAEFF4} = s 'DWGPoint Class'
+ {
+ ProgID = s 'SLNKDWF.DWGPoint.1'
+ VersionIndependentProgID = s 'SLNKDWF.DWGPoint'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/EPlotSection.rgs b/SlnkDWFCom/EPlotSection.rgs
new file mode 100644
index 0000000..88cbf71
--- /dev/null
+++ b/SlnkDWFCom/EPlotSection.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ SLNKDWF.EPlotSection.1 = s 'EPlotSection Class'
+ {
+ CLSID = s '{F2599AE6-8A08-4B5E-9C68-BD975229F0D1}'
+ }
+ SLNKDWF.EPlotSection = s 'EPlotSection Class'
+ {
+ CLSID = s '{F2599AE6-8A08-4B5E-9C68-BD975229F0D1}'
+ CurVer = s 'SLNKDWF.EPlotSection.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {F2599AE6-8A08-4B5E-9C68-BD975229F0D1} = s 'EPlotSection Class'
+ {
+ ProgID = s 'SLNKDWF.EPlotSection.1'
+ VersionIndependentProgID = s 'SLNKDWF.EPlotSection'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/EPlotSections.h b/SlnkDWFCom/EPlotSections.h
new file mode 100644
index 0000000..9f9cc67
--- /dev/null
+++ b/SlnkDWFCom/EPlotSections.h
@@ -0,0 +1,59 @@
+// EPlotSections.h : Declaration of the CEPlotSections
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+
+#include "EPlotSectionsImpl.h"
+
+#include "ComObjectEmbed.h"
+#include "myEPlotSection.h"
+
+// CEPlotSections
+
+class ATL_NO_VTABLE CEPlotSections :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public ISupportErrorInfo,
+ public IDispatchImpl
+{
+public:
+ CEPlotSections()
+ {
+ }
+
+DECLARE_GET_CONTROLLING_UNKNOWN() //ADDED
+
+BEGIN_COM_MAP(CEPlotSections)
+ COM_INTERFACE_ENTRY(IEPlotSections)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(ISupportErrorInfo)
+END_COM_MAP()
+
+// ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease() ;
+
+protected:
+ IDWFFile *m_pParent; // Non-addreffed!
+ CEPlotSectionsImpl *m_pSectionsImpl; // Pointer naar onderliggende sections
+ CAtlArray> m_EPlotSections;
+
+public:
+ void InitImpl(CEPlotSectionsImpl *epl);
+ void SetParent(IDWFFile *pParent);
+ BOOL ProcessManifest(DWFToolkit::DWFManifest& rManifest, CString sourceDescription);
+
+ STDMETHODIMP get_Parent(IDWFFile **ppParent);
+ STDMETHOD(get_Count)(LONG* pVal);
+ STDMETHOD(get_Item)(LONG i, IDispatch** pVal);
+};
diff --git a/SlnkDWFCom/EPlotSections.rgs b/SlnkDWFCom/EPlotSections.rgs
new file mode 100644
index 0000000..793ce05
--- /dev/null
+++ b/SlnkDWFCom/EPlotSections.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ SLNKDWF.EPlotSections.1 = s 'EPlotSections Class'
+ {
+ CLSID = s '{7B2E7661-9B9A-4217-A19E-745EFFF8E86D}'
+ }
+ SLNKDWF.EPlotSections = s 'EPlotSections Class'
+ {
+ CLSID = s '{7B2E7661-9B9A-4217-A19E-745EFFF8E86D}'
+ CurVer = s 'SLNKDWF.EPlotSections.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {7B2E7661-9B9A-4217-A19E-745EFFF8E86D} = s 'EPlotSections Class'
+ {
+ ProgID = s 'SLNKDWF.EPlotSections.1'
+ VersionIndependentProgID = s 'SLNKDWF.EPlotSections'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/Metafile.cpp b/SlnkDWFCom/Metafile.cpp
new file mode 100644
index 0000000..3856b7b
--- /dev/null
+++ b/SlnkDWFCom/Metafile.cpp
@@ -0,0 +1,135 @@
+/******************************************************************************
+ * File : Metafile.cpp (c) 1997-2002, Furix
+ *
+ * Author : J. Groot Lipman
+ * Project : BetterWMF
+ * Version : 4.00
+ *
+ * Function : Core file of BetterWMF. Contains all functions to convert a
+ * WMF-file or Clipboard object to a better one
+ *****************************************************************************/
+
+#include "stdafx.h"
+
+#include "metafile.h"
+
+/*****************************************************************************
+ * Static variables for CMetafile. Only temporary used for/in static playback
+ * procedures
+ */
+
+// ==========================================================================
+/*
+
+ FUNCTION : WriteMetaFileAsPlaceable
+
+ PARAMETERS : HMETAFILE - a handle to the metafile
+ LPCSTR lpstrOutFileName - filename to write to
+
+ PURPOSE : Write a metafile in placeable format
+
+ RETURNS : BOOL - TRUE is Success, FALSE is failure
+
+ COMMENTS : Fills out and writes a placeable header, followed by the
+ metafile bits, to the file.
+
+ HISTORY : 4/17/95 - Created
+
+*/
+BOOL CMetafile::WriteMetaFileAsPlaceable( HMETAFILE hOld, CSize Size, double Inch, LPCSTR lpstrOutFileName)
+{
+ FILE *OutFile;
+ //OFSTRUCT outof;
+
+ DWORD dwSize;
+ LPBYTE pBits;
+
+ ALDUSMFHEADER pAldusMFHdr;
+ // Fill out the placeable header
+ pAldusMFHdr.key = ALDUS_KEY;
+ pAldusMFHdr.hmf = NULL;
+ pAldusMFHdr.inch = (unsigned short)Inch;
+;
+ pAldusMFHdr.reserved = 0;
+ pAldusMFHdr.bbox.left = (short)0;
+ pAldusMFHdr.bbox.top = (short)0;
+ pAldusMFHdr.bbox.right = (short)Size.cx;
+ pAldusMFHdr.bbox.bottom = (short)Size.cy;
+ pAldusMFHdr.checksum = CalculateAPMCheckSum( pAldusMFHdr );
+
+ // Get the bits
+ if( (dwSize = GetMetaFileBitsEx( hOld, 0, NULL )) == 0 )
+ {
+ DeleteMetaFile( hOld );
+// myErrorBox(NULL, "Failed to Get MetaFile Bits Size");
+ return NULL;
+ }
+ // Allocate that much memory
+ if( (pBits = (LPBYTE) malloc( dwSize )) == NULL )
+ {
+ DeleteMetaFile( hOld );
+// myErrorBox(NULL, "Failed to Allocate Memory for Metafile Bits");
+ return NULL;
+ }
+ // Get the metafile bits
+ if( GetMetaFileBitsEx( hOld, dwSize, pBits ) == 0 )
+ {
+ free( pBits );
+ DeleteMetaFile( hOld );
+// myErrorBox(NULL, "Failed to Get MetaFile Bits");
+ return NULL;
+ }
+
+ // TODO: Error checking
+ // Open the file
+ OutFile = fopen( lpstrOutFileName, "wb" );
+
+ // Write the header
+ fwrite(&pAldusMFHdr, 1, sizeof( APMFILEHEADER ), OutFile);
+
+ // Write the bits
+ fwrite(pBits, 1, dwSize, OutFile );
+
+ // Close the file
+ fclose(OutFile);
+
+ // Clean up
+ free( pBits );
+ return TRUE;
+}
+// End WriteMetaFileAsPlaceable
+// ==========================================================================
+
+
+// ==========================================================================
+/*
+
+ FUNCTION : CalculateAPMCheckSum
+
+ PARAMETERS : APMFILEHEADER apmfh - A placeable header
+
+ PURPOSE : Calculates the checksum for a placeable header
+
+ RETURNS : WORD - the checksum
+
+ COMMENTS : The checksum is derived by XORing each word.
+
+ HISTORY : 4/17/95 - Created
+
+*/
+WORD CMetafile::CalculateAPMCheckSum( ALDUSMFHEADER pAldusMFHdr )
+{
+ LPWORD lpWord;
+ WORD wResult, i;
+
+ // Start with the first word
+ wResult = *(lpWord = (LPWORD)(&pAldusMFHdr));
+ // XOR in each of the other 9 words
+ for(i=1;i<=9;i++)
+ {
+ wResult ^= lpWord[i];
+ }
+ return wResult;
+}
+// End CalculateAPMCheckSum
+// ==========================================================================
diff --git a/SlnkDWFCom/Metafile.h b/SlnkDWFCom/Metafile.h
new file mode 100644
index 0000000..e0ec88f
--- /dev/null
+++ b/SlnkDWFCom/Metafile.h
@@ -0,0 +1,39 @@
+#ifndef __METAFILE_H_
+#define __METAFILE_H_
+
+#pragma pack(1)
+//
+//placeable metafile data definitions
+//
+typedef struct tagOLDRECT
+{
+ short left;
+ short top;
+ short right;
+ short bottom;
+} OLDRECT;
+
+typedef struct
+{
+ DWORD key;
+ WORD hmf;
+ OLDRECT bbox;
+ WORD inch;
+ DWORD reserved;
+ WORD checksum;
+} ALDUSMFHEADER, * LPALDUSMFHEADER, APMFILEHEADER;
+#pragma pack()
+
+#define OFFSET_TO_META sizeof (ALDUSMFHEADER)
+#define METAHEADER_SIZE sizeof (METAHEADER)
+#define ALDUS_KEY 0x9AC6CDD7
+
+class CMetafile
+{
+// Operations
+public:
+ static BOOL WriteMetaFileAsPlaceable( HMETAFILE hOld, CSize Size, double Inch, LPCSTR lpstrOutFileName);
+ static WORD CalculateAPMCheckSum( ALDUSMFHEADER pAldusMFHdr );
+};
+
+#endif // __METAFILE_H_
diff --git a/SlnkDWFCom/Options.cpp b/SlnkDWFCom/Options.cpp
new file mode 100644
index 0000000..75437d0
--- /dev/null
+++ b/SlnkDWFCom/Options.cpp
@@ -0,0 +1,50 @@
+// Options.cpp : Implementation of COptions
+
+#include "stdafx.h"
+#include "Options.h"
+
+CSLNKOptions g_SLNKOptions; // The one and only
+
+// Set all default values
+CSLNKOptions::CSLNKOptions()
+{
+ m_MinContSize = 0.20e6; // Minimale grootte voor een contour om herkend te worden
+ m_SkipContLeader = FALSE; // ARKEY tekeningen hebben een leading lijntje voor de contour
+}
+// COptions
+
+STDMETHODIMP COptions::InterfaceSupportsErrorInfo(REFIID riid)
+{
+ static const IID* arr[] =
+ {
+ &IID_IOptions
+ };
+
+ for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
+ {
+ if (InlineIsEqualGUID(*arr[i],riid))
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+STDMETHODIMP COptions::SetOption(BSTR optionName, VARIANT OptionValue)
+{
+ CComVariant val(OptionValue);
+ CString nm(optionName);
+ nm.MakeUpper();
+
+ if (nm=="MINCONTSIZE")
+ {
+ HRESULT hr = val.ChangeType(VT_R8);
+ if (FAILED(hr)) return hr;
+ g_SLNKOptions.m_MinContSize = val.dblVal;
+ }
+ if (nm=="SKIPCONTLEADER")
+ {
+ HRESULT hr = val.ChangeType(VT_BOOL);
+ if (FAILED(hr)) return hr;
+ g_SLNKOptions.m_SkipContLeader = val.boolVal;
+ }
+ return S_OK;
+}
diff --git a/SlnkDWFCom/Options.h b/SlnkDWFCom/Options.h
new file mode 100644
index 0000000..81422b8
--- /dev/null
+++ b/SlnkDWFCom/Options.h
@@ -0,0 +1,66 @@
+// Options.h : Declaration of the COptions
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+
+class CSLNKOptions
+{
+public:
+ CSLNKOptions();
+
+ double m_MinContSize; // In DWG Units
+ BOOL m_SkipContLeader; //
+};
+extern CSLNKOptions g_SLNKOptions; // The one and only
+
+// COptions
+
+class ATL_NO_VTABLE COptions :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public ISupportErrorInfo,
+ public IDispatchImpl
+{
+public:
+ COptions()
+ {
+ }
+
+DECLARE_REGISTRY_RESOURCEID(IDR_OPTIONS)
+
+
+BEGIN_COM_MAP(COptions)
+ COM_INTERFACE_ENTRY(IOptions)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(ISupportErrorInfo)
+END_COM_MAP()
+
+// ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+public:
+
+ STDMETHOD(SetOption)(BSTR optionName, VARIANT OptionValue);
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(Options), COptions)
diff --git a/SlnkDWFCom/Options.rgs b/SlnkDWFCom/Options.rgs
new file mode 100644
index 0000000..a6a3f14
--- /dev/null
+++ b/SlnkDWFCom/Options.rgs
@@ -0,0 +1,26 @@
+HKCR
+{
+ SLNKDWF.Options.1 = s 'Options Class'
+ {
+ CLSID = s '{168678A9-6FA7-49C3-B839-DFDF07E0A79A}'
+ }
+ SLNKDWF.Options = s 'Options Class'
+ {
+ CLSID = s '{168678A9-6FA7-49C3-B839-DFDF07E0A79A}'
+ CurVer = s 'SLNKDWF.Options.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {168678A9-6FA7-49C3-B839-DFDF07E0A79A} = s 'Options Class'
+ {
+ ProgID = s 'SLNKDWF.Options.1'
+ VersionIndependentProgID = s 'SLNKDWF.Options'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/SLNKContour.cpp b/SlnkDWFCom/SLNKContour.cpp
new file mode 100644
index 0000000..68e25a1
--- /dev/null
+++ b/SlnkDWFCom/SLNKContour.cpp
@@ -0,0 +1,138 @@
+// SLNKContour.cpp : Implementation of CSLNKContour
+
+#include "stdafx.h"
+#include "SLNKContour.h"
+#include "Whipfile.h"
+
+// Merk op dat sommige functies ook nog in WhipFile zijn gedefinieerd. Die moeten daar weg omdat we
+// tegenwoordig (mei 2007) via WhipFile.Contour("label") een Contour object opleveren waar je alles
+// maar op doet, of beter nog mettertijd WhipFile.Contours.Item("label")
+// Voor backward compatibiliteit laten we de Whipfile nog maar even intact
+
+// CSLNKContour
+
+void CSLNKContour::SetImpl(CSLNKContourImpl * pSLNKContour)
+{
+ m_SLNKContour = pSLNKContour;
+ if (m_SLNKContour->m_fromSymbol) return; // Die zijn vast nog niet getransformeerd
+
+ WT_Logical_Box bx = pSLNKContour->bounds();
+
+ WT_Point3D dwgPt;
+ CComQIPtr pt;
+
+ dwgPt = pSLNKContour->m_parentWhipFileState->m_contunits.transform(bx.minpt());
+ m_dwgBounding->get_min(&pt);
+ pt->put_DwgX(dwgPt.m_x);
+ pt->put_DwgY(dwgPt.m_y);
+ pt.Release();
+
+ dwgPt = pSLNKContour->m_parentWhipFileState->m_contunits.transform(bx.maxpt());
+ m_dwgBounding->get_max(&pt);
+ pt->put_DwgX(dwgPt.m_x);
+ pt->put_DwgY(dwgPt.m_y);
+ pt.Release();
+
+ WT_Logical_Point lp = CSLNKContourImpl::Centroid(*pSLNKContour);
+ dwgPt = pSLNKContour->m_parentWhipFileState->m_contunits.transform(lp);
+ m_dwgCenter->put_DwgX(dwgPt.m_x);
+ m_dwgCenter->put_DwgY(dwgPt.m_y);
+};
+
+STDMETHODIMP CSLNKContour::SetColor(ULONG rgb, BYTE Alpha /*=0*/)
+{
+ int b=rgb%256;
+ int g=(rgb>>8)%256;
+ int r=(rgb>>16)%256;
+ m_SLNKContour->m_Color.set(r, g, b, Alpha);
+
+ return S_OK;
+}
+
+// De FriendlyName verschijnt uiteindelijk als tooltip
+STDMETHODIMP CSLNKContour::SetUrl(BSTR Url, BSTR FriendlyName)
+{
+ CString fName(FriendlyName);
+ if (fName=="")
+ fName=m_SLNKContour->m_contLabel.ascii();
+
+ // Merk op: \n lijkt \012 te zijn?
+ fName.Replace("\012", "\\n"); // Anders corrupte (ascii?) DWF
+ fName.Replace("\015", "\\n"); // Anders corrupte (ascii?) DWF
+
+ if (WT_String::is_ascii(fName.GetLength(), fName))
+ m_SLNKContour->m_Url.set( WD_URL_Optimize, (LPCSTR)CString(Url), (LPCSTR)fName);
+ else
+ { // Use UNICODE for example for Michaël
+ CStringW s(fName);
+ m_SLNKContour->m_Url.set( WD_URL_Optimize, Url, s);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKContour::get_Area(DOUBLE* pVal)
+{
+ *pVal = m_SLNKContour->m_DWGArea;
+
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKContour::get_Extents(IBoundingBox** pVal)
+{
+ if (m_SLNKContour->m_fromSymbol)
+ return E_NOTIMPL; // (nog) niet op symbolen
+
+ return m_dwgBounding->QueryInterface(IID_IBoundingBox, (void**)pVal);
+}
+
+STDMETHODIMP CSLNKContour::get_Center(IDWGPoint** pVal)
+{
+ if (m_SLNKContour->m_fromSymbol)
+ return E_NOTIMPL; // (nog) niet op symbolen
+ return m_dwgCenter->QueryInterface(IID_IDWGPoint, (void**)pVal);
+}
+
+STDMETHODIMP CSLNKContour::get_Key(BSTR* pVal)
+{
+ CComBSTR bstrString(m_SLNKContour->m_Key);
+
+ return bstrString.CopyTo(pVal);
+}
+
+STDMETHODIMP CSLNKContour::put_Key(BSTR newVal)
+{
+ CString key(newVal);
+ m_SLNKContour->m_Key = key;
+
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKContour::get_Label(BSTR* pVal)
+{
+ CComBSTR bstrString(m_SLNKContour->m_ExtraLabel);
+ return bstrString.CopyTo(pVal);
+}
+
+STDMETHODIMP CSLNKContour::put_Label(BSTR newVal)
+{
+ CString key(newVal);
+ m_SLNKContour->m_ExtraLabel = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKContour::get_Hatch(BYTE* pVal)
+{
+ (*pVal) = m_SLNKContour->m_Pattern;
+
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKContour::put_Hatch(BYTE newVal)
+{
+ WT_Fill_Pattern patt = WT_Fill_Pattern((WT_Fill_Pattern::WT_Pattern_ID)newVal);
+ m_SLNKContour->m_Pattern.set(patt);
+ //contour->m_Pattern.pattern_scale() = 1.0;
+
+ return S_OK;
+}
diff --git a/SlnkDWFCom/SLNKContour.h b/SlnkDWFCom/SLNKContour.h
new file mode 100644
index 0000000..c68e730
--- /dev/null
+++ b/SlnkDWFCom/SLNKContour.h
@@ -0,0 +1,104 @@
+// SLNKContour.h : Declaration of the CSLNKContour
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+#include "SLNKContourImpl.h"
+#include "BoundingBox.h"
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+
+
+// CSLNKContour
+
+class ATL_NO_VTABLE CSLNKContour :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IDispatchImpl
+{
+public:
+ CSLNKContour()
+ {
+ }
+
+//REMOVED DECLARE_REGISTRY_RESOURCEID(IDR_SLNKCONTOUR)
+
+
+BEGIN_COM_MAP(CSLNKContour)
+ COM_INTERFACE_ENTRY(ISLNKContour)
+ COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ //
+ // Maak object m_dwgBounding
+ //
+ CComObject *pBoundingBox;
+ HRESULT hr = CComObject::CreateInstance(&pBoundingBox);
+ if(FAILED(hr)) return hr;
+
+ pBoundingBox->AddRef();
+ hr = pBoundingBox->QueryInterface(IID_IBoundingBox, (void **)&m_dwgBounding);
+ pBoundingBox->Release();
+ if(FAILED(hr)) return hr;
+
+ //
+ // Maak object m_dwgCenter
+ //
+ CComObject *pDWGPoint;
+ hr = CComObject::CreateInstance(&pDWGPoint);
+ if(FAILED(hr)) return hr;
+
+ pDWGPoint->AddRef();
+ hr = pDWGPoint->QueryInterface(IID_IDWGPoint, (void **)&m_dwgCenter);
+ pDWGPoint->Release();
+ if(FAILED(hr)) return hr;
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+ // Deze SLNKContour wijst naar een CSLNKContourImpl in een WhipFile object. We moeten voorkomen
+ // dat deze te snel uit de scope wegvalt. Dat doen we mbv SetParent
+ // Omgekeerd is geen probleem: de WhipFile verwijst niet(!) naar de CSLNKContour en heeft er dus
+ // geen last van dat die wegvalt (van zijn SLNKContourImpl objecten is hij gewoon eigenaar)
+
+ void SetParent(IWhipFile *pParent)
+ {
+ HRESULT hr = pParent->QueryInterface(IID_IWhipFile, (void **)&m_parent_iWhipFile);
+ };
+ void SetImpl(CSLNKContourImpl * pSLNKContour);
+
+private:
+ CSLNKContourImpl * m_SLNKContour;
+ CComQIPtr m_dwgCenter;
+ CComQIPtr m_dwgBounding;
+ CComQIPtr m_parent_iWhipFile; // Om scope levend te houden
+
+public:
+
+ STDMETHOD(SetColor)(ULONG rgb, BYTE Alpha);
+ STDMETHOD(SetUrl) (BSTR Url, BSTR FriendlyName);
+ STDMETHOD(get_Area)(DOUBLE* pVal);
+ STDMETHOD(get_Extents)(IBoundingBox** pVal);
+ STDMETHOD(get_Center)(IDWGPoint** pVal);
+ STDMETHOD(get_Key)(BSTR* pVal);
+ STDMETHOD(put_Key)(BSTR newVal);
+ STDMETHOD(get_Label)(BSTR* pVal);
+ STDMETHOD(put_Label)(BSTR newVal);
+ STDMETHOD(get_Hatch)(BYTE* pVal);
+ STDMETHOD(put_Hatch)(BYTE newVal);
+};
+
+//REMOVED OBJECT_ENTRY_AUTO(__uuidof(SLNKContour), CSLNKContour)
diff --git a/SlnkDWFCom/SLNKContour.rgs b/SlnkDWFCom/SLNKContour.rgs
new file mode 100644
index 0000000..9063bce
--- /dev/null
+++ b/SlnkDWFCom/SLNKContour.rgs
@@ -0,0 +1,26 @@
+HKCR
+{
+ SLNKDWFCom.SLNKContour.1 = s 'SLNKContour Class'
+ {
+ CLSID = s '{476C0F28-5860-485D-BEBD-D03F68E1C930}'
+ }
+ SLNKDWFCom.SLNKContour = s 'SLNKContour Class'
+ {
+ CLSID = s '{476C0F28-5860-485D-BEBD-D03F68E1C930}'
+ CurVer = s 'SLNKDWFCom.SLNKContour.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {476C0F28-5860-485D-BEBD-D03F68E1C930} = s 'SLNKContour Class'
+ {
+ ProgID = s 'SLNKDWFCom.SLNKContour.1'
+ VersionIndependentProgID = s 'SLNKDWFCom.SLNKContour'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/SLNKDWF.cpp b/SlnkDWFCom/SLNKDWF.cpp
new file mode 100644
index 0000000..8fb3240
--- /dev/null
+++ b/SlnkDWFCom/SLNKDWF.cpp
@@ -0,0 +1,115 @@
+// SLNKDWF.cpp : Implementation of DLL Exports.
+
+#include "stdafx.h"
+
+#include "resource.h"
+#include "SLNKDWF.h"
+#include "dlldatax.h"
+
+// Detect Memory Leaks
+#ifdef _DEBUG
+//CMemLeakDetect memLeakDetect;
+#endif
+
+HINSTANCE g_hInstance;
+extern CString buildDATE;
+extern CString buildTIME;
+
+class CSLNKDWFModule : public CAtlDllModuleT< CSLNKDWFModule >
+{
+public :
+ DECLARE_LIBID(LIBID_SLNKDWFLib)
+ DECLARE_REGISTRY_APPID_RESOURCEID(IDR_SLNKDWF, "{71B32202-1B68-4E92-9C86-8F53FB298011}")
+};
+
+CSLNKDWFModule _AtlModule;
+
+
+// DLL Entry Point
+extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+{
+ g_hInstance = hInstance;
+ char module[_MAX_PATH]; // HMODULE
+
+ GetModuleFileName(g_hInstance, module, sizeof(module));
+
+ char *txt;
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH: txt = "DLL_PROCESS_ATTACH"; break;
+ case DLL_PROCESS_DETACH: txt = "DLL_PROCESS_DETACH"; break;
+ case DLL_THREAD_ATTACH: txt = "DLL_THREAD_ATTACH"; break;
+ case DLL_THREAD_DETACH: txt = "DLL_THREAD_DETACH"; break;
+ default: txt = "UNKNOWN reason";
+ }
+
+ DWORD pid = GetCurrentProcessId();
+ if (dwReason == DLL_PROCESS_ATTACH)
+ myDoTRACE("\nLoading SLNKDWF: built on %s, %s"
+ "\n DLL: %s"
+ "\n PID: %d"
+// "\n Handle: %x\n"
+ , buildDATE, buildTIME, module, pid, hInstance);
+// else
+// myDoTRACE("\nUn/Loading SLNKDWF handle %x, reason %s", hInstance, txt);
+
+#ifdef _MERGE_PROXYSTUB
+ if (!PrxDllMain(hInstance, dwReason, lpReserved))
+ return FALSE;
+#endif
+ hInstance;
+ return _AtlModule.DllMain(dwReason, lpReserved);
+}
+
+
+// Used to determine whether the DLL can be unloaded by OLE
+STDAPI DllCanUnloadNow(void)
+{
+#ifdef _MERGE_PROXYSTUB
+ HRESULT hr = PrxDllCanUnloadNow();
+ if (FAILED(hr))
+ return hr;
+#endif
+ return _AtlModule.DllCanUnloadNow();
+}
+
+
+// Returns a class factory to create an object of the requested type
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+{
+#ifdef _MERGE_PROXYSTUB
+ if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK)
+ return S_OK;
+#endif
+ return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
+}
+
+
+// DllRegisterServer - Adds entries to the system registry
+STDAPI DllRegisterServer(void)
+{
+ // registers object, typelib and all interfaces in typelib
+ HRESULT hr = _AtlModule.DllRegisterServer();
+#ifdef _MERGE_PROXYSTUB
+ if (FAILED(hr))
+ return hr;
+ hr = PrxDllRegisterServer();
+#endif
+ return hr;
+}
+
+
+// DllUnregisterServer - Removes entries from the system registry
+STDAPI DllUnregisterServer(void)
+{
+ HRESULT hr = _AtlModule.DllUnregisterServer();
+#ifdef _MERGE_PROXYSTUB
+ if (FAILED(hr))
+ return hr;
+ hr = PrxDllRegisterServer();
+ if (FAILED(hr))
+ return hr;
+ hr = PrxDllUnregisterServer();
+#endif
+ return hr;
+}
diff --git a/SlnkDWFCom/SLNKDWF.def b/SlnkDWFCom/SLNKDWF.def
new file mode 100644
index 0000000..0562f63
--- /dev/null
+++ b/SlnkDWFCom/SLNKDWF.def
@@ -0,0 +1,9 @@
+; SLNKDWF.def : Declares the module parameters.
+
+LIBRARY "SLNKDWF.DLL"
+
+EXPORTS
+ DllCanUnloadNow PRIVATE
+ DllGetClassObject PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
diff --git a/SlnkDWFCom/SLNKDWF.idl b/SlnkDWFCom/SLNKDWF.idl
new file mode 100644
index 0000000..a0e0c7f
--- /dev/null
+++ b/SlnkDWFCom/SLNKDWF.idl
@@ -0,0 +1,364 @@
+// SLNKDWF.idl : IDL source for SLNKDWF
+//
+
+// This file will be processed by the MIDL tool to
+// produce the type library (SLNKDWF.tlb) and marshalling code.
+
+#include "olectl.h"
+import "oaidl.idl";
+import "ocidl.idl";
+
+
+interface IEPlotSection;
+interface IEPlotSections;
+interface ISLNKEvent;
+interface IBoundingBox;
+interface IDWGPoint;
+//interface IChild;
+//interface ISubChild;
+
+[
+ object,
+ uuid(3C57EFD2-B1A1-4B70-A6B2-14D05401F458),
+ dual,
+ nonextensible,
+ helpstring("IDWFFile Interface"),
+ pointer_default(unique)
+]
+interface IDWFFile : IDispatch{
+ [id(1), helpstring("method Open")] HRESULT Open(BSTR DWFPath);
+ [propget, id(9), helpstring("property PropertiesXML")] HRESULT PropertiesXML([out, retval] BSTR* pVal);
+ [propget, id(10), helpstring("property EPlotSections")] HRESULT EPlotSections([out,retval] IEPlotSections **ppEPlotSections);
+};
+[
+ object,
+ uuid(B0C6AC9F-3D1E-4489-9CE9-436A220ED12F),
+ dual,
+ nonextensible,
+ helpstring("IWhipFile Interface"),
+ pointer_default(unique)
+]
+interface IWhipFile : IDispatch{
+ [id(1), helpstring("method Load")] HRESULT Load([in] BSTR WhipPath);
+ [id(2), helpstring("method LoadStream")] HRESULT LoadStream([in] VARIANT EPlotStream);
+ [id(3), helpstring("method SaveAs")] HRESULT SaveAs([in] BSTR WhipPath);
+ [id(4), helpstring("method SetLabel")] HRESULT SetLabel([in] BSTR IdentLabel, [in] BSTR ExtraLabel);
+ [id(5), helpstring("method SetColor")] HRESULT SetColor([in] BSTR IdentLabel, [in] ULONG rgb, [in, defaultvalue(0)] BYTE Alpha);
+ [id(8), helpstring("method SetLabelFont")] HRESULT SetLabelFont([in] BSTR FontName, [in] DOUBLE FontHeight, [in, defaultvalue(0)] DOUBLE FontHeightSymbols);
+ [id(9), helpstring("method SetLabelPosition")] HRESULT SetLabelPosition([in, defaultvalue(1)] BYTE LabelPos);
+ [propget, id(10), helpstring("method ContoursXML")] HRESULT ContoursXML([out, retval] BSTR* pVal);
+ [id(12), helpstring("method SetLayers")] HRESULT SetLayers([in] BSTR reContouren, [in] BSTR reLabels);
+ [propget, id(14), helpstring("property AddSymbol")] HRESULT AddSymbol([in] DOUBLE dwgX, [in] DOUBLE dwgY, BSTR symbolName, [out, retval] IUnknown** pVal);
+ [id(15), helpstring("method DefineSymbol")] HRESULT DefineSymbol([in] BSTR symbolName, [in] VARIANT EPlotStream);
+ [id(16), helpstring("method DefineBitmapSymbol")] HRESULT DefineBitmapSymbol([in] BSTR symbolName, [in] BSTR symbolPath, [in] DOUBLE height);
+ [propget, id(17), helpstring("property Contour")] HRESULT Contour([in] BSTR IdentLabel, [out, retval] IUnknown** pVal);
+ [id(18), helpstring("method SetFilterLayers")] HRESULT SetFilterLayers([in] BSTR reLayers);
+ [propget, id(19), helpstring("property hintScale")] HRESULT hintScale([out, retval] DOUBLE* pVal);
+ [propput, id(19), helpstring("property hintScale")] HRESULT hintScale([in] DOUBLE newVal);
+ [propget, id(20), helpstring("property FindInContour")] HRESULT FindInContour([in] DOUBLE dwgX, [in] DOUBLE dwgY, [out, retval] BSTR* pVal);
+};
+[
+ object,
+ uuid(FB9CAA9B-CA0A-4BF0-AA2C-47579BEFA214),
+ dual,
+ nonextensible,
+ helpstring("IWhip2PNG Interface"),
+ pointer_default(unique)
+]
+interface IWhip2PNG : IDispatch{
+ [id(1), helpstring("method Load")] HRESULT Load([in] BSTR WhipPath);
+ [id(2), helpstring("method SaveAsPng")] HRESULT SaveAsPNG([in] BSTR PNGPath);
+ [id(3), helpstring("method SaveAsWMF")] HRESULT SaveAsWMF([in] BSTR WMFPath);
+ [id(4), helpstring("method Find")] HRESULT Find([in] LONG findX, [in] LONG findY, [out, retval] BSTR* foundLabel);
+ [id(5), helpstring("method SetDimensions")] HRESULT SetDimensions([in] LONG sizeX,
+ [in] LONG sizeY, [in] LONG offsetX, [in] LONG offsetY, [in] DOUBLE dScale, [in, defaultvalue(0)] LONG lRotation);
+ [id(6), helpstring("method GetAsMap")] HRESULT GetAsMap( [out, retval] BSTR* AsMap);
+// [id(7), helpstring("method FindCoords")] HRESULT FindCoords([in] LONG findX, [in] LONG findY, [out] VARIANT* dwgX, [out] VARIANT* dwgY);
+ [propget, id(8), helpstring("property AtlRegExp")] HRESULT AtlRegExp([in] BSTR RegExp, [in] BSTR TestExp, [out, retval] BSTR* pVal);
+ [id(9), helpstring("method TextAsPNG")] HRESULT TextAsPNG(BSTR Message, [out, retval] VARIANT *ImageData);
+ [id(10), helpstring("property GetAsPNG")] HRESULT GetAsPNG([out, retval] VARIANT *ImageData);
+ [id(11), helpstring("property GetAsTransGIF")] HRESULT GetAsTransGIF([out, retval] VARIANT *ImageData);
+ [id(12), helpstring("method LoadStream")] HRESULT LoadStream([in] VARIANT DWFStream);
+ [id(13), helpstring("method SetLayers")] HRESULT SetLayers([in] BSTR RegExp);
+ [propget, id(14), helpstring("property forceBW2")] HRESULT forceBW([out, retval] VARIANT_BOOL* pVal);
+ [propput, id(14), helpstring("property forceBW2")] HRESULT forceBW([in] VARIANT_BOOL newVal);
+ [propget, id(15), helpstring("property SLNKEvent")] HRESULT SLNKEvent([out, retval] ISLNKEvent** pVal);
+ [propget, id(16), helpstring("property paperColor")] HRESULT paperColor([out, retval] LONG* pVal);
+ [propput, id(16), helpstring("property paperColor")] HRESULT paperColor([in] LONG newVal);
+ [id(17), helpstring("method ReplaceColor")] HRESULT ReplaceColor([in] LONG paperColor, [in] LONG oldColor, [in] LONG newColor);
+ [propget, id(18), helpstring("property Maximize")] HRESULT Maximize([out, retval] VARIANT_BOOL* pVal);
+ [propput, id(18), helpstring("property Maximize")] HRESULT Maximize([in] VARIANT_BOOL newVal);
+ [propget, id(19), helpstring("property dwgScale")] HRESULT dwgScale([out, retval] DOUBLE* pVal);
+ [propput, id(19), helpstring("property dwgScale")] HRESULT dwgScale([in] DOUBLE newVal);
+ [propget, id(21), helpstring("property forceGray")] HRESULT forceGray([out, retval] VARIANT_BOOL* pVal);
+ [propput, id(21), helpstring("property forceGray")] HRESULT forceGray([in] VARIANT_BOOL newVal);
+};
+[
+ object,
+ uuid(68FBB9BF-FD4C-42D4-9670-459CCF7480BE),
+ dual,
+ nonextensible,
+ helpstring("IAbout Interface"),
+ pointer_default(unique)
+]
+interface IAbout : IDispatch{
+ [propget, id(1), helpstring("property All")] HRESULT All([out, retval] BSTR* pVal);
+ [propget, id(2), helpstring("property DLLPath")] HRESULT DLLPath([out, retval] BSTR* pVal);
+ [propget, id(3), helpstring("property Buildtime")] HRESULT Buildtime([out, retval] BSTR* pVal);
+ [propget, id(4), helpstring("property UserContext")] HRESULT UserContext([out, retval] BSTR* pVal);
+ [propget, id(5), helpstring("property VersionMajor")] HRESULT VersionMajor([out, retval] LONG* pVal);
+ [propget, id(6), helpstring("property VersionMinor")] HRESULT VersionMinor([out, retval] LONG* pVal);
+ [propget, id(7), helpstring("property VersionString")] HRESULT VersionString([out, retval] BSTR* pVal);
+};
+[
+ object,
+ uuid(99560CEF-C2CE-4CB3-AE7F-6AD6CE72CC97),
+ dual,
+ nonextensible,
+ helpstring("IEPlotSection Interface"),
+ pointer_default(unique)
+]
+interface IEPlotSection : IDispatch{
+// [id(1), helpstring("method Init"),hidden] HRESULT Init([in] long *ptr);
+// [id(2), helpstring("method GetEPlotSection"),hidden] HRESULT GetEPlotSection([out] long **ptr);
+ [propget, helpstring("My Parent")] HRESULT Parent([out, retval] IEPlotSections **ppParent);
+ [propget, id(3), helpstring("property Name")] HRESULT Name([out, retval] BSTR* pVal);
+ [propget, id(4), helpstring("property Title")] HRESULT Title([out, retval] BSTR* pVal);
+ [local]
+ [id(6), helpstring("method Read")] HRESULT
+ Read([out, size_is(cb), length_is(*pcbRead)]void *pv, [in]ULONG cb, [out]ULONG *pcbRead);
+ [local]
+ [id(7), helpstring("method Write")] HRESULT
+ Write([in, size_is(cb)] const void *pv, [in]ULONG cb, [out]ULONG *pcbWritten);
+ [propget, id(8), helpstring("property PaperColor")] HRESULT PaperColor([out, retval] ULONG* pVal);
+ [id(9), helpstring("method Open")] HRESULT Open([in]BOOL bForWrite);
+ [id(10), helpstring("method Close")] HRESULT Close(void);
+ [propget, id(11), helpstring("property SourceDescription")] HRESULT SourceDescription([out, retval] BSTR* pVal);
+ [propget, id(12), helpstring("property PropertiesXML")] HRESULT PropertiesXML([out, retval] BSTR* pVal);
+ [propget, id(13), helpstring("property PaperClipWidth")] HRESULT PaperClipWidth([out, retval] DOUBLE* pVal);
+ [propget, id(14), helpstring("property EPlotSectionImpl"), hidden] HRESULT EPlotSectionImpl([out, retval] /*CEPlotSectionImpl*/BYTE ** pVal);
+ [propput, id(14), helpstring("property EPlotSectionImpl"), hidden] HRESULT EPlotSectionImpl([in] /*CEPlotSectionImpl*/ BYTE * newVal);
+};
+[
+ object,
+ uuid(32292BE4-2ACB-4BDD-AF3C-DF91ADD4EF36),
+ dual,
+ nonextensible,
+ helpstring("IEPlotSections Interface"),
+ pointer_default(unique)
+]
+interface IEPlotSections : IDispatch{
+ [propget, helpstring("My Parent")] HRESULT Parent([out, retval] IDWFFile **ppParent);
+ [propget, id(1), helpstring("property Count")] HRESULT Count([out, retval] LONG* pVal);
+ [propget, id(2), helpstring("property Item")] HRESULT Item([in] LONG i, [out, retval] IDispatch** pVal);
+};
+[
+ object,
+ uuid(BA3EEF9F-BEB1-4478-870B-3E274AF8506A),
+ dual,
+ nonextensible,
+ helpstring("ISLNKEvent Interface"),
+ pointer_default(unique)
+]
+interface ISLNKEvent : IDispatch{
+ [propget, id(1), helpstring("property DwgX")] HRESULT DwgX([out, retval] DOUBLE* pVal);
+ [propput, id(1), helpstring("property DwgX")] HRESULT DwgX([in] DOUBLE newVal);
+ [propget, id(2), helpstring("property DwgY")] HRESULT DwgY([out, retval] DOUBLE* pVal);
+ [propput, id(2), helpstring("property DwgY")] HRESULT DwgY([in] DOUBLE newVal);
+ [propget, id(7), helpstring("property ContourLabel")] HRESULT ContourLabel([out, retval] BSTR* pVal);
+ [propput, id(7), helpstring("property ContourLabel")] HRESULT ContourLabel([in] BSTR newVal);
+ [propget, id(8), helpstring("property ContourLayer")] HRESULT ContourLayer([out, retval] BSTR* pVal);
+ [propput, id(8), helpstring("property ContourLayer")] HRESULT ContourLayer([in] BSTR newVal);
+ [propget, id(9), helpstring("property TextLabel")] HRESULT TextLabel([out, retval] BSTR* pVal);
+ [propput, id(9), helpstring("property TextLabel")] HRESULT TextLabel([in] BSTR newVal);
+ [propget, id(10), helpstring("property TextLayer")] HRESULT TextLayer([out, retval] BSTR* pVal);
+ [propput, id(10), helpstring("property TextLayer")] HRESULT TextLayer([in] BSTR newVal);
+ [propget, id(11), helpstring("property found")] HRESULT found([out, retval] IDWGPoint** pVal);
+ [propget, id(12), helpstring("property dwgExtents")] HRESULT dwgExtents([out, retval] IBoundingBox** pVal);
+ [propget, id(13), helpstring("property viewExtents")] HRESULT viewExtents([out, retval] IBoundingBox** pVal);
+};
+[
+ object,
+ uuid(102FE53F-3C9A-47C6-9BAD-1434838FF53D),
+ dual,
+ nonextensible,
+ helpstring("IBoundingBox Interface"),
+ pointer_default(unique)
+]
+interface IBoundingBox : IDispatch{
+ [propget, id(1), helpstring("property min")] HRESULT min([out, retval] IDWGPoint** pVal);
+ [propget, id(2), helpstring("property max")] HRESULT max([out, retval] IDWGPoint** pVal);
+};
+[
+ object,
+ uuid(C5678016-EF7B-4476-966E-8AFD4514DB2A),
+ dual,
+ nonextensible,
+ helpstring("IDWGPoint Interface"),
+ pointer_default(unique)
+]
+interface IDWGPoint : IDispatch{
+ [propget, id(1), helpstring("property DwgX")] HRESULT DwgX([out, retval] DOUBLE* pVal);
+ [propput, id(1), helpstring("property DwgX")] HRESULT DwgX([in] DOUBLE newVal);
+ [propget, id(2), helpstring("property DwgY")] HRESULT DwgY([out, retval] DOUBLE* pVal);
+ [propput, id(2), helpstring("property DwgY")] HRESULT DwgY([in] DOUBLE newVal);
+};
+[
+ object,
+ uuid(A505B2D9-4D41-411F-B2A7-B297AA399278),
+ dual,
+ nonextensible,
+ helpstring("ISLNKContour Interface"),
+ pointer_default(unique)
+]
+interface ISLNKContour : IDispatch{
+ [id(2), helpstring("method SetColor")] HRESULT SetColor([in] ULONG rgb, [in, defaultvalue(0)] BYTE Alpha);
+ [id(3), helpstring("method SetUrl")] HRESULT SetUrl([in] BSTR Url, [in] BSTR FriendlyName);
+ [propget, id(5), helpstring("property Area")] HRESULT Area([out, retval] DOUBLE* pVal);
+ [propget, id(6), helpstring("property Extents")] HRESULT Extents([out, retval] IBoundingBox ** pVal);
+ [propget, id(7), helpstring("property Center")] HRESULT Center([out, retval] IDWGPoint** pVal);
+ [propget, id(8), helpstring("property Key")] HRESULT Key([out, retval] BSTR* pVal);
+ [propput, id(8), helpstring("property Key")] HRESULT Key([in] BSTR newVal);
+ [propget, id(9), helpstring("property Label")] HRESULT Label([out, retval] BSTR* pVal);
+ [propput, id(9), helpstring("property Label")] HRESULT Label([in] BSTR newVal);
+ [propget, id(10), helpstring("property Hatch")] HRESULT Hatch([out, retval] BYTE* pVal);
+ [propput, id(10), helpstring("property Hatch")] HRESULT Hatch([in] BYTE newVal);
+};
+[
+ object,
+ uuid(FE75E3AB-5047-4CB6-A910-FF3156CB7946),
+ dual,
+ nonextensible,
+ helpstring("ISLNKSymbol Interface"),
+ pointer_default(unique)
+]
+interface ISLNKSymbol : IDispatch{
+ [propget, id(2), helpstring("property Scale")] HRESULT Scale([out, retval] DOUBLE* pVal);
+ [propput, id(2), helpstring("property Scale")] HRESULT Scale([in] DOUBLE newVal);
+ [propget, id(3), helpstring("property Rotation")] HRESULT Rotation([out, retval] LONG* pVal);
+ [propput, id(3), helpstring("property Rotation")] HRESULT Rotation([in] LONG newVal);
+ [propget, id(4), helpstring("property Contour")] HRESULT Contour([out, retval] IUnknown** pVal);
+};
+[
+ object,
+ uuid(FC848365-3C85-490D-8CC0-DB66D73FA34E),
+ dual,
+ nonextensible,
+ helpstring("IOptions Interface"),
+ pointer_default(unique)
+]
+interface IOptions : IDispatch{
+ [id(1), helpstring("method SetOption")] HRESULT SetOption([in] BSTR optionName, VARIANT OptionValue);
+};
+[
+ uuid(B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8),
+ version(1.0),
+ helpstring("SLNKDWF 1.0 Type Library")
+]
+library SLNKDWFLib
+{
+ importlib("stdole2.tlb");
+ [
+ uuid(BE2BCD58-4971-49E6-9A70-CDDD5C01224D),
+ helpstring("DWFFile Class")
+ ]
+ coclass myDWFFile
+ {
+ [default] interface IDWFFile;
+ };
+ [
+ uuid(C2632BD5-3157-45A6-8FFC-57063FF2B169),
+ helpstring("WhipFile Class")
+ ]
+ coclass WhipFile
+ {
+ [default] interface IWhipFile;
+ };
+ [
+ uuid(783AC7F0-E6E1-4CE1-A38B-FA047D44DC1C),
+ helpstring("Whip2PNG Class")
+ ]
+ coclass Whip2PNG
+ {
+ [default] interface IWhip2PNG;
+ };
+ [
+ uuid(2BA64B82-1A96-4F15-9815-40B291B505EB),
+ helpstring("About Class")
+ ]
+ coclass About
+ {
+ [default] interface IAbout;
+ };
+ [
+ uuid(F2599AE6-8A08-4B5E-9C68-BD975229F0D1),
+ helpstring("EPlotSection Class"),
+ noncreatable
+ ]
+ coclass EPlotSection
+ {
+ [default] interface IEPlotSection;
+ };
+ [
+ uuid(7B2E7661-9B9A-4217-A19E-745EFFF8E86D),
+ helpstring("EPlotSections Class"),
+ noncreatable
+ ]
+ coclass EPlotSections
+ {
+ [default] interface IEPlotSections;
+ };
+ [
+ uuid(F7226C2D-B5C7-4C72-AA43-6D5013EF7C96),
+ helpstring("SLNKEvent Class"),
+ noncreatable
+ ]
+ coclass SLNKEvent
+ {
+ [default] interface ISLNKEvent;
+ };
+ [
+ uuid(FCEF1E56-36FF-4F66-BEA5-FD08D860524F),
+ helpstring("BoundingBox Class"),
+ noncreatable
+ ]
+ coclass BoundingBox
+ {
+ [default] interface IBoundingBox;
+ };
+ [
+ uuid(96301A8D-1DC9-4900-B89D-C745C4CAEFF4),
+ helpstring("DWGPoint Class"),
+ noncreatable
+ ]
+ coclass DWGPoint
+ {
+ [default] interface IDWGPoint;
+ };
+ [
+ uuid(476C0F28-5860-485D-BEBD-D03F68E1C930),
+ helpstring("SLNKContour Class"),
+ noncreatable
+ ]
+ coclass SLNKContour
+ {
+ [default] interface ISLNKContour;
+ };
+ [
+ uuid(8CEBC89F-658A-49C8-96E4-852FFFA9B10F),
+ helpstring("SLNKSymbol Class"),
+ noncreatable
+ ]
+ coclass SLNKSymbol
+ {
+ [default] interface ISLNKSymbol;
+ };
+ [
+ uuid(168678A9-6FA7-49C3-B839-DFDF07E0A79A),
+ helpstring("Options Class")
+ ]
+ coclass Options
+ {
+ [default] interface IOptions;
+ };
+};
diff --git a/SlnkDWFCom/SLNKDWF.rgs b/SlnkDWFCom/SLNKDWF.rgs
new file mode 100644
index 0000000..f191d93
--- /dev/null
+++ b/SlnkDWFCom/SLNKDWF.rgs
@@ -0,0 +1,11 @@
+HKCR
+{
+ NoRemove AppID
+ {
+ '%APPID%' = s 'SLNKDWF'
+ 'SLNKDWF.DLL'
+ {
+ val AppID = s '%APPID%'
+ }
+ }
+}
diff --git a/SlnkDWFCom/SLNKDWF.vcproj b/SlnkDWFCom/SLNKDWF.vcproj
new file mode 100644
index 0000000..1fabce8
--- /dev/null
+++ b/SlnkDWFCom/SLNKDWF.vcproj
@@ -0,0 +1,533 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnkDWFCom/SLNKDWFVersion.h b/SlnkDWFCom/SLNKDWFVersion.h
new file mode 100644
index 0000000..fb73747
--- /dev/null
+++ b/SlnkDWFCom/SLNKDWFVersion.h
@@ -0,0 +1,18 @@
+// Zorg dat versies alfabetisch altijd op elkaar volgen!
+#define SLNK_MAJOR_VERSION 2
+#define SLNK_MINOR_VERSION 00
+#define SLNK_BUILD_VERSION 0
+
+// Define resource strings
+#define ECHO(a) #a
+#define STRINGIZE_SLNK_BUILD(major, minor, build) ECHO(major) "," ECHO(minor) ",0," ECHO(build)
+#define STRINGIZE_SLNK_FULL(major, minor) ECHO(major) "." ECHO(minor)
+
+// Deze wordt gebruikt in SLNKDWF.RC2 en eindigt in Version Tab van de properties
+// Daar conformeren we aan de standaard(?)
+#define SLNK_BUILDVERSION STRINGIZE_SLNK_BUILD(SLNK_MAJOR_VERSION, SLNK_MINOR_VERSION, SLNK_BUILD_VERSION)
+
+// Deze wordt in splashscherm getoond en in About-scherm
+// Bovendien wordt DonShowSplashVersion hiervan afgeleid
+// Ergo: Voor de eenvoud niet de BUILD_VERSION tonen aan eindgebruikers
+#define SLNK_FULLVERSION STRINGIZE_SLNK_FULL(SLNK_MAJOR_VERSION, SLNK_MINOR_VERSION)
diff --git a/SlnkDWFCom/SLNKEvent.cpp b/SlnkDWFCom/SLNKEvent.cpp
new file mode 100644
index 0000000..737e00a
--- /dev/null
+++ b/SlnkDWFCom/SLNKEvent.cpp
@@ -0,0 +1,95 @@
+// SLNKEvent.cpp : Implementation of CSLNKEvent
+
+#include "stdafx.h"
+#include "SLNKEvent.h"
+
+
+// CSLNKEvent
+
+
+STDMETHODIMP CSLNKEvent::get_DwgX(DOUBLE* pVal)
+{
+ (*pVal) = m_DwgX;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKEvent::put_DwgX(DOUBLE newVal)
+{
+ m_DwgX = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKEvent::get_DwgY(DOUBLE* pVal)
+{
+ (*pVal) = m_DwgY;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKEvent::put_DwgY(DOUBLE newVal)
+{
+ m_DwgY = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKEvent::get_ContourLabel(BSTR* pVal)
+{
+ CComBSTR bstrString(m_ContourLabel);
+ return bstrString.CopyTo(pVal);
+}
+
+STDMETHODIMP CSLNKEvent::put_ContourLabel(BSTR newVal)
+{
+ m_ContourLabel = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKEvent::get_ContourLayer(BSTR* pVal)
+{
+ CComBSTR bstrString(m_ContourLayer);
+ return bstrString.CopyTo(pVal);
+}
+
+STDMETHODIMP CSLNKEvent::put_ContourLayer(BSTR newVal)
+{
+ m_ContourLayer = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKEvent::get_TextLabel(BSTR* pVal)
+{
+ CComBSTR bstrString(m_TextLabel);
+ return bstrString.CopyTo(pVal);
+}
+
+STDMETHODIMP CSLNKEvent::put_TextLabel(BSTR newVal)
+{
+ m_TextLabel = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKEvent::get_TextLayer(BSTR* pVal)
+{
+ CComBSTR bstrString(m_TextLayer);
+ return bstrString.CopyTo(pVal);
+}
+
+STDMETHODIMP CSLNKEvent::put_TextLayer(BSTR newVal)
+{
+ m_TextLayer = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKEvent::get_found(IDWGPoint** pVal)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKEvent::get_dwgExtents(IBoundingBox** pVal)
+{
+ return m_dwgBounding->QueryInterface(IID_IBoundingBox, (void**)pVal);
+}
+
+STDMETHODIMP CSLNKEvent::get_viewExtents(IBoundingBox** pVal)
+{
+ return m_viewBounding->QueryInterface(IID_IBoundingBox, (void**)pVal);
+}
diff --git a/SlnkDWFCom/SLNKEvent.h b/SlnkDWFCom/SLNKEvent.h
new file mode 100644
index 0000000..3e5e7df
--- /dev/null
+++ b/SlnkDWFCom/SLNKEvent.h
@@ -0,0 +1,93 @@
+// SLNKEvent.h : Declaration of the CSLNKEvent
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+#include "BoundingBox.h"
+
+
+// CSLNKEvent
+
+class ATL_NO_VTABLE CSLNKEvent :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IDispatchImpl
+{
+public:
+ CSLNKEvent()
+ {
+ }
+
+//REMOVED DECLARE_REGISTRY_RESOURCEID(IDR_SLNKEVENT)
+
+
+BEGIN_COM_MAP(CSLNKEvent)
+ COM_INTERFACE_ENTRY(ISLNKEvent)
+ COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ //
+ // Maak object m_dwgBounding
+ //
+ CComObject *pBoundingBox;
+ HRESULT hr = CComObject::CreateInstance(&pBoundingBox);
+ if(FAILED(hr)) return hr;
+
+ pBoundingBox->AddRef();
+ hr = pBoundingBox->QueryInterface(IID_IBoundingBox, (void **)&m_dwgBounding);
+ pBoundingBox->Release();
+ if(FAILED(hr)) return hr;
+
+ //
+ // Maak object m_viewBounding
+ //
+ hr = CComObject::CreateInstance(&pBoundingBox);
+ if(FAILED(hr)) return hr;
+
+ pBoundingBox->AddRef();
+ hr = pBoundingBox->QueryInterface(IID_IBoundingBox, (void **)&m_viewBounding);
+ pBoundingBox->Release();
+ if(FAILED(hr)) return hr;
+
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+private:
+ CComQIPtr m_dwgBounding;
+ CComQIPtr m_viewBounding;
+
+ double m_DwgX, m_DwgY;
+ double m_minDwgX, m_maxDwgY;
+ double m_maxDwgX, m_minDwgY;
+ CString m_ContourLabel, m_ContourLayer;
+ CString m_TextLabel, m_TextLayer;
+public:
+
+ STDMETHOD(get_DwgX)(DOUBLE* pVal);
+ STDMETHOD(put_DwgX)(DOUBLE newVal);
+ STDMETHOD(get_DwgY)(DOUBLE* pVal);
+ STDMETHOD(put_DwgY)(DOUBLE newVal);
+ STDMETHOD(get_ContourLabel)(BSTR* pVal);
+ STDMETHOD(put_ContourLabel)(BSTR newVal);
+ STDMETHOD(get_ContourLayer)(BSTR* pVal);
+ STDMETHOD(put_ContourLayer)(BSTR newVal);
+ STDMETHOD(get_TextLabel)(BSTR* pVal);
+ STDMETHOD(put_TextLabel)(BSTR newVal);
+ STDMETHOD(get_TextLayer)(BSTR* pVal);
+ STDMETHOD(put_TextLayer)(BSTR newVal);
+ STDMETHOD(get_found)(IDWGPoint** pVal);
+ STDMETHOD(get_dwgExtents)(IBoundingBox** pVal);
+ STDMETHOD(get_viewExtents)(IBoundingBox** pVal);
+};
+
+//REMOVED OBJECT_ENTRY_AUTO(__uuidof(SLNKEvent), CSLNKEvent)
diff --git a/SlnkDWFCom/SLNKEvent.rgs b/SlnkDWFCom/SLNKEvent.rgs
new file mode 100644
index 0000000..d99bbea
--- /dev/null
+++ b/SlnkDWFCom/SLNKEvent.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ SLNKDWF.SLNKEvent.1 = s 'SLNKEvent Class'
+ {
+ CLSID = s '{F7226C2D-B5C7-4C72-AA43-6D5013EF7C96}'
+ }
+ SLNKDWF.SLNKEvent = s 'SLNKEvent Class'
+ {
+ CLSID = s '{F7226C2D-B5C7-4C72-AA43-6D5013EF7C96}'
+ CurVer = s 'SLNKDWF.SLNKEvent.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {F7226C2D-B5C7-4C72-AA43-6D5013EF7C96} = s 'SLNKEvent Class'
+ {
+ ProgID = s 'SLNKDWF.SLNKEvent.1'
+ VersionIndependentProgID = s 'SLNKDWF.SLNKEvent'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/SLNKSymbol.cpp b/SlnkDWFCom/SLNKSymbol.cpp
new file mode 100644
index 0000000..49ab0e5
--- /dev/null
+++ b/SlnkDWFCom/SLNKSymbol.cpp
@@ -0,0 +1,75 @@
+// SLNKSymbol.cpp : Implementation of CSLNKSymbol
+
+#include "stdafx.h"
+#include "SLNKSymbol.h"
+#include "SLNKContour.h"
+
+// CSLNKSymbol
+
+STDMETHODIMP CSLNKSymbol::InterfaceSupportsErrorInfo(REFIID riid)
+{
+ static const IID* arr[] =
+ {
+ &IID_IWhipFile
+ };
+
+ for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
+ {
+ if (InlineIsEqualGUID(*arr[i],riid))
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+
+void CSLNKSymbol::SetImpl(CSLNKSymbolImpl * pSLNKSymbol)
+{
+ m_SLNKSymbol = pSLNKSymbol;
+}
+
+STDMETHODIMP CSLNKSymbol::get_Scale(DOUBLE* pVal)
+{
+ (*pVal) = m_SLNKSymbol->m_Scale;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKSymbol::put_Scale(DOUBLE newVal)
+{
+ m_SLNKSymbol->m_Scale = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKSymbol::get_Rotation(LONG* pVal)
+{
+ (*pVal) = m_SLNKSymbol->m_Rotation;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKSymbol::put_Rotation(LONG newVal)
+{
+ long rotation = (newVal%360+360)%360; // Normaliseren
+ if (rotation%90 != 0)
+ return myAtlReportError (GetObjectCLSID(), "ERROR Symbol rotation must be 0/90/180/270.");
+
+ m_SLNKSymbol->m_Rotation = newVal;
+ return S_OK;
+}
+
+STDMETHODIMP CSLNKSymbol::get_Contour(IUnknown** pVal)
+{
+ CSLNKContourImpl *contour= &m_SLNKSymbol->m_SLNKContour;
+
+ CComObject *theContour;
+ HRESULT hr = CComObject::CreateInstance(&theContour);
+ if(FAILED(hr)) return hr;
+
+ theContour->AddRef();
+ hr = theContour->QueryInterface(IID_ISLNKContour, (void **)pVal);
+ if(FAILED(hr)) return hr;
+
+ theContour->SetParent(m_parent_iWhipFile); // Zelfde parent maar
+ theContour->Release();
+ theContour->SetImpl(contour); // Heel belangrijk: zet de implementatie waar we een interface op bieden
+
+ return S_OK;
+}
diff --git a/SlnkDWFCom/SLNKSymbol.rgs b/SlnkDWFCom/SLNKSymbol.rgs
new file mode 100644
index 0000000..0f4b5e0
--- /dev/null
+++ b/SlnkDWFCom/SLNKSymbol.rgs
@@ -0,0 +1,26 @@
+HKCR
+{
+ SLNKDWFCom.SLNKSymbol.1 = s 'SLNKSymbol Class'
+ {
+ CLSID = s '{8CEBC89F-658A-49C8-96E4-852FFFA9B10F}'
+ }
+ SLNKDWFCom.SLNKSymbol = s 'SLNKSymbol Class'
+ {
+ CLSID = s '{8CEBC89F-658A-49C8-96E4-852FFFA9B10F}'
+ CurVer = s 'SLNKDWFCom.SLNKSymbol.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {8CEBC89F-658A-49C8-96E4-852FFFA9B10F} = s 'SLNKSymbol Class'
+ {
+ ProgID = s 'SLNKDWFCom.SLNKSymbol.1'
+ VersionIndependentProgID = s 'SLNKDWFCom.SLNKSymbol'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/SLNKSymbolDefImpl.cpp b/SlnkDWFCom/SLNKSymbolDefImpl.cpp
new file mode 100644
index 0000000..6a61566
--- /dev/null
+++ b/SlnkDWFCom/SLNKSymbolDefImpl.cpp
@@ -0,0 +1,427 @@
+#include "StdAfx.h"
+#include "myEPlotSection.h"
+#include "SLNKSymbolDefImpl.h"
+#include "../SLNKDWFImpl/CxImage\CxImage\ximage.h"
+#include "../SLNKDWFImpl/Whip2DCImpl.h"
+#include "SLNKContourImpl.h"
+#include
+
+// Bij EPlotsection (external DWF)
+CSLNKSymbolDefinition::CSLNKSymbolDefinition(CComQIPtr EPlotSection)
+{
+ m_iEPlotSection = EPlotSection;
+
+ CEPlotSectionImpl *epli;
+ m_iEPlotSection->get_EPlotSectionImpl((BYTE **)&epli);
+ m_wtFile.set_eplotsection(epli);
+ m_AsBitmap = NULL;
+ m_BuiltIn = false;
+ calculateBoundary();
+};
+
+// Bij Contour list (builtin symbol)
+CSLNKSymbolDefinition::CSLNKSymbolDefinition(int count, WT_Logical_Point const *points)
+{
+ m_BuiltIn = true;
+ m_wtFile.set_eplotsection(NULL);
+ this->m_dwgScale = 1.0;
+ m_AsBitmap = NULL;
+ m_BoundingContour.set(count, points, false);
+ m_Origin = CSLNKContourImpl::Centroid(m_BoundingContour);
+};
+
+// By bitmap
+CSLNKSymbolDefinition::CSLNKSymbolDefinition(CString const filepath, double const height)
+{
+ m_wtFile.set_eplotsection(NULL);
+ m_AsBitmap = NULL;
+ m_BuiltIn = false;
+ CxImage img;
+ if (!img.Load(filepath))
+ { // Rood kruisje?
+ img.Create(32, 32, 24);
+ img.Clear(255); // Wit
+ img.DrawLine(0,31,0,31,RGB(255,0,0));
+ img.DrawLine(0,31,31,0,RGB(255,0,0));
+ };
+ BYTE *m_Buffer=NULL;
+ long m_size;
+ img.Encode(m_Buffer, m_size, CXIMAGE_FORMAT_PNG);
+
+ this->m_dwgScale = (double)img.GetHeight()/ height;
+
+ //myDoTRACE("\nCreates symbol bitmap (%d,%d)->PNG %d byte (W2D was %d)", pixeldx,pixeldy,m_size, epli->size());
+
+ m_AsBitmap = new
+ WT_PNG_Group4_Image(
+ (int)img.GetHeight(), /*rows*/
+ (int)img.GetWidth(), /*cols*/
+ WT_PNG_Group4_Image::PNG,
+ 3,
+ NULL,
+ m_size,
+ (WT_Byte*)m_Buffer,
+ WT_Logical_Point(0,0),
+ WT_Logical_Point(img.GetWidth(),img.GetHeight()),
+ WD_False); // Geen copy, we verwijderen zelf expliciet
+
+ WT_Logical_Point pts4[4] = { WT_Logical_Point(0, 0),
+ WT_Logical_Point(img.GetWidth(), 0),
+ WT_Logical_Point(img.GetWidth(), img.GetHeight()),
+ WT_Logical_Point(0, img.GetHeight())};
+ m_BoundingContour.set(4, pts4, true);
+ m_Origin = CSLNKContourImpl::Centroid(m_BoundingContour);
+};
+
+CSLNKSymbolDefinition::~CSLNKSymbolDefinition(void)
+{
+ if (m_AsBitmap)
+ {
+ CxImage xx;xx.FreeMemory((void *)m_AsBitmap->data()); // We hebben een copy gedaan dus dit mag/moet
+ delete m_AsBitmap;
+ }
+}
+
+// Bepaal een bounding contour van ons symbool. Die is eventueel later leuk te gebruiken voor een HitTest
+// v0: bounding box
+// v1: bounding octagon
+// Algoritm: search google for Bounding Octagon
+// http://geometryalgorithms.com/Archive/algorithm_0107/algorithm_0107.htm
+// (v2: bounding convex hull waarschijnlijk overkill)
+#include
+WT_Result CSLNKSymbolDefinition::calculateBoundary ()
+{
+ WT_Result result;
+
+ m_wtFile.set_file_mode(WT_File::File_Read);
+ result = m_wtFile.open();
+ if (result != WT_Result::Success)
+ return result;
+
+ // Door de enorm grote dwf-coordinaten lopen we een integer overflow risico tijdens
+ // onze bepaling van Pmin en Pmax (die min en max van x+y bepalen) en in theorie
+ // ook van Qmin en Qmax (die over het verschil x-y gaan) hoewel dat in de praktijk rond 0 zal liggen
+ // Daarom rekenen we systematisch met de helft. Dat moet risico's voorkomen en de afrondfout nemen
+ // we voor lief
+ // Merk op dat de resulterende Octagon kleiner is dan de de bounding box, die zeker binnen de coordinaat
+ // ruimte valt dus voor het eindresultaat is er geen risico. Alleen oppassen voor tussenresultaten dus
+ // Ging concreet mis met 41610ev_symbols.dwf
+ WT_Integer32 Xmin, Xmax, Ymin, Ymax;
+ WT_Integer32 Pmin2, Pmax2, Qmin2, Qmax2;
+ // Signal invalid
+ Xmin = Ymin = Pmin2 = Qmin2 = INT_MAX;
+ Xmax = Ymax = Pmax2 = Qmax2 = INT_MIN;
+
+ BOOL ViewportDone = FALSE; // We doen alleen de eerste viewport.
+ // Gaf problemen bij symbolen die vanuit paperspace waren geexporteerd
+ // Do the actual reading.
+ while ((result = m_wtFile.process_next_object()) == WT_Result::Success)
+ {
+ //myTRACE("Attribute '%s'\n", wtFile->file_stats()->descriptions());
+ switch(m_wtFile.current_object()->object_type())
+ {
+ case WT_Object::Attribute:
+ {
+ const WT_Attribute *obj = (WT_Attribute *)m_wtFile.current_object();
+ if (obj->object_id() == WT_Object::Viewport_ID)
+ {
+ if (ViewportDone)
+ {
+ myTRACE("\nSkipping second viewport in symbol");
+ break;
+ }
+ ViewportDone = TRUE;
+ WT_Viewport *viewport = (WT_Viewport *)m_wtFile.current_object();
+ WT_Units symbolunits = viewport->viewport_units();
+ m_dwgScale = symbolunits.application_to_dwf_transform()(0,0); // Symbol's dScale
+ break;
+ }
+ break;
+ }
+ case WT_Object::Drawable:
+ {
+ WT_Drawable *obj = (WT_Drawable *)m_wtFile.current_object();
+ if (obj->object_id() != WT_Object::Origin_ID)// Belachelijk dat die Drawable is?
+ {
+ WT_Logical_Box bx = obj->bounds(&m_wtFile);
+ Xmin = min(Xmin, bx.minpt().m_x);
+ Ymin = min(Ymin, bx.minpt().m_y);
+ Xmax = max(Xmax, bx.maxpt().m_x);
+ Ymax = max(Ymax, bx.maxpt().m_y);
+
+ // Voor echte (deel)cirkels gaan we de diagonaal bounding box scherper berekenen
+ if (obj->object_id() == WT_Object::Outline_Ellipse_ID || obj->object_id() == WT_Object::Filled_Ellipse_ID)
+ {
+ WT_Ellipse *elp = (WT_Ellipse *)obj;
+ if (elp->minor() == elp->major()) // Anders te ingewikkeld
+ { // Bepaal het ingeschreven vierkant van de cirkel
+ WT_Integer32 dr = myRound(elp->minor() / sqrt(2.0) + 0.5); // Altijd omhoog afronden
+ WT_Logical_Box bx2;
+ bx2.minpt() = WT_Logical_Point(elp->position().m_x - dr, elp->position().m_y - dr);
+ bx2.maxpt() = WT_Logical_Point(elp->position().m_x + dr, elp->position().m_y + dr);
+ // Houdt er wel rekening mee dat bij partiele cirkels het origineel scherper kan
+ // zijn omdat wij er geen rekening houden dat de cirkel misschien partieel is
+ Pmin2 = min(Pmin2, max(bx.minpt().m_x/2 + bx.minpt().m_y/2,bx2.minpt().m_x/2 + bx2.minpt().m_y/2)); // Linksonder
+ Qmax2 = max(Qmax2, min(bx.maxpt().m_x/2 - bx.minpt().m_y/2,bx2.maxpt().m_x/2 - bx2.minpt().m_y/2)); // Rechtsonder
+ Pmax2 = max(Pmax2, min(bx.maxpt().m_x/2 + bx.maxpt().m_y/2,bx2.maxpt().m_x/2 + bx2.maxpt().m_y/2)); // Rechtsboven
+ Qmin2 = min(Qmin2, max(bx.minpt().m_x/2 - bx.maxpt().m_y/2,bx2.minpt().m_x/2 - bx2.maxpt().m_y/2)); // Linksboven
+ break;
+ }
+ // else gewoon 'doorvallen' naar standaard Pmin2 etc.
+ }
+
+ // Voor WT_Pointset gebaseerde objecten kunnen we het ook wel beter
+ if (obj->object_id() == WT_Object::Polygon_ID ||
+ obj->object_id() == WT_Object::Polyline_ID ||
+ obj->object_id() == WT_Object::Polytriangle_ID)
+ {
+ WT_Point_Set *pts;
+ // Rechtstreekse cast naar (WT_Point_Set *) gaf memory violations?
+ switch (obj->object_id())
+ {
+ case WT_Object::Polygon_ID : pts = (WT_Polygon *)m_wtFile.current_object(); break;
+ case WT_Object::Polyline_ID : pts = (WT_Polyline *)m_wtFile.current_object(); break;
+ case WT_Object::Polytriangle_ID: pts = (WT_Polytriangle *)m_wtFile.current_object(); break;
+ }
+
+ for (int i=0;icount(); i++)
+ {
+ WT_Logical_Point &pt = pts->points()[i];
+ Pmin2 = min(Pmin2, pt.m_x/2 + pt.m_y/2); // Linksonder
+ Qmax2 = max(Qmax2, pt.m_x/2 - pt.m_y/2); // Rechtsonder
+ Pmax2 = max(Pmax2, pt.m_x/2 + pt.m_y/2); // Rechtsboven
+ Qmin2 = min(Qmin2, pt.m_x/2 - pt.m_y/2); // Linksboven
+ }
+ break; // we zijn wel klaar
+ }
+
+ Pmin2 = min(Pmin2, bx.minpt().m_x/2 + bx.minpt().m_y/2); // Linksonder
+ Qmax2 = max(Qmax2, bx.maxpt().m_x/2 - bx.minpt().m_y/2); // Rechtsonder
+ Pmax2 = max(Pmax2, bx.maxpt().m_x/2 + bx.maxpt().m_y/2); // Rechtsboven
+ Qmin2 = min(Qmin2, bx.minpt().m_x/2 - bx.maxpt().m_y/2); // Linksboven
+ }
+ }
+ break;
+ default:
+ //myTRACE("Skipping '%s'\n", wtFile->file_stats()->descriptions());
+ break;
+ }
+ }
+// if (result == WT_Result::End_Of_DWF_Opcode_Found)
+// dwfresult = DwfResult::Success;
+
+ m_wtFile.close();
+
+ // Rechthoek
+// WT_Logical_Point pts1[4] = { WT_Logical_Point(Xmin, Ymin),
+// WT_Logical_Point(Xmax, Ymin),
+// WT_Logical_Point(Xmax, Ymax),
+// WT_Logical_Point(Xmin, Ymax)};
+ m_BoundingBox = WT_Logical_Box(Xmin, Ymin, Xmax, Ymax);
+
+ // Diamant heeft overflow risico
+// WT_Logical_Point pts2[4] = { WT_Logical_Point(Pmin2+Qmin2, Pmin2-Qmin2),
+// WT_Logical_Point(Pmin2+Qmax2, Pmin2-Qmax2),
+// WT_Logical_Point(Pmax2+Qmax2, Pmax2-Qmax2),
+// WT_Logical_Point(Pmax2+Qmin2, Pmax2-Qmin2)};
+
+ // Octagon
+ // Expressievolgorde is telkens belangrijk om overflow te voorkomen
+ WT_Logical_Point pts3[8] = { WT_Logical_Point(Pmin2-Ymin+Pmin2, Ymin),
+ WT_Logical_Point(Qmax2+Ymin+Qmax2, Ymin),
+ WT_Logical_Point(Xmax, Xmax-Qmax2-Qmax2),
+ WT_Logical_Point(Xmax, Pmax2-Xmax+Pmax2),
+ WT_Logical_Point(Pmax2-Ymax+Pmax2, Ymax),
+ WT_Logical_Point(Qmin2+Ymax+Qmin2, Ymax),
+ WT_Logical_Point(Xmin, Xmin-Qmin2-Qmin2),
+ WT_Logical_Point(Xmin, Pmin2-Xmin+Pmin2)};
+
+ m_BoundingContour.set(sizeof(pts3)/sizeof(pts3[0]), pts3, true);
+ m_Origin = CSLNKContourImpl::Centroid(m_BoundingContour);
+
+ return result;
+}
+
+#ifdef NO_BITMAPPEREN
+WT_Drawable *CSLNKSymbolDefinition::asBitmap(int pixeldx, int pixeldy, long paperColor)
+{
+ if (m_AsBitmap)
+ {
+ // TODO: Wat als pixeldy != m_AsBitmap->rows()
+ // Dat dwfdx anders is is minder boeiend, dat verschaalt wel
+ WT_PNG_Group4_Image *newBitmap = new
+ WT_PNG_Group4_Image(
+ m_AsBitmap->rows(), /*rows*/
+ m_AsBitmap->columns(), /*cols*/
+ WT_PNG_Group4_Image::PNG,
+ 3,
+ NULL,
+ m_AsBitmap->data_size(),
+ (WT_Byte *)m_AsBitmap->data(),
+ m_BoundingBox.minpt(),
+ m_BoundingBox.maxpt(),
+ WD_False); // Don't copy
+ m_AsBitmap = newBitmap;
+ return m_AsBitmap; // Dan zijn we rap klaar. Dat is onze winst
+ }
+
+ // Blijkbaar de eerste keer hier. Tijd om de bitmap te bakken
+ CWhip2DCImpl iWhip2DC;
+ HDC pDC = ::GetDC(0);
+ HDC myDC = CreateCompatibleDC(pDC);
+ //ReleaseDC(pDC);
+ CEPlotSectionImpl *epli = NULL;
+ m_iEPlotSection->get_EPlotSectionImpl((BYTE **)&epli);
+ iWhip2DC.Load(myDC, epli,
+ "", ".*",
+ myRound(pixeldx), myRound(pixeldy),
+ VARIANT_TRUE /*center*/, VARIANT_TRUE /*m_Maximize*/);
+
+ BITMAPINFO bmInfo;
+ memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ bmInfo.bmiHeader.biWidth=pixeldx;
+ bmInfo.bmiHeader.biHeight=pixeldy;
+ bmInfo.bmiHeader.biPlanes=1;
+ bmInfo.bmiHeader.biCompression=BI_RGB; // Geen compressie
+ bmInfo.bmiHeader.biBitCount=24;
+ //create a new bitmap and select it in the memory dc
+ BYTE *pbase;
+ HBITMAP TmpBmp = CreateDIBSection(pDC, &bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
+ HGDIOBJ TmpObj=SelectObject(myDC,TmpBmp);
+
+ iWhip2DC.put_paperColor(paperColor); // Op zich maken we hem transparant maar onze zwart/wit toggle moet wel kloppen
+ SUCCEEDED(iWhip2DC.Paint(VARIANT_FALSE /*m_forceBW*/));
+ CxImage img;
+ img.CreateFromHBITMAP(TmpBmp);
+
+ img.DecreaseBpp(8, FALSE); // Werkt averechts voor kleine plaatjes (pallette is groot?)
+ // Maar CxImage::Draw2 lijkt alleen te werken met palette achtergrond dus het moet maar
+ RGBQUAD back = {GetBValue(paperColor), // RGBQUAD is BGR!!
+ GetGValue(paperColor),
+ GetRValue(paperColor),0};
+ ///RGBQUAD back = {0,0,0,0};
+ img.SetTransIndex(img.GetNearestIndex(back));
+// img.SetTransColor(back); // Voor als we zonder pallette werken
+
+ BYTE *m_Buffer=NULL;
+ long m_size;
+ img.Encode(m_Buffer, m_size, CXIMAGE_FORMAT_PNG);
+ myDoTRACE("\nCreates symbol bitmap (%d,%d)->PNG %d byte (W2D was %d)", pixeldx,pixeldy,m_size, epli->size());
+
+ DeleteObject(TmpBmp);
+ DeleteDC(myDC);
+ ReleaseDC( NULL, pDC ); //Do not forget!
+
+ m_AsBitmap = new
+ WT_PNG_Group4_Image(
+ pixeldy, /*rows*/
+ pixeldy, /*cols*/
+ WT_PNG_Group4_Image::PNG,
+ 3,
+ NULL,
+ m_size,
+ (WT_Byte*)m_Buffer,
+ m_BoundingBox.minpt(),
+ m_BoundingBox.maxpt(),
+ WD_False); // Geen copy, we verwijderen zelf expliciet
+
+ return m_AsBitmap;
+}
+#endif
+
+WT_Result CSLNKSymbolDefinition::serialize(WT_File & file)
+{
+ if (m_AsBitmap)
+ { // Wel even kopietje trekken omdat anders niet opnieuw getransformeerd wordt
+ WT_PNG_Group4_Image(
+ m_AsBitmap->rows(), /*rows*/
+ m_AsBitmap->columns(), /*cols*/
+ WT_PNG_Group4_Image::PNG,
+ 3,
+ NULL,
+ m_AsBitmap->data_size(),
+ (WT_Byte *)m_AsBitmap->data(),
+ m_AsBitmap->bounds().minpt(),
+ m_AsBitmap->bounds().maxpt(),
+ WD_False).serialize(file);
+ return WT_Result::Success;
+ }
+ if (m_BuiltIn)
+ return WT_Result::Success;
+
+ WT_Result result;
+ // Open onze symbool DWF
+ m_wtFile.set_file_mode(WT_File::File_Read);
+ result = m_wtFile.open();
+ if (result != WT_Result::Success)
+ return result; // Waarschijnlijk builtin symbol?
+
+// Op zich is er minder kans op overflow als we het symbool tijden het inlezen
+// al richting (0,0) zetten. Dan wordt echter niet meer de definitieve transform
+// uitgevoerd omdat m_transformed op WD_True staat.
+// WT_Logical_Point lshift(- m_Origin.m_x,- m_Origin.m_y);
+//
+// m_wtFile.heuristics().set_transform(WT_Transform (lshift, 0, 0, 0));
+// m_wtFile.heuristics().set_apply_transform(true);
+
+ // Do the actual reading.
+ // Een apply_transform is door de aanroeper al op file gezet.
+ // Dankzij set_apply_transform gaat de rest miraculeus vanzelf
+ while ((result = m_wtFile.process_next_object()) == WT_Result::Success)
+ {
+ //myTRACE("Attribute '%s'\n", wtFile->file_stats()->descriptions());
+ switch(m_wtFile.current_object()->object_type())
+ {
+ case WT_Object::Drawable:
+#ifdef _DEBUG
+ if (m_wtFile.current_object()->object_id() == WT_Object::Origin_ID
+ && !file.heuristics().allow_binary_data()
+ )
+ { // Origin is niet toegestaan bij ASCII
+ break;
+ }
+#endif
+ m_wtFile.current_object()->serialize(file);
+ break;
+ case WT_Object::Attribute:
+ {
+ const WT_Attribute *obj = (WT_Attribute *)m_wtFile.current_object();
+ // myTRACE("Attribute '%s'\n", my_plan_file.file_stats()->descriptions());
+ // Hoewel een Attibute gaat hij toch niet via desired_rendition
+ // Omdat we weten dat we net uit uit een DWF komen kunnen we best
+ // wel rechtstreeks serializen
+ // Let wel: desired_rendition is dan niet meer te vertrouwen. Zie @@@
+ if (obj->object_id() == WT_Object::View_ID)
+ {
+ // De view komt VOOR de Viewport dus wordt niet goed vertaald
+ // bovendien doen we er toch niets mee
+ break;
+ }
+ if (obj->object_id() == WT_Object::Layer_ID)
+ {
+ // Zou toch wel erg complex worden. Werkt ook maar matig
+ break;
+ }
+ if (obj->object_id() == WT_Object::Color_ID)
+ { // Misschien een zwart-wit toggle doorvoeren? Of zelfs highlight?
+ // m_iEPlotSection->get_PaperColor()
+ }
+ if (obj->object_id() == WT_Object::Viewport_ID)
+ {
+ break; // Voorkom dat het Viewport object in de DWF komt
+ // Dan krijgen we last omdat we er op clippen
+ // eigenlijk moeten we de originele viewport
+ // terug zetten na afloop
+ }
+ obj->serialize(file);
+ }
+ break;
+ default:
+ //myTRACE("Skipping '%s'\n", wtFile->file_stats()->descriptions());
+ break;
+ }
+ }
+ m_wtFile.close();
+ return WT_Result::Success;
+}
diff --git a/SlnkDWFCom/SLNKSymbolDefImpl.h b/SlnkDWFCom/SLNKSymbolDefImpl.h
new file mode 100644
index 0000000..a6584f0
--- /dev/null
+++ b/SlnkDWFCom/SLNKSymbolDefImpl.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "Whiptk/whip_toolkit.h"
+#include "myWT_File.h"
+
+class CSLNKSymbolDefinition
+{
+public:
+ CSLNKSymbolDefinition(CComQIPtr EPlotSection);
+ CSLNKSymbolDefinition(int count, WT_Logical_Point const *points) ;
+ CSLNKSymbolDefinition(CString const filepath, double const height);
+ ~CSLNKSymbolDefinition(void);
+
+ CComQIPtr m_iEPlotSection; // Om scope levend te houden
+ myWT_File m_wtFile; // Beetje redundant?
+ WT_Logical_Box m_BoundingBox;
+ WT_Polygon m_BoundingContour;
+ WT_Logical_Point m_Origin;
+ double m_dwgScale;
+ WT_Drawable *asBitmap(int pixeldx, int pixeldy, long paperColor);
+ WT_Result serialize(WT_File & file);
+
+private:
+ bool m_BuiltIn;
+ WT_Result calculateBoundary();
+ WT_PNG_Group4_Image *m_AsBitmap;
+};
diff --git a/SlnkDWFCom/SLNKSymbolImpl.cpp b/SlnkDWFCom/SLNKSymbolImpl.cpp
new file mode 100644
index 0000000..8fed14f
--- /dev/null
+++ b/SlnkDWFCom/SLNKSymbolImpl.cpp
@@ -0,0 +1,188 @@
+#include "StdAfx.h"
+#include "myEPlotSection.h"
+#include "SLNKSymbolDefImpl.h"
+#include "SLNKSymbolImpl.h"
+#include "../SLNKDWFImpl/CxImage\CxImage\ximage.h"
+#include "../SLNKDWFImpl/Whip2DCImpl.h"
+#include
+
+CSLNKSymbolImpl::CSLNKSymbolImpl(void)
+{
+}
+
+CSLNKSymbolImpl::~CSLNKSymbolImpl(void)
+{
+}
+
+CSLNKSymbolImpl::CSLNKSymbolImpl(double dwgX, double dwgY, CWhipFileState *State)
+{
+ m_dwgX = dwgX;
+ m_dwgY = dwgY;
+ m_symbolName = "";
+ m_Rotation = 0;
+ m_Scale = 1.0;
+ m_SLNKContour.m_parentWhipFileState = State;
+ m_SLNKContour.m_fromSymbol=true;
+}
+
+WT_Result CSLNKSymbolImpl::serialize (WT_File & file, WT_Units & units,
+ CSLNKSymbolDefinition *symbdef, double hintScale)
+{
+ ATLASSERT(symbdef != NULL);
+
+ WT_Point3D insertion(m_dwgX, m_dwgY);
+ //m_SLNKContour.m_parentWhipFileState->m_contunits
+
+ double dScale = units.application_to_dwf_transform()(0,0); // Drawing's dScale
+
+ WT_Transform wasTransform = file.heuristics().transform();
+ WT_Boolean wasApplyTransform = file.heuristics().apply_transform();
+
+ WT_Logical_Point LPInsertion = units.transform(insertion);
+ // Onze file had mogelijk al een transform staan. Die moeten we wel blijven ondersteunen
+ // (terugzetten komt wel)
+ if (wasApplyTransform)
+ {
+ LPInsertion *= wasTransform;
+ }
+ // WT_Transform ondersteunt wel rotaties 0,90,180 en 270. Dat gaat echter altijd om DWF 0,0
+ // terwijl wij toch echt om ons insertionpoint willen.
+ // Het (b)lijkt oplosbaar door ons punt te tegenroteren
+ WT_Transform tr0;
+ tr0.set_rotation((360-m_Rotation)%360);
+ LPInsertion *= tr0;
+
+ WT_Result result;
+
+#ifdef _xDEBUG
+ { // Cirkel onder het symbool tekenen
+ WT_Logical_Point center = units.transform(insertion);
+ // Binnenkant cirkel
+ file.desired_rendition().color() = WT_Color(128, 128, 128, 0); // doorzichtig werkt (nog) niet voor ellipsen
+ WT_Filled_Ellipse(center, 1500, 1500).serialize(file);
+ // Buitenkant cirkel
+ file.desired_rendition().color() = WT_Color(0, 255, 0, 0); // doorzichtig werkt (nog) niet voor ellipsen
+ file.desired_rendition().line_weight() = WT_Line_Weight(100);
+ WT_Outline_Ellipse(center, 1500, 1500).serialize(file);
+ file.desired_rendition().line_weight() = WT_Line_Weight(0);
+ }
+#endif
+#ifdef _DEBUG
+ { // klein cirkeltje op insertion
+ WT_Logical_Point center = units.transform(insertion);
+ // Binnenkant cirkel
+ file.desired_rendition().color() = WT_Color(0, 0, 128, 0); // doorzichtig werkt (nog) niet voor ellipsen
+ WT_Filled_Ellipse(center, 50, 50).serialize(file);
+ // Buitenkant cirkel
+ file.desired_rendition().color() = WT_Color(0, 128, 0, 0); // doorzichtig werkt (nog) niet voor ellipsen
+ file.desired_rendition().line_weight() = WT_Line_Weight(10);
+ WT_Outline_Ellipse(center, 50, 50).serialize(file);
+ file.desired_rendition().line_weight() = WT_Line_Weight(0);
+ }
+#endif
+ // Vertrouw de huidige rendition niet! Het eerste lijntje van een symbool kan default wit verwachten (CO206.DWF)
+ // Tijdens het serializen van het symbool hebben we niets met (desired)_rendition te maken
+ WT_Color().serialize(file); // Op de default zetten. TODO: Moet eigenlijk voor alle attributen
+
+ double dx, dy;
+
+ dx = dy = m_Scale * dScale / symbdef->m_dwgScale;
+ // PAS OP: (SDU tekening) je kunt hier in overflow problemen komen
+ // als dx*symbdef->m_Origin.m_x>MAXINT ofwel eigenlijk al als dx>1.0
+ // ofwel als d(rawing)Scale > symbdef->m_dwgScale (en dan heb ik het nog
+ // niet over verschaalde symbolen).
+ if (dx*symbdef->m_Origin.m_x > INT_MAX || dy*symbdef->m_Origin.m_y > INT_MAX)
+ {
+ throw myCString("\nSLNKDWF symbol coordinate overflow. Possible solutions:"
+ "\nDecrease drawing dwf resolution (%.6f)"
+ "\nIncrease symbool dwf resolution (%.6f)"
+ "\nDecrease symbol scale (%.6f)",dScale, symbdef->m_dwgScale, m_Scale
+ );
+ }
+ //myDoTRACE("\nSymbool m_Scale = %.6f, dScale = %.6f, symbdef->m_dwgScale = %.6f==>dx=%.6g", m_Scale, dScale, symbdef->m_dwgScale, dx);
+ // WT_Logical_Point lshift(LPInsertion);
+
+ WT_Logical_Point lshift(LPInsertion.m_x - myRound(dx*symbdef->m_Origin.m_x),
+ LPInsertion.m_y - myRound(dy*symbdef->m_Origin.m_y));
+
+ file.heuristics().set_transform(WT_Transform (lshift, dx, dy, m_Rotation));
+ file.heuristics().set_apply_transform(true);
+
+#ifdef NO_BITMAPPEREN
+ // Vooralsnog uitgeschakeld: we hebben de (hoognodige) achtergrondkleur niet
+ Merk op dat builtin symbols (star) geen nog geen boundingbox ingevuld hebben
+ int pixeldx = 1000;
+ int pixeldy = 1000;
+ if (hintScale>0)
+ {
+ WT_Logical_Box bx = symbdef->m_BoundingBox;
+ pixeldx = myRound((bx.maxpt().m_x - bx.minpt().m_x)*m_Scale/symbdef->m_dwgScale/hintScale);
+ pixeldy = myRound((bx.maxpt().m_y - bx.minpt().m_y)*m_Scale/symbdef->m_dwgScale/hintScale);
+ //myDoTRACE("\nbx=(%d,%d)-(%d,%d)",bx.minpt().m_x,bx.minpt().m_y,bx.maxpt().m_x,bx.maxpt().m_y);
+ //myDoTRACE(" makes (%d,%d) pixels",pixeldx,pixeldy);
+ }
+ if ( 0 && pixeldx < 100 && pixeldy < 100 ) // Heel weinig pixels
+ { // Bitmap versie van het symbool gebruiken
+ //double rescale = 1.0; //m_Scale/symbdef->m_dwgScale*dScale;
+ if (pixeldx > 0 && pixeldy > 0)
+ {
+ symbdef->asBitmap(pixeldx, pixeldy, 0xffffff)->serialize(file);
+ }
+ }
+ else
+#endif
+ { //Gewone vector versie
+ symbdef->serialize(file);
+ }
+
+#ifdef _DEBUG
+ WT_Comments cmt;
+ CString s; s.Format("About to insert symbol contour %s", m_symbolName);
+ cmt.set(s);
+ cmt.serialize(file);
+#endif
+
+ //Cirkeltje op symbool zwaartepunt
+ //file.desired_rendition().color() = WT_Color(255, 0, 0, 0);
+ //WT_Filled_Ellipse(symbdef->m_Center, 50, 50).serialize(file);
+
+#ifdef _DEBUG
+ m_SLNKContour.m_outlineAlpha = 255; // Zichtbaar maken
+#else
+ m_SLNKContour.m_outlineAlpha = 0; // Onzichtbaar maken
+#endif
+ // En vervolgens nog een mooi bounding contourtje er om heen.
+ // Die is essentieel voor het aanwijzen. Doordat hierboven de alpha op 0 is gezet wordt hij wel transparant
+ WT_Color().serialize(file); // Op de default zetten.
+ file.desired_rendition().color() = file.rendition().color() = WT_Color();
+ m_SLNKContour.serialize(file, true);
+
+ // Nu contour aanpassen. Is handig voor later teksten bijplaatsen
+ // Echter: die willen we exclusief 'wasTranform' hebben. Daarvoor tegencorrigeren we
+ //
+ LPInsertion = units.transform(insertion);
+ WT_Transform tr1;
+ tr1.set_rotation((360-m_Rotation)%360);
+ LPInsertion *= tr1;
+ lshift = WT_Logical_Point(LPInsertion.m_x - myRound(dx*symbdef->m_Origin.m_x),
+ LPInsertion.m_y - myRound(dy*symbdef->m_Origin.m_y));
+ WT_Transform tm(lshift, dx, dy, m_Rotation);
+ m_SLNKContour.transform(tm); // Pas op: de bounds zijn nu misschien nog verkeerd
+#if 0
+ // Tegencorrectie werkte niet goed met rotatie. Daarom maar zoals hierboven
+ WT_Transform tm(file.heuristics().transform());
+ WT_Logical_Point wasT(wasTransform.m_translate);
+ WT_Transform tr1;
+ tr1.set_rotation((360-m_Rotation)%360);
+ wasT *= tr1;
+ tm.m_translate.m_x -= wasT.m_x;
+ tm.m_translate.m_y -= wasT.m_y;
+ m_SLNKContour.transform(tm); // Pas op: de bounds zijn nu misschien nog verkeerd
+#endif
+
+ // En transform weer terug
+ file.heuristics().set_transform(wasTransform);
+ file.heuristics().set_apply_transform(wasApplyTransform);
+ // ASSERT: Deze werkt nu ook m_SLNKContour.serialize(file, true, true);
+ return result;
+};
diff --git a/SlnkDWFCom/SLNKSymbolImpl.h b/SlnkDWFCom/SLNKSymbolImpl.h
new file mode 100644
index 0000000..60cd114
--- /dev/null
+++ b/SlnkDWFCom/SLNKSymbolImpl.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "Whiptk/whip_toolkit.h"
+#include "SLNKContourImpl.h"
+
+class CSLNKSymbolImpl
+{
+public:
+ CSLNKSymbolImpl(void);
+
+ CSLNKSymbolImpl(double dwgX, double dwgY, CWhipFileState *State);
+
+ WT_Result serialize (WT_File & file, WT_Units & units,
+ CSLNKSymbolDefinition *symbdef,
+ double hintScale);
+ WT_Result calculateBoundary (myWT_File *wtFile);
+
+ ~CSLNKSymbolImpl(void);
+public:
+ double m_dwgX, m_dwgY;
+ //CString m_Label;
+ //CString m_Key;
+ CString m_symbolName;
+ int m_Rotation;
+ double m_Scale;
+ CSLNKContourImpl m_SLNKContour;
+};
diff --git a/SlnkDWFCom/SLNKdwf.aps b/SlnkDWFCom/SLNKdwf.aps
new file mode 100644
index 0000000..792bea9
Binary files /dev/null and b/SlnkDWFCom/SLNKdwf.aps differ
diff --git a/SlnkDWFCom/SLNKdwf.rc b/SlnkDWFCom/SLNKdwf.rc
new file mode 100644
index 0000000..e52ad05
--- /dev/null
+++ b/SlnkDWFCom/SLNKdwf.rc
@@ -0,0 +1,158 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "winres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""winres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "1 TYPELIB ""SLNKDWF.tlb""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#include "SLNKDWFVersion.h"
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION SLNK_MAJOR_VERSION, SLNK_MINOR_VERSION, 0, SLNK_BUILD_VERSION
+ PRODUCTVERSION SLNK_MAJOR_VERSION, SLNK_MINOR_VERSION, 0, SLNK_BUILD_VERSION
+ FILEFLAGSMASK 0x1fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Dijkoraad IT"
+ VALUE "FileDescription", "Superlink DWF "
+ VALUE "FileVersion", SLNK_BUILDVERSION "\0"
+ VALUE "InternalName", "SLNKDWF.dll"
+ VALUE "LegalCopyright", "(c) Dijkoraad IT 2005-2007. All rights reserved."
+ VALUE "OriginalFilename", "SLNKDWF.dll"
+ VALUE "ProductName", "Superlink"
+ VALUE "ProductVersion", SLNK_BUILDVERSION "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_SLNKDWF REGISTRY "SLNKDWF.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_PROJNAME "SLNKDWF"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Dutch (Netherlands) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NLD)
+#ifdef _WIN32
+LANGUAGE LANG_DUTCH, SUBLANG_DUTCH
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// REGISTRY
+//
+
+IDR_DWFFILE REGISTRY "DWFFile.rgs"
+IDR_WHIPFILE REGISTRY "WhipFile.rgs"
+IDR_WHIP2PNG REGISTRY "Whip2PNG.rgs"
+IDR_ABOUT REGISTRY "About.rgs"
+IDR_EPLOTSECTION REGISTRY "EPlotSection.rgs"
+IDR_EPLOTSECTIONS REGISTRY "EPlotSections.rgs"
+IDR_SLNKEVENT REGISTRY "SLNKEvent.rgs"
+IDR_BOUNDINGBOX REGISTRY "BoundingBox.rgs"
+IDR_DWGPOINT REGISTRY "DWGPoint.rgs"
+IDR_SLNKCONTOUR REGISTRY "SLNKContour.rgs"
+IDR_SLNKSYMBOL REGISTRY "SLNKSymbol.rgs"
+IDR_OPTIONS REGISTRY "Options.rgs"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+#endif // Dutch (Netherlands) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+1 TYPELIB "SLNKDWF.tlb"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/SlnkDWFCom/Whip2PNG.cpp b/SlnkDWFCom/Whip2PNG.cpp
new file mode 100644
index 0000000..dc48ca9
--- /dev/null
+++ b/SlnkDWFCom/Whip2PNG.cpp
@@ -0,0 +1,608 @@
+// Whip2PNG.cpp : Implementation of CWhip2PNG
+
+#include "stdafx.h"
+#include "CxImage\CxImage\ximage.h"
+
+#include "Whip2DCImpl.h"
+
+#include "Whip2PNG.h"
+
+#include "metafile.h"
+
+CWhip2PNG::CWhip2PNG()
+{
+ m_sizeX = 800;
+ m_sizeY = 600;
+ m_offsetX = 0;
+ m_offsetY = 0;
+ m_dScale = 1.0;
+ m_lRotation = 0;
+ m_RegExp = ".*";
+ m_forcePaper = FALSE;
+ m_forceBW = FALSE;
+ m_forceGray = FALSE;
+ m_Maximize = FALSE;
+ m_dwgScale = 0.0;
+}
+
+STDMETHODIMP CWhip2PNG::Load(BSTR WhipPath)
+{
+ myDoTRACE("\nCWhip2PNG::Load('%ls')", WhipPath);
+
+ m_WhipPath = WhipPath;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::LoadStream(VARIANT EPlotStream)
+{
+ myDoTRACE("\nCWhip2PNG::LoadStream()");
+
+ if (EPlotStream.vt!=VT_ERROR)
+ {
+ VARIANT *var2 = &EPlotStream;
+ if (var2->vt==(VT_VARIANT|VT_BYREF)) // ByRef
+ var2 = (VARIANT *)var2->pvarVal;
+
+ if (var2->vt==VT_DISPATCH)
+ {
+ m_iEPlotSection = var2->pdispVal;
+ if (!m_iEPlotSection)
+ return E_INVALIDARG;
+ }
+ else
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
+}
+
+// Werkt nog niet echt goed?
+STDMETHODIMP CWhip2PNG::SaveAsWMF(BSTR WMFPath)
+{
+ CmyTimer timer("CWhip2PNG::SaveAsWMF");
+
+#if 0
+ HDC myDC = CreateEnhMetaFile(NULL,CString(WMFPath),NULL,NULL); // In memory
+ InitDC(myDC);
+
+ if (m_forcePaper)
+ HRESULT res = m_iWhip2DC.set_paperColor(m_paperColor);
+ res = m-iWhip2DC->Paint(m_forceBW);
+ HENHMETAFILE hMF = CloseEnhMetaFile(myDC);
+ DeleteEnhMetaFile(hMF);
+ DeleteDC(myDC);
+
+#endif
+
+#if 1
+ HDC myDC = CreateMetaFile(NULL); // In memory
+ InitDC(myDC);
+
+ HRESULT res;
+ if (m_forcePaper)
+ res = m_iWhip2DC.put_paperColor(m_paperColor);
+ res = m_iWhip2DC.Paint(m_forceBW);
+
+ HMETAFILE hMF = CloseMetaFile(myDC);
+ CMetafile::WriteMetaFileAsPlaceable(hMF, CSize(m_sizeX, m_sizeY),m_sizeX/4,CString(WMFPath));
+ DeleteMetaFile(hMF);
+ DeleteDC(myDC);
+
+#endif
+
+ putDWGInfo(); // Generieke info naar het event
+
+ return S_OK;
+}
+
+bool CWhip2PNG::CreateCxImage(CxImage *img)
+{
+ CmyTimer timer("CWhip2PNG::CreateCXImage");
+
+ bool res = true;
+
+ //----
+ HDC pDC = ::GetDC(0);
+ HDC myDC = CreateCompatibleDC(pDC);
+ //ReleaseDC(pDC);
+ InitDC(myDC); // Stelt ook definitieve m_SizeX en m_SizeY vast
+
+#if 1
+
+ BITMAPINFO bmInfo;
+ memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ bmInfo.bmiHeader.biWidth=m_sizeX;
+ bmInfo.bmiHeader.biHeight=m_sizeY;
+ bmInfo.bmiHeader.biPlanes=1;
+ bmInfo.bmiHeader.biCompression=BI_RGB; // Geen compressie
+ bmInfo.bmiHeader.biBitCount=24;
+
+ //create a new bitmap and select it in the memory dc
+ BYTE *pbase;
+ HBITMAP TmpBmp = CreateDIBSection(pDC, &bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
+ //----
+#else
+ // Deze werkt ook wel maar is 10% langzamer? Je zou sneller verwachten?
+ // Bovendien ben je nu afhankelijk van de display instellingen?
+ // En het converteren CreateFromHBITMAP is veel langzamer
+ HBITMAP TmpBmp = CreateCompatibleBitmap ( pDC, m_sizeX, m_sizeY );
+ //BITMAP bm;
+ //GetObject(TmpBmp, sizeof(BITMAP), (LPSTR) &bm);
+ //als bm.bmBits nu NULL is hebben we wel een echte DFB;
+#endif
+ if (!TmpBmp)
+ {
+ myDoTRACE("\nTmpBmp==NULL when creating (%d, %d)??", m_sizeX, m_sizeY);
+ return false;
+ }
+
+ HGDIOBJ TmpObj=SelectObject(myDC,TmpBmp);
+
+ if (m_forcePaper)
+ m_iWhip2DC.put_paperColor(m_paperColor);
+
+ res = res && SUCCEEDED(m_iWhip2DC.Paint(m_forceBW));
+ if (!res)myDoTRACE("Paint faalt??");
+
+ if (!img->CreateFromHBITMAP(TmpBmp))
+ {
+ myDoTRACE("CreateFromHBITMAP faalt??");
+ return false;
+ }
+ if (m_lRotation%360 == 90 || m_lRotation%360 == -270)
+ img->RotateLeft();
+
+ if (m_lRotation%360 == -90 || m_lRotation%360 == 270)
+ img->RotateRight();
+
+ if (m_lRotation == -180 || m_lRotation == 180) // Voor te draggen symbolen
+ img->Rotate180();
+
+ putDWGInfo(); // Generieke info naar het event
+
+ DeleteObject(TmpBmp);
+ DeleteDC(myDC);
+ ReleaseDC( NULL, pDC ); //Do not forget!
+
+ return res;
+}
+
+// Alleen gebruikt in testscripts
+STDMETHODIMP CWhip2PNG::SaveAsPNG(BSTR PNGPath)
+{
+ myDoTRACE("\nCWhip2PNG::SaveAsPNG('%ls')", PNGPath);
+
+ CxImage img;
+ bool res = CreateCxImage(&img);
+ if (!res)
+ {
+ CString err; err.Format("Could not CreateCxImage: %s", img.GetLastError());
+ return myAtlReportError (GetObjectCLSID(), "\nCWhip2PNG::SaveAsPNG('%ls')\n%s", (LPCSTR)m_WhipPath, err);
+ }
+
+ {
+ CmyTimer timer("PNG Save");
+
+ if (!img.Save(CString(PNGPath), CXIMAGE_FORMAT_PNG))
+ return myAtlReportError (GetObjectCLSID(), "\nSaveAsPNG save failed: %s", img.GetLastError());
+ }
+
+ return S_OK;
+}
+
+
+// Handig om GetIMG.asp errormessages te laten opleveren
+// Ondersteunt ook m_Maximize: dan wordt de witruimte geminimaliseerd;
+STDMETHODIMP CWhip2PNG::TextAsPNG(BSTR Message, VARIANT *ImageData)
+{
+ // Indirect via een tempDC omdat anders de CompatibleBitmap Z/W wordt
+ // TODO: Als de server Windows in 256 kleuren draait, wat krijg je dan?
+ HDC tempDC = CreateDC("DISPLAY",NULL,NULL,NULL);
+ HDC myDC = CreateCompatibleDC ( tempDC );
+
+ CString tok(Message);
+ tok.Replace("~", "\n"); // We ondersteunen ook ~ als newline
+ RECT rc = { 0, 0, m_sizeX, 0};
+ DrawText(myDC, tok, tok.GetLength(), &rc, DT_CALCRECT); // Grootte bepalen
+
+ if (m_Maximize)
+ {
+ m_sizeX = rc.right;
+ m_sizeY = rc.bottom;
+ }
+ HBITMAP memBM = CreateCompatibleBitmap ( tempDC, m_sizeX, m_sizeY );
+ DeleteDC(tempDC);
+ SelectObject(myDC, memBM);
+ HBRUSH tempBrush = CreateSolidBrush(RGB(255,255,255));
+ HBRUSH oldbrush = (HBRUSH) SelectObject(myDC,tempBrush);
+ FillRect(myDC,CRect(0,0,m_sizeX, m_sizeY),tempBrush);
+ SelectObject(myDC,oldbrush);
+ DeleteObject(tempBrush);
+
+ // Nu het echte tekenen
+ rc.top = m_sizeY/2 - rc.bottom/2; // Vertikaal centreren
+ rc.bottom = m_sizeY/2 + rc.bottom/2;
+ DrawText(myDC, tok, tok.GetLength(), &rc, DT_TOP);
+
+ CxImage img;
+ if (!img.CreateFromHBITMAP(memBM))
+ return myAtlReportError (GetObjectCLSID(), "\nTextAsPNG CreateFromHBITMAP failed: %s", img.GetLastError());
+
+ DeleteObject(memBM);
+ DeleteDC(tempDC);
+ DeleteDC(myDC);
+
+ return StreamPNG(img, ImageData, TRUE);
+}
+
+// Als we dan toch door de tekening zijn gegaan is het soms
+// wel handig informatie over de tekening te hebben
+// Dat stoppen we grotendeels in m_SLNKEvent
+void CWhip2PNG::putDWGInfo()
+{
+ HRESULT res;
+ res = m_iWhip2DC.get_paperColor((LONG*)&m_paperColor); // Weten we nu ook
+
+ double resX, resY;
+
+ res = m_iWhip2DC.DPtoDWG(0, m_sizeY, &resX, &resY);
+ CComQIPtr bbView;
+ m_SLNKEvent->get_viewExtents(&bbView);
+ CComQIPtr pt;
+ bbView->get_min(&pt);
+ pt->put_DwgX(resX);
+ pt->put_DwgY(resY);
+ pt.Release(); // Voor re-use
+
+ res = m_iWhip2DC.DPtoDWG(m_sizeX, 0, &resX, &resY);
+ bbView->get_max(&pt);
+ pt->put_DwgX(resX);
+ pt->put_DwgY(resY);
+ pt.Release();
+
+ double resMX, resMY;
+ res = m_iWhip2DC.DWGExtents(&resX, &resY, &resMX, &resMY);
+
+ CComQIPtr bbDWG;
+ m_SLNKEvent->get_dwgExtents(&bbDWG);
+ bbDWG->get_min(&pt);
+ pt->put_DwgX(resX);
+ pt->put_DwgY(resY);
+ pt.Release();
+
+ bbDWG->get_max(&pt);
+ pt->put_DwgX(resMX);
+ pt->put_DwgY(resMY);
+ pt.Release();
+}
+
+// Zoek een punt dat de gebruiker in de tekening geklikt heeft.
+// Er wordt alleen een simpele tekst opgeleverd (hetzij aangeklikte truetype tekst
+// of een Contour label). Meer details zijn via get_SLNKEvent te verkrijgen
+STDMETHODIMP CWhip2PNG::Find(LONG findX, LONG findY, BSTR* foundLabel)
+{
+ CmyTimer timer("CWhip2PNG::Find");
+
+ HDC pDC = ::GetDC(0);
+ HDC myDC = CreateCompatibleDC(pDC);
+ //ReleaseDC(pDC);
+ // Er hoeft geen bitmap naar myDC omdat we toch niet painten
+ InitDC(myDC);
+
+ CString ContourLabel, ContourLayer, TextLabel, TextLayer;
+ HRESULT res = m_iWhip2DC.Find(findX, findY,
+ FALSE,
+ ContourLabel, ContourLayer, TextLabel, TextLayer);
+
+ if (TextLabel != "")
+ (*foundLabel) = TextLabel.AllocSysString();
+ else if (ContourLabel != "")
+ (*foundLabel) = ContourLabel.AllocSysString();
+
+ double resX, resY;
+ res = m_iWhip2DC.DPtoDWG(findX, findY, &resX, &resY);
+ m_SLNKEvent->put_DwgX(resX);
+ m_SLNKEvent->put_DwgY(resY);
+
+ m_SLNKEvent->put_ContourLabel(CComBSTR(ContourLabel));
+ m_SLNKEvent->put_ContourLayer(CComBSTR(ContourLayer));
+ m_SLNKEvent->put_TextLabel(CComBSTR(TextLabel));
+ m_SLNKEvent->put_TextLayer(CComBSTR(TextLayer));
+
+ putDWGInfo(); // Generieke info naar het event
+
+ DeleteDC(myDC);
+ ReleaseDC( NULL, pDC ); //Do not forget!
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::SetDimensions(LONG sizeX, LONG sizeY, // PNG image size
+ LONG offsetX, LONG offsetY, // Panning
+ DOUBLE dScale, // Zooming, 1.0 default
+ LONG lRotation) // Rotation, 0 default, multiple of 90
+{
+ if (sizeX*dScale <=0 ||
+ sizeY*dScale <=0 ||
+ sizeX*dScale >=LONG_MAX+0.5 ||
+ sizeY*dScale >=LONG_MAX+0.5)
+ return myAtlReportError (GetObjectCLSID(), "\nCWhip2PNG::SetDimensions invalid zoom");
+
+ m_sizeX = sizeX;
+ m_sizeY = sizeY;
+ m_offsetX = offsetX;
+ m_offsetY = offsetY;
+ m_dScale = dScale;
+ m_lRotation = lRotation;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::GetAsMap(BSTR* AsMap)
+{
+ myDoTRACE("\nCWhip2PNG::GetAsMAP()");
+ CmyTimer timer("CWhip2PNG::GetAsMap");
+
+ HDC pDC = ::GetDC(0);
+ HDC myDC = CreateCompatibleDC(pDC);
+
+ // Er hoeft geen bitmap naar myDC omdat we toch niet painten
+ // Let wel: daardoor kunnen we niet optimaliseren met RectVisible?
+ InitDC(myDC);
+ //ReleaseDC(pDC);
+
+ CString result, dummy;
+ HRESULT res = m_iWhip2DC.Find(0, 0,
+ TRUE, /*AsMap*/
+ result, dummy, dummy, dummy);
+
+ // Als we dan toch door de tekening zijn gegaan is dit wel handig om te hebben
+ putDWGInfo(); // Generieke info naar het event
+
+ (*AsMap) = result.AllocSysString();
+
+ DeleteDC(myDC);
+ ReleaseDC( NULL, pDC ); //Do not forget!
+
+ return S_OK;
+}
+
+// Testfunctie om RegExp's te testen
+STDMETHODIMP CWhip2PNG::get_AtlRegExp(BSTR RegExp, BSTR TestExp, BSTR* pVal)
+{
+ CAtlRegExp<> reLayers; // Welke layers moeten aan
+ REParseError status = reLayers.Parse( CString(RegExp), false );
+ if (REPARSE_ERROR_OK != status)
+ {
+ myTRACE("\nSorry, kan reguliere expressie layersOn niet parsen");
+ // Unexpected error.
+ return S_FALSE;
+ }
+
+ CAtlREMatchContext<> mcUrl;
+ //CAtlREMatchContext<> mcUrl2;
+
+ BOOL b1 = reLayers.Match(CString(TestExp), &mcUrl);
+// b &= (mcUrl.m_uNumGroups > 0);
+ CString res;
+ res.Format("Testing: %ls for %ls: %d", RegExp, TestExp, b1);
+ CComBSTR bstrString(res);
+ return bstrString.CopyTo(pVal);
+
+ return S_OK;
+}
+
+// Stream een CImage als PNG (bPNG) of als GIF (!bPNG)
+HRESULT CWhip2PNG::StreamPNG(CxImage &img, VARIANT *ImageData, BOOL bPNG)
+{
+ SAFEARRAY *psaData; BYTE *pData;
+ SAFEARRAYBOUND rgsabound[1];
+
+ long size=0;
+ BYTE* pBuffer=0;
+ {
+ {
+ CmyTimer timer("CWhip2PNG::StreamPNG/de PNG encoden");
+ if (!img.Encode(pBuffer,size, bPNG?CXIMAGE_FORMAT_PNG:CXIMAGE_FORMAT_GIF))
+ return myAtlReportError (GetObjectCLSID(), "\nStreamPNG encode failed: %s", img.GetLastError());
+ }
+
+ // TODO: Echt netjes zou zijn om hier een IStream op te leveren?
+ // create safe array and copy image data
+ rgsabound[0].lLbound = 0; rgsabound[0].cElements = size;
+ psaData = SafeArrayCreate(VT_UI1, 1, rgsabound);
+ SafeArrayAccessData(psaData, (void **)&pData);
+ memcpy(pData,pBuffer,size);
+ SafeArrayUnaccessData(psaData);
+ img.FreeMemory (pBuffer);
+ // put data in variant
+ ImageData->vt = (VT_ARRAY | VT_UI1);
+ ImageData->parray = psaData;
+ }
+ myDoTRACE("\nCWhip2PNG::StreamPNG done, sending %d bytes", size);
+
+ return S_OK;
+
+}
+
+// Draggable symbolen
+STDMETHODIMP CWhip2PNG::GetAsTransGIF(VARIANT *ImageData)
+{
+ return CWhip2PNG::GetAsXXX(ImageData, FALSE);
+}
+
+STDMETHODIMP CWhip2PNG::GetAsPNG(VARIANT *ImageData)
+{
+ return CWhip2PNG::GetAsXXX(ImageData, TRUE);
+}
+
+STDMETHODIMP CWhip2PNG::GetAsXXX(VARIANT *ImageData, BOOL bPNG)
+{
+ try
+ {
+ myDoTRACE("\nCWhip2PNG::GetAsPNG()");
+
+ CxImage img;
+ BOOL res = CreateCxImage(&img);
+ if (!res)
+ {
+ CString err; err.Format("Could not CreateCxImage: %s", img.GetLastError());
+ throw err;
+ }
+
+ if (!bPNG)
+ { // Transparante GIF.
+ RGBQUAD back = {GetBValue(m_paperColor), // RGBQUAD is BGR!!
+ GetGValue(m_paperColor),
+ GetRValue(m_paperColor),0};
+ if (m_forceGray)
+ {
+ img.GrayScale();
+ BYTE gray = RGB2GRAY(GetRValue(m_paperColor),
+ GetGValue(m_paperColor),
+ GetBValue(m_paperColor));
+ back.rgbBlue = back.rgbGreen = back.rgbRed = gray;
+ }
+ else
+ {
+ }
+ // GIF is 8 bit.
+ img.DecreaseBpp(8, FALSE);
+ img.SetTransIndex(img.GetNearestIndex(back));
+ // GIF kent geen Alpha, IE6 geen PNG transparantie
+ //img.AlphaCreate();
+ //img.AlphaSet(192);
+ }
+ return StreamPNG(img, ImageData, bPNG);
+ }
+ catch (DWFException& ex)
+ {
+ CString err;
+ err.Format("%ls\n%ls\n%s\n%ls(%d)",ex.type(),ex.message(),ex.function(),ex.file(),ex.line());
+ return myAtlReportError (GetObjectCLSID(), "\nCWhip2PNG::GetAsPNG('%s')\n%s", m_WhipPath, err);
+ }
+ catch (CString& err)
+ {
+ return myAtlReportError (GetObjectCLSID(), "\nCWhip2PNG::GetAsPNG('%s')\n%s", m_WhipPath, err);
+ }
+}
+
+STDMETHODIMP CWhip2PNG::SetLayers(BSTR RegExp)
+{
+ m_RegExp = RegExp;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::get_SLNKEvent(ISLNKEvent** pVal)
+{
+ return m_SLNKEvent->QueryInterface(IID_ISLNKEvent, (void**)pVal);
+}
+
+void CWhip2PNG::InitDC(HDC &myDC)
+{
+ SetViewportOrgEx(myDC, m_offsetX, m_offsetY, NULL);
+ CEPlotSectionImpl *epli = NULL;
+ if (m_iEPlotSection) // Via stream?
+ m_iEPlotSection->get_EPlotSectionImpl((BYTE **)&epli);
+ m_iWhip2DC.Load(myDC, epli,
+ m_WhipPath, m_RegExp,
+ myRound(m_sizeX*m_dScale), myRound(m_sizeY*m_dScale),
+ VARIANT_TRUE /*center*/, m_Maximize, m_dwgScale);
+
+ // Als m_dwgScale was gespecificeerd moeten we wel een goede bitmapgrootte kiezen
+ if (m_dwgScale > 0.0)
+ {
+ CSize newsize = m_iWhip2DC.get_Size();
+ m_sizeX = newsize.cx; // Veronderstel m_dScale = 1.0
+ m_sizeY = newsize.cy;
+ }
+}
+STDMETHODIMP CWhip2PNG::get_paperColor(LONG* pVal)
+{
+ (*pVal) = m_paperColor;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::put_paperColor(LONG newVal)
+{
+ m_paperColor = newVal;
+ m_forcePaper = TRUE;
+
+ return S_OK;
+}
+
+// Zet een vertaal kleur (afhankelijk van papierkleur)
+STDMETHODIMP CWhip2PNG::ReplaceColor(LONG paperColor, LONG oldColor, LONG newColor)
+{
+ m_iWhip2DC.ReplaceColor(paperColor, oldColor, newColor);
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::get_Maximize(VARIANT_BOOL* pVal)
+{
+ (*pVal) = m_Maximize;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::put_Maximize(VARIANT_BOOL newVal)
+{
+ m_Maximize = newVal;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::get_dwgScale(DOUBLE* pVal)
+{
+ (*pVal) = m_dwgScale;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::put_dwgScale(DOUBLE newVal)
+{
+ if (newVal <= 0.0)
+ return myAtlReportError (GetObjectCLSID(), "\nInvalid dwgScale");
+
+ m_dwgScale = newVal;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::get_forceBW(VARIANT_BOOL* pVal)
+{
+ (*pVal) = m_forceBW;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::put_forceBW(VARIANT_BOOL newVal)
+{
+ m_forceBW = newVal;
+ if (m_forceBW)
+ {
+ m_paperColor = 0xFFFFFF; // Op wit alvast
+ m_forcePaper = TRUE;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::get_forceGray(VARIANT_BOOL* pVal)
+{
+ (*pVal) = m_forceGray;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhip2PNG::put_forceGray(VARIANT_BOOL newVal)
+{
+ m_forceGray = newVal;
+
+ return S_OK;
+}
diff --git a/SlnkDWFCom/Whip2PNG.h b/SlnkDWFCom/Whip2PNG.h
new file mode 100644
index 0000000..1e59dab
--- /dev/null
+++ b/SlnkDWFCom/Whip2PNG.h
@@ -0,0 +1,121 @@
+// Whip2PNG.h : Declaration of the CWhip2PNG
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+#include "SLNKEvent.h"
+
+// CWhip2PNG
+
+class ATL_NO_VTABLE CWhip2PNG :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IDispatchImpl
+{
+public:
+
+DECLARE_REGISTRY_RESOURCEID(IDR_WHIP2PNG)
+
+
+BEGIN_COM_MAP(CWhip2PNG)
+ COM_INTERFACE_ENTRY(IWhip2PNG)
+ COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ CComObject *pSLNKEvent; // For when the user has clicked on the drawing
+ HRESULT hr = CComObject::CreateInstance(&pSLNKEvent);
+ if(FAILED(hr)) return hr;
+
+ pSLNKEvent->AddRef();
+ hr = pSLNKEvent->QueryInterface(IID_ISLNKEvent, (void **)&m_SLNKEvent);
+ pSLNKEvent->Release();
+ if(FAILED(hr)) return hr;
+
+// CComObject< CWhip2DC >* pWhip2DC;
+// hr = CComObject::CreateInstance(&pWhip2DC);
+// if(FAILED(hr)) return hr;
+
+// pWhip2DC->AddRef();
+// hr = pWhip2DC->QueryInterface(&m_iWhip2DC);
+// pWhip2DC->Release();
+
+ return hr;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+public:
+
+ CWhip2PNG(); // Default constructor
+
+ // Een van de volgende twee moet gebruikt worden om de file te laden
+ STDMETHOD(Load)(BSTR WhipPath);
+ STDMETHOD(LoadStream)(VARIANT EPlotStream);
+
+ STDMETHOD(SetDimensions)(LONG sizeX, LONG sizeY, LONG offsetX, LONG offsetY, DOUBLE dScale, LONG lRotation);
+ STDMETHOD(SetLayers)(BSTR RegExp);
+
+ STDMETHOD(SaveAsPNG)(BSTR PNGPath);
+ STDMETHOD(SaveAsWMF)(BSTR WMFPath);
+
+ STDMETHOD(TextAsPNG)(BSTR Message, VARIANT *ImageData);
+ STDMETHOD(GetAsPNG)(VARIANT *ImageData);
+ STDMETHOD(GetAsTransGIF)(VARIANT *ImageData);
+ STDMETHOD(GetAsXXX)(VARIANT *ImageData, BOOL bPNG);
+
+ STDMETHOD(Find)(LONG findX, LONG findY, BSTR* foundLabel);
+ STDMETHOD(GetAsMap)(BSTR* AsMap);
+ STDMETHOD(get_AtlRegExp)(BSTR RegExp, BSTR TestExp, BSTR* pVal);
+private:
+ bool CreateCxImage(CxImage* img);
+ void InitDC(HDC &myDC);
+
+ HRESULT StreamPNG(CxImage &img, VARIANT *ImageData, BOOL bPNG);
+
+ CComQIPtr m_SLNKEvent; // For when the user has clicked on the drawing
+ // Will also hold minmax drawing XY?
+
+ //CComQIPtr m_iWhip2DC;
+ CWhip2DCImpl m_iWhip2DC;
+
+ // Een van de volgende twee zal gezet zijn
+ CComQIPtr m_iEPlotSection;
+ CString m_WhipPath;
+
+ void putDWGInfo();
+
+ LONG m_sizeX, m_sizeY;
+ LONG m_offsetX, m_offsetY;
+ double m_dScale;
+ LONG m_lRotation;
+ COLORREF m_paperColor; BOOL m_forcePaper;
+ BOOL m_forceBW;
+ BOOL m_forceGray;
+ BOOL m_Maximize;
+ double m_dwgScale;
+
+ CString m_RegExp;
+public:
+ STDMETHOD(get_SLNKEvent)(ISLNKEvent** pVal);
+ STDMETHOD(get_paperColor)(LONG* pVal);
+ STDMETHOD(put_paperColor)(LONG newVal);
+ STDMETHOD(ReplaceColor)(LONG paperColor, LONG oldColor, LONG newColor);
+ STDMETHOD(get_Maximize)(VARIANT_BOOL* pVal);
+ STDMETHOD(put_Maximize)(VARIANT_BOOL newVal);
+ STDMETHOD(get_dwgScale)(DOUBLE* pVal);
+ STDMETHOD(put_dwgScale)(DOUBLE newVal);
+ STDMETHOD(get_forceBW)(VARIANT_BOOL* pVal);
+ STDMETHOD(put_forceBW)(VARIANT_BOOL newVal);
+ STDMETHOD(get_forceGray)(VARIANT_BOOL* pVal);
+ STDMETHOD(put_forceGray)(VARIANT_BOOL newVal);
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(Whip2PNG), CWhip2PNG)
diff --git a/SlnkDWFCom/Whip2PNG.rgs b/SlnkDWFCom/Whip2PNG.rgs
new file mode 100644
index 0000000..1a83470
--- /dev/null
+++ b/SlnkDWFCom/Whip2PNG.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ SLNKDWF.Whip2PNG.1 = s 'Whip2PNG Class'
+ {
+ CLSID = s '{783AC7F0-E6E1-4CE1-A38B-FA047D44DC1C}'
+ }
+ SLNKDWF.Whip2PNG = s 'Whip2PNG Class'
+ {
+ CLSID = s '{783AC7F0-E6E1-4CE1-A38B-FA047D44DC1C}'
+ CurVer = s 'SLNKDWF.Whip2PNG.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {783AC7F0-E6E1-4CE1-A38B-FA047D44DC1C} = s 'Whip2PNG Class'
+ {
+ ProgID = s 'SLNKDWF.Whip2PNG.1'
+ VersionIndependentProgID = s 'SLNKDWF.Whip2PNG'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/WhipFile.cpp b/SlnkDWFCom/WhipFile.cpp
new file mode 100644
index 0000000..3b3ca2f
--- /dev/null
+++ b/SlnkDWFCom/WhipFile.cpp
@@ -0,0 +1,1065 @@
+// WhipFile.cpp : Implementation of CWhipFile
+
+#include "stdafx.h"
+#include "myEPlotSection.h"
+#include "WhipFile.h"
+#include "SLNKContour.h"
+
+#include "Dwfcore/Mime.h"
+
+//
+// WHIPFILE.CPP
+//
+// This file defines class CWhipFile
+// which is mostly concerned with detecting closed contours
+// and merging a Contour file with a planfile. <<= jun 2007: al lang obsolete
+//
+
+// CWhipFile
+
+WT_Logical_Point star[] = { WT_Logical_Point(-1000, 0),
+ WT_Logical_Point( -200, 200),
+ WT_Logical_Point( 0, 1000),
+ WT_Logical_Point( 200, 200),
+ WT_Logical_Point( 1000, 0),
+ WT_Logical_Point( 200, -200),
+ WT_Logical_Point( 0,-1000),
+ WT_Logical_Point( -200, -200),
+ WT_Logical_Point(-1000, 0)
+ };
+
+WT_Logical_Point octa[] = { WT_Logical_Point( 1000, 414),
+ WT_Logical_Point( 414, 1000),
+ WT_Logical_Point( -414, 1000),
+ WT_Logical_Point(-1000, 414),
+ WT_Logical_Point(-1000, -414),
+ WT_Logical_Point( -414,-1000),
+ WT_Logical_Point( 414,-1000),
+ WT_Logical_Point( 1000, -414),
+ WT_Logical_Point( 1000, 414)
+ };
+
+CWhipFile::CWhipFile()
+{
+ m_FontName.set("Arial");
+ m_FontHeight = 400.0;
+ m_FontHeightSymbols = 200.0;
+
+ // Predefine fixed symbols
+ CSLNKSymbolDefinition * symb = new CSLNKSymbolDefinition(sizeof(star)/sizeof(star[0]), star);
+ m_State.m_SLNKSymbolDefinitions.SetAt("*STAR", symb);
+
+ symb = new CSLNKSymbolDefinition(sizeof(octa)/sizeof(octa[0]), octa);
+ m_State.m_SLNKSymbolDefinitions.SetAt("*OCTAGON", symb);
+}
+
+int xxxx;
+STDMETHODIMP CWhipFile::InterfaceSupportsErrorInfo(REFIID riid)
+{
+ static const IID* arr[] =
+ {
+ &IID_IWhipFile
+ };
+
+ for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
+ {
+ if (InlineIsEqualGUID(*arr[i],riid))
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+// Open de contour file
+STDMETHODIMP CWhipFile::Load(BSTR WhipPath)
+{
+ myDoTRACE("\nCWhipFile::Open('%ls')", WhipPath);
+
+ m_W2DFile.set_filename(WhipPath);
+
+ return ProcessContouren();
+}
+
+
+// Set xc = CreateObject("SLNKDWF.DWFFile")
+// xc.Open(dwfFile)
+// Set y = CreateObject("SLNKDWF.WhipFile")
+// y.LoadStream xc.EplotSections.Item(0)
+STDMETHODIMP CWhipFile::LoadStream(VARIANT EPlotStream)
+{
+ myDoTRACE("\nCCWhipFile::LoadStream()");
+
+ if (EPlotStream.vt!=VT_ERROR)
+ {
+ VARIANT *var2 = &EPlotStream;
+ if (var2->vt==(VT_VARIANT|VT_BYREF)) // ByRef
+ var2 = (VARIANT *)var2->pvarVal;
+
+ if (var2->vt==VT_DISPATCH)
+ {
+ CComQIPtr EPlotSection;
+ EPlotSection = var2->pdispVal;
+ if (!EPlotSection)
+ return E_INVALIDARG;
+ else
+ {
+ m_iEPlotSection = EPlotSection;
+ CEPlotSectionImpl *epli;
+ m_iEPlotSection->get_EPlotSectionImpl((BYTE **)&epli);
+ m_W2DFile.set_eplotsection(epli);
+ }
+ }
+ else
+ return E_INVALIDARG;
+ }
+
+ return ProcessContouren();
+}
+
+HRESULT CWhipFile::ProcessContouren()
+{
+ m_W2DFile.set_file_mode(WT_File::File_Read);
+
+ // Alle callback functies zijn static. Die kunnen de variabele
+ // m_State niet benaderen. Daarom maar via set_user_data
+ m_W2DFile.heuristics().set_user_data((void *)&m_State);
+
+ if (m_W2DFile.open() == WT_Result::Success)
+ { xxxx=0;
+ CmyTimer xx("Contouren opzoeken");
+ m_State.contLayerActive = true;
+ m_State.labelLayerActive = true; // Kan bij de eerste laag anders blijken te zijn
+
+ read_for_contours(); // Zoek eerst alle contouren en labels
+ processLabels(); // En verwerk ze daarna
+ myDoTRACE("\nFound %d polylines, %d contours and %d labels.", xxxx, m_State.m_SLNKContouren.GetCount(), m_State.m_SLNKLabels.GetCount());
+
+ m_W2DFile.close(); // closing Input file.
+ }
+ else
+ {
+ return myAtlReportError (GetObjectCLSID(), "ERROR CWhipFile:: Unable to open file/stream:");
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CWhipFile::SetLayers(BSTR reContouren, BSTR reLabels)
+{
+ myTRACE("\nParsing met contouren %ls", reContouren);
+ myTRACE("\nParsing met labels %ls", (LPCTSTR)reLabels);
+ if (!m_State.SetLayers(reContouren, reLabels))
+ return myAtlReportError (GetObjectCLSID(), "ERROR: Unable to parse Whipfile regLayers");
+
+ return S_OK;
+}
+
+// Lagen die over moeten blijven. De rest wordt er uit gestript.
+STDMETHODIMP CWhipFile::SetFilterLayers(BSTR reLayers)
+{
+ myTRACE("\nFilter met lagen %ls", reLayers);
+ if (!m_State.SetFilterLayers(reLayers))
+ return myAtlReportError (GetObjectCLSID(), "ERROR: Unable to parse Whipfile SetFilterLayers");
+
+ return S_OK;
+}
+
+void CWhipFile::read_for_contours()
+{
+ WT_Result result;
+
+ m_W2DFile.set_text_action(my_process_text);
+ m_W2DFile.set_polyline_action(my_process_polyline);
+
+ // AutoCAD does not generate polygon's for closed polylines
+ // It only does for filled SOLID hatching
+ //m_W2DFile.set_polygon_action(my_process_polygon);
+ //m_W2DFile.set_polytriangle_action(my_process_polytriangle);
+ m_W2DFile.set_layer_action(my_process_layer);
+ // Do the actual reading.
+ do {
+ result = m_W2DFile.process_next_object();
+ } while (result == WT_Result::Success);
+
+ // Nu zijn ze wel een keer bekend, we hebben ze later weer nodig
+ m_State.m_contunits=m_W2DFile.rendition().drawing_info().units();
+ m_view=m_W2DFile.rendition().rendering_options().view();
+
+ // We gaan er later nog een keer door voor de plattegrond. Geen processing dan
+ m_W2DFile.set_text_action(WT_Text::default_process);
+ m_W2DFile.set_polyline_action(WT_Polyline::default_process);
+}
+
+// Result: Area in original drawing coordinates
+// Veronderstel dat het 5e punt gelijk is aan het eerste (daarom aan einde delen door 2?)
+double PolygonArea(WT_Point_Set * ps, WT_Units units)
+{
+ int i,j;
+ double area = 0;
+
+ for (i=0;icount();i++) {
+ j = (i + 1) % ps->count();
+ WT_Point3D dwfPtA = units.transform(ps->points()[i]);
+ WT_Point3D dwfPtB = units.transform(ps->points()[j]);
+
+ area += dwfPtA.m_x * dwfPtB.m_y;
+ area -= dwfPtA.m_y * dwfPtB.m_x;
+ }
+
+ area /= 2;
+ return(area < 0 ? -area : area);
+}
+
+// Iterate all labels and determine in which contour they fall
+void CWhipFile::processLabels()
+{
+ for (size_t lbl=0; lblm_DWGArea/1e6);
+ if (contour->m_contLabel.length()==0)
+ {
+ if (prevContour != NULL)
+ {
+ myTRACE(" Hmm, we hadden al eerder succes");
+ if (prevContour->m_DWGArea > contour->m_DWGArea)
+ {
+ myTRACE(" en we hebben een kleinere. Reset prevContour");
+ prevContour->m_contLabel = "";
+ prevContour = contour;
+ }
+ else // Nieuwe contour is niet beter
+ {
+ contour = prevContour;
+ }
+ }
+ else
+ prevContour = contour;
+ prevContour->m_contLabel = text.string();
+ prevContour->m_Key = text.string().ascii();
+ #ifdef SHAKE_FOR_TEST
+ if (1||prevContour->m_Label.equals("x706"))
+ {
+ srand( (unsigned)time( NULL ) );
+ int i;
+ for (i=0;icount();i++) {
+ WT_Logical_Point *pt = &(prevContour->points()[i]);
+ int diff = (int)(400); // 0.1% afwijking
+ double dx = ((double)rand() / RAND_MAX - 0.5);
+ double dy = ((double)rand() / RAND_MAX - 0.5);
+ pt->m_x += diff * dx;
+ pt->m_y += diff * dy;
+ }
+
+ }
+ #endif
+ prevContour->m_ptLabel = text.position();
+ }
+ else
+ {
+ myTRACE("\nLabel %s with area %8.2fm2", text.string().ascii(), contour->m_DWGArea/1e6);
+ if (!strcmp(text.string().ascii(), contour->m_contLabel.ascii()))
+ myTRACE(" komt dubbel voor (maar wel dezelfde contour)!");
+ else
+ myTRACE(" was al bezet door %s", contour->m_contLabel.ascii());
+ }
+ }
+ }
+ }
+ return;
+}
+
+WT_Result CWhipFile::my_process_layer (WT_Layer & layer, WT_File & file)
+{
+ file.rendition().layer() = layer;
+ if (layer.layer_name().length()>0) // Anders zittie alleen maar in de weg
+ { // Dat doet de default_process 'fout'
+ file.layer_list().add_layer(layer);
+ }
+
+ WT_Integer32 layer_num = layer.layer_num();
+ WT_Layer *ll = file.layer_list().find_layer_from_index(layer_num);
+ if (ll&& ll->layer_name().ascii())
+ {
+ CWhipFileState *m_State = (CWhipFileState *)file.heuristics().user_data();
+ m_State->labelLayerActive = m_State->labelMatch(ll->layer_name().ascii());
+ m_State->contLayerActive = m_State->contMatch(ll->layer_name().ascii());
+ }
+
+ return WT_Result::Success;
+}
+
+// This is what AutoCAD seems to create for a normal closed polyline
+// but also for the rendition of the character '0'
+WT_Result CWhipFile::my_process_polyline(WT_Polyline & polyline, WT_File & file)
+{
+ CWhipFileState *m_State = (CWhipFileState *)file.heuristics().user_data();
+ if (!m_State->contLayerActive)
+ return WT_Result::Success; // Wrong layer
+
+ bool frstIsLast = (polyline.points()[0].m_x == polyline.points()[polyline.count()-1].m_x &&
+ polyline.points()[0].m_y == polyline.points()[polyline.count()-1].m_y);
+ // (Vigor) DWF's uit ARKEY hebben de onhebbelijke eigenschap dat de contour begint
+ // met een aanhaallijntje. Dat ondersteunen we dan toch maar.
+ bool scndIsLast = false;
+ if (g_SLNKOptions.m_SkipContLeader && polyline.count()>1)
+ {
+ scndIsLast = (polyline.points()[1].m_x == polyline.points()[polyline.count()-1].m_x &&
+ polyline.points()[1].m_y == polyline.points()[polyline.count()-1].m_y);
+ }
+ if (!frstIsLast && !scndIsLast)
+ return WT_Result::Success; // Not closed. Who cares
+
+xxxx++;
+
+ WT_Units units=file.rendition().drawing_info().units();
+
+ // WD_True as we are going to mess
+ CSLNKContourImpl *myContour;
+ if (scndIsLast) // eerste lijntje droppen
+ myContour = new CSLNKContourImpl(polyline.count()-1,polyline.points()+1, WD_True, m_State);
+ else
+ myContour = new CSLNKContourImpl(polyline.count(),polyline.points(), WD_True, m_State);
+
+ // A major problem: Sometimes AutoCAD's DWFOUT merges two adjacent polylines
+ // into one WT_Polyline. We hate that so we start splitting them again here
+ // Note this also happens on rendering of some texts. We don't care about
+ // that but cannot detect the difference, so split them as well.
+ // TODO: Als een afgesplitste contour uiteindelijk binnen de start contour
+ // valt dan hebben we te maken met een eiland dat door een tekenaar
+ // gemaakt is. Dan moeten we niet splitsen. Zucht..
+
+ for (int i=1; icount()-2; i++) // -2: Laat normale eindpunt ongemoeid
+ {
+ if ((myContour->points()[i]).m_x == (myContour->points()[0]).m_x &&
+ myContour->points()[i].m_y == myContour->points()[0].m_y
+ )
+ { // Van 0..i is al een loop. Trek die er alvast uit
+ myTRACE("\nSplit case %d-%d",i,myContour->count());
+ // Create a copy of the looping section
+ // Sample: i=6, j=2, diff=4 pt
+ CSLNKContourImpl *myContour2 = new CSLNKContourImpl(i, myContour->points(), WD_True, m_State);
+ myContour2->m_DWGArea = PolygonArea(myContour2, units);
+ m_State->m_SLNKContouren.Add(myContour2);
+
+ // Create a copy of the end section
+ CSLNKContourImpl *myContour3 = new CSLNKContourImpl(myContour->count()-i, myContour->points()+i, WD_True, m_State);
+ // Delete the old one (seem all together a little overkill)
+ delete myContour;
+ myContour = myContour3;
+ i=0; // vanaf daar verder kijken
+ }
+ }
+
+ // Bij akzo 4310 kwam (Alleen AutoCAD 2004) het volgende geval voor.
+ // Dat onderkennen we door te testen met het oude algoritme en een twee-punts overlap
+ // 0,8--->1
+ // | |
+ // | v
+ // 3,7<--2,6
+ // | ^
+ // v |
+ // 4----->5
+
+ for (int i=1; icount()-1; i++)
+ {
+ for (int j=0; jpoints()[i] == myContour->points()[j])
+ {
+ myTRACE("\nSplitsen?");
+ if (myContour->points()[i+1] == myContour->points()[j+1])
+ {
+ myTRACE(" YES");
+ // Van j..i is een loop. Trek die er uit
+ // myTRACE("\nSplit case %d-%d",i,myContour->count());
+ // Create a copy of the looping section
+ // Sample: i=6, j=2, diff=4 pt
+ CSLNKContourImpl *myContour2 = new CSLNKContourImpl(i-j+1, myContour->points()+j, WD_True, m_State);
+ myContour2->m_DWGArea = PolygonArea(myContour2, units);
+ m_State->m_SLNKContouren.Add(myContour2);
+
+ // Close the hole in myContour
+ for (int k=j+1; k+i-jcount(); k++)
+ myContour->points()[k]=myContour->points()[k+i-j];
+
+ // Create a copy of the start section
+ CSLNKContourImpl *myContour3 = new CSLNKContourImpl(myContour->count()-(i-j), myContour->points(), WD_True, m_State);
+ // Delete the old one (seem all together a little overkill)
+ delete myContour;
+ myContour = myContour3;
+ i=j; // vanaf daar verder kijken
+ }
+ }
+ }
+
+ // Last (or only) section
+ myContour->m_DWGArea = PolygonArea(myContour, units);
+ myTRACE("\nFound contour with area %8.2fm2", myContour->m_DWGArea/1e6);
+ if (myContour->m_DWGArea >= g_SLNKOptions.m_MinContSize)
+ m_State->m_SLNKContouren.Add(myContour);// Doet uiteindelijk wel een delete op myContour
+ else
+ {
+ myTRACE(" te klein bevonden");
+ delete myContour;
+ }
+
+ return WT_Result::Success;
+}
+
+// Note: For SHX-fonts AutoCAD 2002+ creates an invisible (Text) object
+// which will get used here
+WT_Result CWhipFile::my_process_text (WT_Text & text, WT_File & file)
+{
+ CWhipFileState *m_State = (CWhipFileState *)file.heuristics().user_data();
+ if (!m_State->labelLayerActive)
+ return WT_Result::Success; // Wrong layer
+
+ m_State->m_SLNKLabels.Add(text);
+ return WT_Result::Success;
+}
+
+// 'Herschrijf' de plan DWF naar de output
+// Doe eerst de 'header' van de DWF (viewport en zo) en zodra
+// we de eerste drawable tegenkomen doen we de contouren tussendoor
+// zodat die (als ze ingekleurd worden) altijd onderaan liggen
+HRESULT CWhipFile::SerializePlan(WT_File & my_plan_file, myWT_File & my_file, double scale)
+{
+ WT_Result result;
+ BOOL firstDrawable = true;
+
+ BOOL CurrentLayerOn = TRUE; // Skip contourlagen
+ my_plan_file.set_layer_action(my_process_layer); // Override default processing
+ // Do the actual reading.
+
+ while ((result = my_plan_file.process_next_object()) == WT_Result::Success)
+ {
+ switch(my_plan_file.current_object()->object_type())
+ {
+ case WT_Object::Origin_ID:
+ break;
+ case WT_Object::Drawable:
+ if (firstDrawable)
+ GenerateContouren(my_plan_file, my_file, scale, true); // Alle 'solid' kleuren
+ firstDrawable = false;
+#ifdef _DEBUG
+ if (my_plan_file.current_object()->object_id() == WT_Object::Origin_ID
+ && !my_file.heuristics().allow_binary_data()
+ )
+ { // I do not understand why but it will assert otherwise
+ break;
+ }
+#endif
+ if (CurrentLayerOn)
+ my_plan_file.current_object()->serialize(my_file);
+ break;
+ case WT_Object::Attribute:
+ {
+ const WT_Attribute *obj = (WT_Attribute *)my_plan_file.current_object();
+ if (obj->object_id() == WT_Object::Layer_ID)
+ { // Sla de oorspronkelijke contour lagen over
+ // En ook de lagen die we niet willen
+ CurrentLayerOn = TRUE;
+ WT_Layer *layer = (WT_Layer *)obj;
+ WT_Integer32 layer_num = layer->layer_num();
+ if (layer_num==0)
+ { // ARKEY heeft lagen met nummer 0. Dat mag niet volgens de
+ // Whip-spec en gaat ook mis (alleen) bij binaire DWF's
+ if (my_file.heuristics().allow_binary_data())
+ {
+ myDoTRACE("\nSkipping layer with invalid number 0");
+ break;
+ }
+ }
+ WT_Layer *ll = my_plan_file.layer_list().find_layer_from_index(layer_num);
+ if (ll&&
+ ll->layer_name().ascii()&&
+ (m_State.labelMatch(ll->layer_name().ascii()) ||
+ m_State.contMatch(ll->layer_name().ascii()) ||
+ !m_State.layerMatch(ll->layer_name().ascii()))
+ )
+ CurrentLayerOn = FALSE; // Layer object hoeft ook niet meer geserialized
+ else
+ layer->serialize(my_file);
+ }
+ else
+ {
+#ifdef _DEBUG
+ CString s(my_plan_file.file_stats()->descriptions());
+ // myTRACE("Attribute '%s'\n", s);
+#endif
+ // Hoewel een Attibute gaat hij toch niet via desired_rendition
+ // Omdat we weten dat we net uit uit een DWF komen kunnen we best
+ // wel rechtstreeks serializen
+ // Let wel: desired_rendition is dan niet meer te vertrouwen. Zie @@@
+ obj->serialize(my_file);
+ }
+ }
+ break;
+ default:
+#ifdef _DEBUG
+ CString s(my_plan_file.file_stats()->descriptions());
+ //myTRACE("Skipping '%s'\n", s);
+#endif
+ break;
+ }
+ }
+// if (result == WT_Result::End_Of_DWF_Opcode_Found)
+// dwfresult = DwfResult::Success;
+
+// TODO: desired_rendition klopt nu niet meer met de daadwerkelijke rendition?
+
+ return S_OK;
+}
+
+// Extra saveas wrapper om met __try een eventuele Win32 exception ook op te vangen
+STDMETHODIMP CWhipFile::SaveAs(BSTR WhipPath)
+{
+ myTRACE("\nAbout to save into %ls with plan", (LPCTSTR)WhipPath);
+
+ __try {
+ return SaveAs2(WhipPath);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DWORD exCode = GetExceptionCode();
+ myDoTRACE("\nUnhandled Win32 exception 0x%x in CWhipFile::SaveAs", exCode);
+ char err[128];
+ sprintf(err, "\nUnhandled Win32 exception 0x%x", exCode);
+
+ return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::SaveAs('%ls')\n%s", (LPCSTR)WhipPath, err);
+ }
+}
+
+STDMETHODIMP CWhipFile::SaveAs2(BSTR WhipPath)
+{
+ try {
+ myWT_File my_file;
+ my_file.set_filename(WhipPath);
+ return Generate(my_file);
+ }
+ catch (WT_Result::Enum e)
+ {
+ CString err;
+ err.Format("\nInternal error WT_Result::Enum %d",e);
+ return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::SaveAs('%ls')\n%s", (LPCSTR)WhipPath, err);
+ }
+ catch (CString &err)
+ {
+ return myAtlReportError (GetObjectCLSID(), err);
+ }
+}
+
+// Altijd hoogte 1000, echte fontheight gaf overflow bij SDU
+class tempFontDC
+{
+public:
+ tempFontDC(WT_String m_FontName)
+ {
+ HDC tempDC = CreateDC("DISPLAY",NULL,NULL,NULL);
+ m_DC = CreateCompatibleDC ( tempDC );
+ DeleteDC(tempDC);
+
+ LOGFONT lf;
+ memset(&lf, 0, sizeof(LOGFONT)); // clear out structure.
+ strncpy(lf.lfFaceName, m_FontName.ascii(), LF_FACESIZE);
+ lf.lfHeight = -FONT_SIZER;
+ fnt = CreateFontIndirect(&lf);
+ HGDIOBJ oldfont = SelectObject(m_DC, fnt);
+ }
+
+ ~tempFontDC()
+ {
+ // Opruimen
+ DeleteObject(fnt);
+ DeleteDC(m_DC);
+ }
+ inline operator const HDC()
+ { return m_DC; }
+private:
+ HDC m_DC;
+ HFONT fnt;
+};
+
+bool CWhipFile::GenerateSymbols(myWT_File &my_file)
+{
+ double scale = m_State.m_contunits.application_to_dwf_transform()(0,0);
+ // TODO: Echt uniek layernum (en URL num) bepalen
+ my_file.desired_rendition().layer() = WT_Layer(my_file, 1000, "SLNK Symbols");
+
+ for (size_t i=0; im_symbolName == "" || !m_State.m_SLNKSymbolDefinitions.Lookup(symbol->m_symbolName))
+ symbol->serialize(my_file, m_State.m_contunits, NULL, m_State.m_hintScale);
+ else
+ {
+#ifdef _DEBUG
+ WT_Comments cmt;
+ CString s; s.Format("About to insert symbol %s", symbol->m_symbolName);
+ cmt.set(s);
+ cmt.serialize(my_file);
+#endif
+ symbol->serialize(my_file, m_State.m_contunits, m_State.m_SLNKSymbolDefinitions[symbol->m_symbolName], m_State.m_hintScale);
+ }
+ }
+ return true;
+}
+
+bool CWhipFile::GenerateSymbolLabels(myWT_File &my_file)
+{
+ double scale = m_State.m_contunits.application_to_dwf_transform()(0,0);
+ // Zet een DC op om bij 'Center' de afmetingen van de tekst te kunnen bepalen
+ int fontheight= myRound(m_FontHeightSymbols * scale);
+ tempFontDC myDC(m_FontName);
+
+ WT_Font myfont;
+ myfont.font_name() = m_FontName;
+ myfont.height() = fontheight;
+ my_file.desired_rendition().font() = my_file.rendition().font() = myfont;
+ myfont.serialize(my_file); // Vertrouw niets. Expliciete serialize. Zie @@@
+
+ WT_Color clr(255,255,255,0); //Teksten wit
+ my_file.desired_rendition().color() = my_file.rendition().color() = clr;
+ clr.serialize(my_file); // Vertrouw niets. Expliciete serialize. Zie @@@
+
+ // TODO: Echt uniek layernum (en URL num) bepalen
+ my_file.desired_rendition().layer() = WT_Layer(my_file, 1001, "SLNK Symbol Labels");
+ for (size_t i=0; im_dwgX, symbol->m_dwgY));
+ symbol->m_SLNKContour.m_ptLabel = center;
+ symbol->m_SLNKContour.SerializeLabel(my_file, CSLNKContourImpl::LABEL_OUTSIDEBOTTOM, fontheight, myDC);
+ }
+ return true;
+}
+
+// Schrijf alle uitgerekende contouren naar het DWF bestand
+// Deze functie wordt twee keer aangeroepen
+// Heel vroeg (voor de plattegrond) worden alle contouren met een solid kleur
+// wegeschreven. Die komen dan helemaal onderop. Ze zouden anders afdekken
+// In de tweede slag komen alle transparante contouren. Die komen na de
+// plattegrond zodat de plattegrond doorschijnt.
+bool CWhipFile::GenerateContouren(WT_File &my_planfile, myWT_File &my_file,
+ double scale, BOOL solidOnly)
+{
+ // Zorg dat we zelf neutraal blijven
+ WT_Layer keepLayer = my_planfile.rendition().layer();
+ WT_Color keepColor = my_planfile.rendition().color();
+
+ // Vertrouw de huidige rendition niet!
+ WT_Color().serialize(my_file);
+
+ //Store the current object node hoewel die echt null zal zijn....
+ WT_Object_Node current_node = my_file.desired_rendition().object_node();
+
+ // TODO: Echt uniek layernum (en URL num) bepalen
+ my_file.desired_rendition().layer() = WT_Layer(my_file, 1002, "SLNK Contours");
+
+ for (size_t i=0; iserialize(my_file, solidOnly);
+ }
+ my_file.desired_rendition().object_node() = current_node;
+
+ my_file.desired_rendition().line_weight() = 0; // Voor als er later bijvoorbeeld nog symbolen komen
+
+ my_file.desired_rendition().layer() = my_file.rendition().layer() = keepLayer;
+ if (keepLayer.layer_num()) keepLayer.serialize(my_file); // Zeker terugzetten
+ my_file.desired_rendition().color() = my_file.rendition().color() = keepColor;
+ keepColor.serialize(my_file); // Zeker terugzetten
+ return true;
+}
+
+bool CWhipFile::GenerateLabels(WT_File &my_planfile, myWT_File &my_file, double scale)
+{
+ // Zorg dat we zelf neutraal blijven
+ WT_Layer keepLayer = my_planfile.rendition().layer();
+ WT_Color keepColor = my_planfile.rendition().color();
+
+ // TODO: Echt uniek layernum (en URL num) bepalen
+ my_file.desired_rendition().layer() = WT_Layer(my_file, 1003, "SLNK Labels");
+
+ // Zet een DC op om bij 'Center' de afmetingen van de tekst te kunnen bepalen
+ int fontheight= myRound(m_FontHeight * scale);
+ tempFontDC myDC(m_FontName);
+
+ WT_Font myfont;
+ myfont.font_name() = m_FontName;
+ myfont.height() = fontheight;
+ my_file.desired_rendition().font() = my_file.rendition().font() = myfont;
+ myfont.serialize(my_file); // Vertrouw niets. Expliciete serialize. Zie @@@
+
+ // En nu nog een keer alle teksten
+ for (size_t i=0; im_contLabel.length()!=0 && contour->m_ExtraLabel != "")
+ { // We have got a proper label/contour
+ // Alle teksten tekenen
+ contour->SerializeLabel(my_file, m_LabelPos, fontheight, myDC);
+ }
+ }
+
+ my_file.desired_rendition().layer() = my_file.rendition().layer() = keepLayer;
+ if (keepLayer.layer_num()) keepLayer.serialize(my_file); // Zeker terugzetten
+ my_file.desired_rendition().color() = my_file.rendition().color() = keepColor;
+ keepColor.serialize(my_file); // Zeker terugzetten
+
+ return true;
+}
+
+// We hebben de contouren bepaald. Genereer daarvoor nu nieuwe DWF-primitieven
+// In het bijzonder kennen we er een kleurtje aan toe en plaatsen wel de labels (opnieuw)
+STDMETHODIMP CWhipFile::Generate(myWT_File &my_file)
+{
+ // Bepaal de te gebruiken hoogte in Logical Points
+
+ double scale = m_State.m_contunits.application_to_dwf_transform()(0,0);
+ myDoTRACE("\nSchaal: %.2f", scale);
+
+ WT_Result result;
+
+ my_file.set_file_mode(WT_File::File_Write);
+#ifdef _DEBUG
+ my_file.heuristics().set_allow_binary_data(WD_False);
+#endif
+ // Zal niet zo snel meer gebeuren maar we willen het zeker niet
+ my_file.heuristics().set_allow_drawable_merging(WD_False);
+ // Let op: De viewer kan 60-file niet zo maar lezen, dat moet naar packed-DWF
+ // Later: viewer 6.5 kan gewoon een W2D file tonen
+ // Let op: bij versie 55 worden Node's niet weggeschreven
+ // my_file.heuristics().set_target_version(55);
+ if (my_file.open() != WT_Result::Success)
+ {
+ return myAtlReportError (GetObjectCLSID(), "ERROR: Unable to open file for writing: %s", my_file.filename().ascii());
+ ATLASSERT(false);
+ }
+
+ // Symbolen worden mogelijk geplaatst net buiten onze coordinatenruimte (met name X)
+ // Dat gaf clipping problemen.
+ // Daarom verplaatsen we alles in onze coordinatenruimte naar links/onder (0,0)
+ WT_Logical_Point lshift(-(max(0,this->m_view.view().m_min.m_x)),
+ -(max(0,this->m_view.view().m_min.m_y))); // Iets minder clipping van INT_MAX
+ // Contouren hebben we ondertussen al wel/
+ // Nu nog een keer door de DWF om de rest te kopieren naar de output
+ m_W2DFile.set_file_mode(WT_File::File_Read);
+ my_file.heuristics().set_apply_transform(WD_False);
+ myTRACE("\nAbout to open plan");
+ if (m_W2DFile.open() == WT_Result::Success)
+ {
+#ifdef _DEBUG
+ WT_Comments cmt;
+ cmt.set("About to insert planfile");
+ cmt.serialize(my_file);
+#endif
+ // TODO: Dit moet uit de originele PlanDWF z'n Manifest/Paper komen
+
+ int keep=my_file.heuristics().target_version();
+ // Even background ondersteunen
+ my_file.heuristics().set_target_version(55);
+ WT_Background bg(WT_Color(0,0,0));
+ bg.serialize(my_file);
+ my_file.heuristics().set_target_version(keep);
+
+ my_file.heuristics().set_transform(WT_Transform (lshift, 1.0, 1.0, 0));
+ my_file.heuristics().set_apply_transform(true);
+
+ {
+ CmyTimer tm("Serializing plan");
+ SerializePlan(m_W2DFile, my_file, scale); // Heeft eventueel een GenerateContouren in zich!
+ }
+#ifdef _DEBUG
+ cmt.set("Plan is serialized");
+ cmt.serialize(my_file);
+#endif
+ myTRACE("\nPlan is serialized");
+ m_W2DFile.close();
+ }
+ else
+ {
+ myTRACE("\nKon plan niet openen");
+ return myAtlReportError (GetObjectCLSID(), "ERROR: Unable to open plan file");
+ }
+
+ myTRACE("\nAbout to generate Contouren");
+ // Twee loops. Eerst alle contouren (en vlakvullingen), daarna pas
+ // de teksten. Zodoende zijn de teksten altijd leesbaar
+ GenerateContouren(m_W2DFile, my_file, scale, false); // Alle transparante kleuren
+ //merging geeft vreemd effect op de contouren die we om symbolen tekenen in _DEBUG mode
+ // dan worden die contouren niet meer meegeschaalt? TODO: Uitzoeken
+ //my_file.heuristics().set_allow_drawable_merging(WD_True); // Voor symbolen kan het (na verschalen) wel schelen
+ GenerateSymbols(my_file); // Ook alle contouren van symbolen
+ GenerateSymbolLabels(my_file);
+ GenerateLabels(m_W2DFile, my_file, scale);
+
+ myTRACE("\nAbout to close");
+ //Restore the saved object node.
+ my_file.desired_rendition().fill() = WD_False;
+ my_file.close();
+
+ myTRACE("\nDone saving");
+ return S_OK;
+}
+
+// mei 2007: DEPRECATED
+// Lege Identlabel zet alle labels op de extralabel+default
+STDMETHODIMP CWhipFile::SetLabel(BSTR IdentLabel, BSTR ExtraLabel)
+{
+ try {
+ for (size_t i=0; im_contLabel.length()>0)
+ {
+ if (contour->m_contLabel.equals(IdentLabel) || SysStringLen(IdentLabel) == 0)
+ {
+ contour->m_ExtraLabel = ExtraLabel;
+ }
+
+ if (SysStringLen(IdentLabel) == 0)
+ contour->m_ExtraLabel += contour->m_contLabel.ascii();
+ }
+ }
+ return S_OK;
+ }
+ catch (WT_Result::Enum e)
+ {
+ CString err;
+ err.Format("\nInternal error WT_Result::Enum %d",e);
+ return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::SetLabel('%ls')\n%s", (LPCSTR)IdentLabel, err);
+ }
+}
+
+// mei 2007: DEPRECATED
+// Lege Identlabel zet alle ruimtes op dezelfde kleur
+STDMETHODIMP CWhipFile::SetColor(BSTR IdentLabel, ULONG rgb, BYTE Alpha /*=0*/)
+{
+ try {
+ for (size_t i=0; im_contLabel.length()>0 &&
+ (SysStringLen(IdentLabel) == 0 || contour->m_contLabel.equals(IdentLabel)))
+ {
+ int b=rgb%256;
+ int g=(rgb>>8)%256;
+ int r=(rgb>>16)%256;
+ contour->m_Color.set(r, g, b, Alpha);
+ }
+ }
+ return S_OK;
+ }
+ catch (WT_Result::Enum e)
+ {
+ CString err;
+ err.Format("\nInternal error WT_Result::Enum %d",e);
+ return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::SetColor('%ls')\n%s", (LPCSTR)IdentLabel, err);
+ }
+
+}
+
+STDMETHODIMP CWhipFile::SetLabelFont(BSTR FontName, DOUBLE FontHeight, DOUBLE FontHeightSymbols)
+{
+ m_FontName.set(FontName);
+ m_FontHeight = FontHeight;
+ m_FontHeightSymbols = (FontHeightSymbols>0)?FontHeightSymbols:FontHeight;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhipFile::SetLabelPosition(BYTE LabelPos)
+{
+ switch (LabelPos)
+ {
+ case 1: m_LabelPos = CSLNKContourImpl::LABEL_DEFAULT; break;
+ case 2: m_LabelPos = CSLNKContourImpl::LABEL_CENTROID; break;
+ case 3: m_LabelPos = CSLNKContourImpl::LABEL_TOPLEFT; break;
+ default: m_LabelPos = CSLNKContourImpl::LABEL_DEFAULT;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhipFile::get_ContoursXML(BSTR* pVal)
+{
+ DWFCore::DWFBufferOutputStream XMLProps(1024);
+
+ DWFUUID _oUUID;
+ DWFXMLSerializer XML(_oUUID);
+ XML.attach(XMLProps);
+ XML.startElement( L"Contours", L"SLNKDWF" );
+ for (size_t i=0; iserializeXML(XML, 0);
+ }
+ XML.endElement();
+ XML.detach();
+
+ CComBSTR bstrString((int)XMLProps.bytes(), (LPCSTR)XMLProps.buffer());
+ return bstrString.CopyTo(pVal);
+}
+
+STDMETHODIMP CWhipFile::get_AddSymbol(DOUBLE dwgX, DOUBLE dwgY, BSTR symbolName, IUnknown** pVal)
+{
+ CString name(symbolName);
+
+ myTRACE("\nAdding symbol %s at %.2f,%.2f", name, dwgX, dwgY);
+
+ CSLNKSymbolImpl *mySymbol = new CSLNKSymbolImpl(dwgX, dwgY, &m_State);
+ m_State.m_SLNKSymbols.Add(mySymbol);
+
+ // Als resultaat leveren we een COM object op waar je eventueel de rest van
+ // de properties op kunt zetten
+ CComObject *theSymbol;
+ HRESULT hr = CComObject::CreateInstance(&theSymbol);
+ if(FAILED(hr)) return hr;
+
+ theSymbol->AddRef();
+ hr = theSymbol->QueryInterface(IID_ISLNKSymbol, (void **)pVal);
+ theSymbol->SetParent(this); // Zodat scope blijft
+ theSymbol->Release();
+ if(FAILED(hr)) return hr;
+ theSymbol->SetImpl(mySymbol); // Heel belangrijk: zet de implementatie waar we een interface op bieden
+
+ if (!m_State.m_SLNKSymbolDefinitions.Lookup(name))
+ name = "*STAR"; // Die vinden we altijd ja
+ ATLASSERT(m_State.m_SLNKSymbolDefinitions.Lookup(name));
+
+ mySymbol->m_symbolName = name;
+ mySymbol->m_SLNKContour.set(m_State.m_SLNKSymbolDefinitions[name]->m_BoundingContour.count(),
+ m_State.m_SLNKSymbolDefinitions[name]->m_BoundingContour.points(), true); // TODO: Is copy wel nodig?==>Ja, we gaan ze later transformeren!
+ if (name[0] == '*')
+ {
+ mySymbol->m_SLNKContour.m_Color = WT_Color(255,0,0,255);
+ mySymbol->m_SLNKContour.m_outlineAlpha = 255; // Anders wordtie helemaal niet getekend?
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CWhipFile::DefineSymbol(BSTR symbolName, VARIANT EPlotStream)
+{
+ myTRACE("\nDefining symbol %ls", symbolName);
+ if (EPlotStream.vt!=VT_ERROR)
+ {
+ VARIANT *var2 = &EPlotStream;
+ if (var2->vt==(VT_VARIANT|VT_BYREF)) // ByRef
+ var2 = (VARIANT *)var2->pvarVal;
+
+ if (var2->vt==VT_DISPATCH)
+ {
+ CComQIPtr EPlotSection;
+ EPlotSection = var2->pdispVal;
+ if (!EPlotSection)
+ return E_INVALIDARG;
+ else
+ {
+ CSLNKSymbolDefinition * symb = new CSLNKSymbolDefinition(EPlotSection);
+
+ CString name(symbolName);
+ m_State.m_SLNKSymbolDefinitions.SetAt(name, symb);
+ }
+ }
+ else
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhipFile::DefineBitmapSymbol(BSTR symbolName, BSTR symbolPath, double height)
+{
+ myTRACE("\nDefining bitmap symbol %ls", symbolName);
+ CSLNKSymbolDefinition * symb = new CSLNKSymbolDefinition(CString(symbolPath), height);
+ CString name(symbolName);
+ m_State.m_SLNKSymbolDefinitions.SetAt(name, symb);
+ //return E_INVALIDARG;
+
+ return S_OK;
+}
+
+// Merk op: als iemand twee keer dezelfde contour opvraagt maken we twee onafhankelijke
+// SLNKContour objecten aan die beide naar dezelfde CSLNKContourImpl wijzen
+// Het maakt verder weinig uit en is wel gemakkelijker (toch?)
+STDMETHODIMP CWhipFile::get_Contour(BSTR IdentLabel, IUnknown** pVal)
+{
+ try {
+ for (size_t i=0; im_contLabel.length()>0 && contour->m_contLabel.equals(IdentLabel))
+ {
+ CComObject *theContour;
+ HRESULT hr = CComObject::CreateInstance(&theContour);
+ if(FAILED(hr)) return hr;
+
+ theContour->AddRef();
+ hr = theContour->QueryInterface(IID_ISLNKContour, (void **)pVal);
+ theContour->SetParent(this);
+ theContour->Release();
+ if(FAILED(hr)) return hr;
+ theContour->SetImpl(contour); // Heel belangrijk: zet de implementatie waar we een interface op bieden
+
+ return S_OK; // Wel gevonden
+ }
+ }
+ return S_OK; // Niet gevonden. Automatisch NULL?
+ }
+ catch (WT_Result::Enum e)
+ {
+ CString err;
+ err.Format("\nInternal error WT_Result::Enum %d",e);
+ return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::get_Contour('%ls')\n%s", (LPCSTR)IdentLabel, err);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhipFile::get_hintScale(DOUBLE* pVal)
+{
+ (*pVal) = m_State.m_hintScale;
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhipFile::put_hintScale(DOUBLE newVal)
+{
+ m_State.m_hintScale = newVal;
+ myTRACE("\nhintScale set to %.6f", newVal);
+
+ return S_OK;
+}
+
+STDMETHODIMP CWhipFile::get_FindInContour(DOUBLE dwgX, DOUBLE dwgY, BSTR* pVal)
+{
+ CString result;
+ WT_Point3D insertion(dwgX, dwgY);
+ WT_Logical_Point LPInsertion = m_State.m_contunits.transform(WT_Point3D(dwgX, dwgY));
+
+ for (size_t i=0; im_contLabel.length()>0)
+ if (CSLNKContourImpl::PointInPolygon(LPInsertion, *contour))
+ {
+ result = contour->m_contLabel;
+ (*pVal) = result.AllocSysString();
+ }
+ }
+ return S_OK;
+}
\ No newline at end of file
diff --git a/SlnkDWFCom/WhipFile.h b/SlnkDWFCom/WhipFile.h
new file mode 100644
index 0000000..8931c06
--- /dev/null
+++ b/SlnkDWFCom/WhipFile.h
@@ -0,0 +1,193 @@
+// WhipFile.h : Declaration of the CWhipFile
+
+#pragma once
+#include "resource.h" // main symbols
+#include "whiptk\whip_toolkit.h"
+#include "myWT_File.h"
+
+using namespace DWFCore;
+using namespace DWFToolkit;
+
+#include "SLNKContourImpl.h"
+#include "SLNKSymbol.h"
+
+#include "SLNKDWF.h"
+
+class CWhipFileState
+{
+public:
+ CWhipFileState()
+ {
+ m_reContouren.Parse(".*", FALSE);
+ m_reLabels.Parse(".*", FALSE);
+ m_reLayers.Parse(".*", FALSE);
+ m_hintScale = -1.0;
+ };
+ BOOL SetLayers(BSTR reContouren, BSTR reLabels)
+ {
+ REParseError status = m_reContouren.Parse( CString(reContouren), false );
+ if (REPARSE_ERROR_OK != status)
+ {
+ myTRACE("\nSorry, kan reguliere expressie contouren niet parsen");
+ // Unexpected error.
+ return FALSE;
+ }
+ status = m_reLabels.Parse( CString(reLabels), false );
+ if (REPARSE_ERROR_OK != status)
+ {
+ myTRACE("\nSorry, kan reguliere expressie labelsB niet parsen");
+ // Unexpected error.
+ return FALSE;
+ }
+ return TRUE;
+ }
+ BOOL SetFilterLayers(BSTR reLayers)
+ {
+ REParseError status = m_reLayers.Parse( CString(reLayers), false );
+ if (REPARSE_ERROR_OK != status)
+ {
+ myTRACE("\nSorry, kan reguliere expressie filterlayers niet parsen");
+ // Unexpected error.
+ return FALSE;
+ }
+ return TRUE;
+ }
+ ~CWhipFileState()
+ {
+ for (size_t i=0; i mcUrl;
+ return m_reContouren.Match(str, &mcUrl);
+ }
+ // Is dit een contourlabel laag
+ BOOL labelMatch(const char* str)
+ {
+ CAtlREMatchContext<> mcUrl;
+ return m_reLabels.Match(str, &mcUrl);
+ }
+ // Is dit een 'gewone' laag die in het resultaat moet verschijnen?
+ BOOL layerMatch(const char* str)
+ {
+ CAtlREMatchContext<> mcUrl;
+ return m_reLayers.Match(str, &mcUrl);
+ }
+ CAtlArray m_SLNKContouren;
+ CAtlArray m_SLNKSymbols;
+ CAtlMap m_SLNKSymbolDefinitions;
+ CAtlArray m_SLNKLabels;
+
+ WT_Units m_contunits;
+ BOOL contLayerActive;
+ BOOL labelLayerActive;
+ double m_hintScale; // Kunnen we gebruiken om symbolen te 'geeken'
+
+private:
+ CAtlRegExp<> m_reContouren;
+ CAtlRegExp<> m_reLabels;
+ CAtlRegExp<> m_reLayers; // Die met SaveAs moeten blijven
+};
+
+// CWhipFile
+class ATL_NO_VTABLE CWhipFile :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public ISupportErrorInfo,
+ public IDispatchImpl
+{
+public:
+ CWhipFile();
+
+DECLARE_REGISTRY_RESOURCEID(IDR_WHIPFILE)
+
+
+BEGIN_COM_MAP(CWhipFile)
+ COM_INTERFACE_ENTRY(IWhipFile)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(ISupportErrorInfo)
+END_COM_MAP()
+
+// ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+public:
+
+ STDMETHOD(Load)(BSTR WhipPath);
+ STDMETHOD(LoadStream)(VARIANT EPlotStream);
+ STDMETHOD(SetLayers)(BSTR reContouren, BSTR reLabels);
+ STDMETHOD(SaveAs)(BSTR WhipPath);
+ STDMETHOD(SaveAs2)(BSTR WhipPath);
+ STDMETHOD(SetLabel)(BSTR IdentLabel, BSTR ExtraLabel);
+ STDMETHOD(SetColor)(BSTR IdentLabel, ULONG rgb, BYTE Alpha);
+ STDMETHOD(SetLabelFont)(BSTR FontName, DOUBLE FontHeight, DOUBLE FontHeightSymbols);
+ STDMETHOD(SetLabelPosition)(BYTE LabelPos);
+ STDMETHOD(get_ContoursXML)(BSTR* pVal);
+ STDMETHOD(get_AddSymbol)(DOUBLE dwgX, DOUBLE dwgY, BSTR symbolName, IUnknown** pVal);
+ STDMETHOD(DefineSymbol)(BSTR symbolName, VARIANT EPlotStream);
+ STDMETHOD(DefineBitmapSymbol)(BSTR symbolName, BSTR symbolPath, DOUBLE height);
+ STDMETHOD(get_Contour)(BSTR IdentLabel, IUnknown** pVal);
+ STDMETHOD(SetFilterLayers)(BSTR reLayers);
+ STDMETHOD(get_FindInContour)(DOUBLE dwgX, DOUBLE dwgY, BSTR* pVal);
+
+private:
+ CWhipFileState m_State;
+
+ WT_String m_FontName;
+ double m_FontHeight, m_FontHeightSymbols;
+ CSLNKContourImpl::LABELPOS m_LabelPos;
+
+ CComQIPtr m_iEPlotSection; // Om scope levend te houden
+ myWT_File m_W2DFile;
+ WT_View m_view; // Initial view
+ HRESULT ProcessContouren();
+ HRESULT SerializePlan(WT_File & my_plan_file, myWT_File & my_file, double scale);
+
+ bool GenerateSymbols(myWT_File &my_file);
+ bool GenerateSymbolLabels(myWT_File &my_file);
+
+ bool GenerateContouren(WT_File &my_planfile, myWT_File &my_file,
+ double scale, BOOL solidOnly);
+ bool GenerateLabels(WT_File &my_planfile, myWT_File &my_file, double scale);
+
+ STDMETHOD(Generate)(myWT_File &my_file);
+ void read_for_contours();
+ void processLabels();
+ static WT_Result my_process_layer (WT_Layer & layer, WT_File & file);
+ //static WT_Result my_process_polygon(WT_Polygon & polygon, WT_File & file);
+ static WT_Result my_process_polyline(WT_Polyline & polyline, WT_File & file);
+ static WT_Result my_process_polytriangle(WT_Polytriangle & polytriangle, WT_File & file);
+ static WT_Result my_process_text (WT_Text & text, WT_File & file);
+public:
+ STDMETHOD(get_hintScale)(DOUBLE* pVal);
+ STDMETHOD(put_hintScale)(DOUBLE newVal);
+};
+
+OBJECT_ENTRY_AUTO(__uuidof(WhipFile), CWhipFile)
diff --git a/SlnkDWFCom/WhipFile.rgs b/SlnkDWFCom/WhipFile.rgs
new file mode 100644
index 0000000..1bdd2a1
--- /dev/null
+++ b/SlnkDWFCom/WhipFile.rgs
@@ -0,0 +1,27 @@
+HKCR
+{
+ SLNKDWF.WhipFile.1 = s 'WhipFile Class'
+ {
+ CLSID = s '{C2632BD5-3157-45A6-8FFC-57063FF2B169}'
+ }
+ SLNKDWF.WhipFile = s 'WhipFile Class'
+ {
+ CLSID = s '{C2632BD5-3157-45A6-8FFC-57063FF2B169}'
+ CurVer = s 'SLNKDWF.WhipFile.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {C2632BD5-3157-45A6-8FFC-57063FF2B169} = s 'WhipFile Class'
+ {
+ ProgID = s 'SLNKDWF.WhipFile.1'
+ VersionIndependentProgID = s 'SLNKDWF.WhipFile'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ val AppID = s '%APPID%'
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/comobjectembed.h b/SlnkDWFCom/comobjectembed.h
new file mode 100644
index 0000000..cb5f8a9
--- /dev/null
+++ b/SlnkDWFCom/comobjectembed.h
@@ -0,0 +1,50 @@
+#ifndef __COMOBJECTEMBED_H_
+#define __COMOBJECTEMBED_H_
+
+
+template //Base must be derived from CComObjectRoot
+class CComObjectEmbed : public Base
+{
+public:
+ typedef Base _BaseClass;
+
+ CComObjectEmbed() {m_pOuterUnknown = NULL;}
+ CComObjectEmbed(void* pv) {m_pOuterUnknown = (IUnknown*)pv;}
+ void SetOuterUnknown(IUnknown *punkContainer) {m_pOuterUnknown = punkContainer;}
+
+#ifdef xx_ATL_DEBUG_INTERFACES
+ ~CComObjectEmbed()
+ {
+ _Module.DeleteNonAddRefThunk(_GetRawUnknown());
+ _Module.DeleteNonAddRefThunk(m_pOuterUnknown);
+ }
+#endif
+
+ STDMETHOD_(ULONG, AddRef)() {return OuterAddRef();}
+ STDMETHOD_(ULONG, Release)() {return OuterRelease();}
+ STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
+ {
+ return _InternalQueryInterface(iid, ppvObject);
+ }
+ template
+ HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
+ {
+ return QueryInterface(__uuidof(Q), (void**)pp);
+ }
+
+ //GetControllingUnknown may be virtual if the Base class has declared
+ //DECLARE_GET_CONTROLLING_UNKNOWN()
+ IUnknown* GetControllingUnknown()
+ {
+#ifdef xx_ATL_DEBUG_INTERFACES
+ IUnknown* p;
+ _Module.AddNonAddRefThunk(m_pOuterUnknown, _T("CComObjectEmbed"), &p);
+ return p;
+#else
+ return m_pOuterUnknown;
+#endif
+ }
+};
+
+
+#endif /* !__COMOBJECTEMBED_H_ */
diff --git a/SlnkDWFCom/eplotsections.cpp b/SlnkDWFCom/eplotsections.cpp
new file mode 100644
index 0000000..7359ec4
--- /dev/null
+++ b/SlnkDWFCom/eplotsections.cpp
@@ -0,0 +1,88 @@
+// EPlotSections.cpp : Implementation of CEPlotSections
+
+#include "stdafx.h"
+#include "EPlotSections.h"
+
+
+// CEPlotSections
+
+STDMETHODIMP CEPlotSections::InterfaceSupportsErrorInfo(REFIID riid)
+{
+ static const IID* arr[] =
+ {
+ &IID_IEPlotSections
+ };
+
+ for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
+ {
+ if (InlineIsEqualGUID(*arr[i],riid))
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+// Omdat de tellingen gekoppeld zijn weten we zeker dat de refcount van
+// onze eigen objecten ook 0 zal zijn en is het dus veilig ze weg te gooien (toch...?)
+void CEPlotSections::FinalRelease()
+{
+ return;
+ for (int i=0; i<(LONG)m_EPlotSections.GetCount(); i++)
+ {
+ CComObjectEmbed *mySection;
+ mySection = &m_EPlotSections.GetAt(i);
+ mySection->FinalRelease();
+ // Gebeurt in de destructor van AtlArray! delete (&m_EPlotSections.GetAt(i));
+ }
+}
+
+void CEPlotSections::InitImpl(CEPlotSectionsImpl *epl)
+{
+ m_pSectionsImpl = epl;
+}
+
+STDMETHODIMP CEPlotSections::get_Parent(IDWFFile **ppParent)
+{
+ return m_pParent->QueryInterface(IID_IDWFFile, (void**)ppParent);
+}
+
+void CEPlotSections::SetParent(IDWFFile *pParent)
+{
+ m_pParent = pParent;
+}
+
+// Actually process the EPlotSections and add them to our collection
+BOOL CEPlotSections::ProcessManifest(DWFManifest& rManifest, CString sourceDescription)
+{
+ ATLASSERT(false);
+ return TRUE;
+}
+
+STDMETHODIMP CEPlotSections::get_Count(LONG* pVal)
+{
+ (*pVal) = (LONG)m_pSectionsImpl->get_Count();
+ return S_OK;
+}
+
+STDMETHODIMP CEPlotSections::get_Item(LONG i, IDispatch** pVal)
+{
+ if (i<0 || i>=(LONG)m_pSectionsImpl->get_Count())
+ return E_INVALIDARG;
+
+ if (m_EPlotSections.GetCount() == 0)
+ { // Tijd om de myEplotSectionImpl's te wrappen met onze myEplotSection's
+ for (int j=0; jget_Count(); j++)
+ {
+ CComObjectEmbed *mySection = new CComObjectEmbed; //= new tMyEplot;
+ mySection->SetParent(this);
+ CEPlotSectionImpl *ps;
+ ps = m_pSectionsImpl->get_Item(j);
+ mySection->InitImpl(ps);
+ mySection->SetOuterUnknown(GetControllingUnknown());
+ mySection->FinalConstruct();
+ m_EPlotSections.Add(*mySection);
+ }
+ }
+ ATLASSERT(i<(LONG)m_EPlotSections.GetCount());
+
+ return (m_EPlotSections.GetAt(i).QueryInterface(pVal));
+}
diff --git a/SlnkDWFCom/myEPlotSection.cpp b/SlnkDWFCom/myEPlotSection.cpp
new file mode 100644
index 0000000..51d4048
--- /dev/null
+++ b/SlnkDWFCom/myEPlotSection.cpp
@@ -0,0 +1,121 @@
+// EPlotSection.cpp : Implementation of CEPlotSection
+
+#include "stdafx.h"
+#include "myEPlotSection.h"
+
+// CEPlotSection
+
+STDMETHODIMP CEPlotSection::InterfaceSupportsErrorInfo(REFIID riid)
+{
+ static const IID* arr[] =
+ {
+ &IID_IEPlotSection
+ };
+
+ for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
+ {
+ if (InlineIsEqualGUID(*arr[i],riid))
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+void CEPlotSection::InitImpl(CEPlotSectionImpl *epl)
+{
+ m_pSectionImpl = epl;
+}
+
+void CEPlotSection::FinalRelease()
+{
+}
+
+STDMETHODIMP CEPlotSection::get_Parent(IEPlotSections **ppParent)
+{
+ return m_pParent->QueryInterface(IID_IEPlotSections, (void**)ppParent);
+}
+
+void CEPlotSection::SetParent(IEPlotSections *pParent)
+{
+ m_pParent = pParent;
+}
+
+STDMETHODIMP CEPlotSection::get_Name(BSTR* pVal)
+{
+ CComBSTR bstrString(m_pSectionImpl->get_Name());
+ return bstrString.CopyTo(pVal);
+}
+
+STDMETHODIMP CEPlotSection::get_Title(BSTR* pVal)
+{
+ CComBSTR bstrString(m_pSectionImpl->get_Title());
+ return bstrString.CopyTo(pVal);
+}
+
+STDMETHODIMP CEPlotSection::get_PaperColor(ULONG* pVal)
+{
+ (*pVal) = m_pSectionImpl->get_PaperColor();
+ return S_OK;
+}
+
+// Always inches
+STDMETHODIMP CEPlotSection::get_PaperClipWidth(DOUBLE* pVal)
+{
+ (*pVal) = m_pSectionImpl->get_PaperClipWidth();
+ return S_OK;
+}
+
+STDMETHODIMP CEPlotSection::Open(BOOL bForWrite)
+{
+ try
+ {
+ m_pSectionImpl->Open( bForWrite);
+ return S_OK;
+ }
+ catch (CString &err)
+ {
+ return myAtlReportError (GetObjectCLSID(), err);
+ }
+}
+
+HRESULT CEPlotSection::Read( void *pv, ULONG cb, ULONG *pcbRead)
+{
+ return m_pSectionImpl->Read( pv, cb, pcbRead);
+};
+
+HRESULT CEPlotSection::Write( const void *pv, ULONG cb, ULONG *pcbWritten)
+{
+ return m_pSectionImpl->Write( pv, cb, pcbWritten) ;
+};
+
+STDMETHODIMP CEPlotSection::Close(void)
+{
+ return m_pSectionImpl->Close();
+}
+
+STDMETHODIMP CEPlotSection::get_SourceDescription(BSTR* pVal)
+{
+ CString s;
+ HRESULT res = m_pSectionImpl->get_SourceDescription(s);
+ (*pVal) = s.AllocSysString();
+ return res;
+}
+
+STDMETHODIMP CEPlotSection::get_PropertiesXML(BSTR* pVal)
+{
+ CString s;
+ HRESULT res = m_pSectionImpl->get_PropertiesXML(s);
+ (*pVal) = s.AllocSysString();
+ return res;
+}
+
+STDMETHODIMP CEPlotSection::get_EPlotSectionImpl(/* CEPlotSectionImpl ** */ BYTE ** pVal)
+{
+ (*pVal) = (BYTE *)m_pSectionImpl;
+ return S_OK;
+}
+
+STDMETHODIMP CEPlotSection::put_EPlotSectionImpl(/* CEPlotSectionImpl * */ BYTE * newVal)
+{
+ return E_FAIL;
+ return S_OK;
+}
diff --git a/SlnkDWFCom/myEPlotSection.h b/SlnkDWFCom/myEPlotSection.h
new file mode 100644
index 0000000..ddab093
--- /dev/null
+++ b/SlnkDWFCom/myEPlotSection.h
@@ -0,0 +1,78 @@
+// EPlotSection.h : Declaration of the CEPlotSection
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+
+#include "myEPlotSectionImpl.h"
+#include "Whiptk/whip_toolkit.h"
+
+// CEPlotSection
+
+class ATL_NO_VTABLE CEPlotSection :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public ISupportErrorInfo,
+ public IDispatchImpl
+// public CEPlotSectionImpl
+{
+public:
+ CEPlotSection()
+ {
+ }
+
+ //REMOVED DECLARE_REGISTRY_RESOURCEID(IDR_EPLOTSECTION)
+
+ BEGIN_COM_MAP(CEPlotSection)
+ COM_INTERFACE_ENTRY(IEPlotSection)
+ COM_INTERFACE_ENTRY(IDispatch)
+ COM_INTERFACE_ENTRY(ISupportErrorInfo)
+ END_COM_MAP()
+
+ // ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease();
+
+protected:
+ IEPlotSections *m_pParent; // Non-addreffed!
+
+private:
+ CEPlotSectionImpl *m_pSectionImpl;
+
+public:
+ void SetParent(IEPlotSections *pParent);
+
+ STDMETHODIMP get_Parent(IEPlotSections **ppParent);
+ STDMETHOD(get_Name)(BSTR* pVal);
+ STDMETHOD(get_Title)(BSTR* pVal);
+
+ void InitImpl(CEPlotSectionImpl *epl);
+
+// IWhipSequentialStream Methods
+public:
+ STDMETHOD(Open)(BOOL bForWrite);
+ STDMETHOD(Read) ( void *pv, ULONG cb, ULONG *pcbRead);
+ STDMETHOD(Write)( const void *pv, ULONG cb,ULONG *pcbWritten);
+ STDMETHOD(Close)(void);
+ STDMETHOD(get_PaperColor)(ULONG* pVal);
+ STDMETHOD(get_SourceDescription)(BSTR* pVal);
+#if DESIRED_CODE(WHIP_OUTPUT)
+ STDMETHOD(get_PropertiesXML)(BSTR* pVal);
+#endif
+ STDMETHOD(get_PaperClipWidth)(DOUBLE* pVal);
+public:
+ STDMETHOD(get_EPlotSectionImpl)(/* CEPlotSectionImpl ** */ BYTE ** pVal);
+public:
+ STDMETHOD(put_EPlotSectionImpl)(/* CEPlotSectionImpl * */ BYTE * newVal);
+};
+
+//REMOVED OBJECT_ENTRY_AUTO(__uuidof(EPlotSection), CEPlotSection)
diff --git a/SlnkDWFCom/resource.h b/SlnkDWFCom/resource.h
new file mode 100644
index 0000000..4964ec1
--- /dev/null
+++ b/SlnkDWFCom/resource.h
@@ -0,0 +1,38 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by SLNKdwf.rc
+//
+#define IDS_PROJNAME 100
+#define IDR_SLNKDWF 101
+#define IDR_DWFFILE 102
+#define IDR_WHIPFILE 103
+#define IDR_WHIP2PNG 104
+#define IDR_ABOUT 105
+#define IDR_SLNKEPLOTSECTION 106
+#define IDR_EPLOTSECTION 107
+#define IDR_EPLOTSECTIONS 108
+#define IDR_WHIPSEQUENTIALSTREAM 109
+#define IDR_TEST 110
+#define IDR_TEST2 111
+#define IDR_SLNKEVENT 112
+#define IDR_ASPOBJECT 113
+#define IDR_WHIP2DC 114
+#define IDR_DC2PNG 115
+#define IDB_MYCONTROL 116
+#define IDR_MYCONTROL 117
+#define IDR_BOUNDINGBOX 118
+#define IDR_DWGPOINT 119
+#define IDR_SLNKCONTOUR 120
+#define IDR_SLNKSYMBOL 126
+#define IDR_OPTIONS 127
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 32768
+#define _APS_NEXT_CONTROL_VALUE 201
+#define _APS_NEXT_SYMED_VALUE 128
+#endif
+#endif
diff --git a/SlnkDWFCom/slnkcont.bin b/SlnkDWFCom/slnkcont.bin
new file mode 100644
index 0000000..9063bce
--- /dev/null
+++ b/SlnkDWFCom/slnkcont.bin
@@ -0,0 +1,26 @@
+HKCR
+{
+ SLNKDWFCom.SLNKContour.1 = s 'SLNKContour Class'
+ {
+ CLSID = s '{476C0F28-5860-485D-BEBD-D03F68E1C930}'
+ }
+ SLNKDWFCom.SLNKContour = s 'SLNKContour Class'
+ {
+ CLSID = s '{476C0F28-5860-485D-BEBD-D03F68E1C930}'
+ CurVer = s 'SLNKDWFCom.SLNKContour.1'
+ }
+ NoRemove CLSID
+ {
+ ForceRemove {476C0F28-5860-485D-BEBD-D03F68E1C930} = s 'SLNKContour Class'
+ {
+ ProgID = s 'SLNKDWFCom.SLNKContour.1'
+ VersionIndependentProgID = s 'SLNKDWFCom.SLNKContour'
+ ForceRemove 'Programmable'
+ InprocServer32 = s '%MODULE%'
+ {
+ val ThreadingModel = s 'Apartment'
+ }
+ 'TypeLib' = s '{B6FCDE6E-141C-4601-B3AC-4DF4D5F25DF8}'
+ }
+ }
+}
diff --git a/SlnkDWFCom/slnksymbol.h b/SlnkDWFCom/slnksymbol.h
new file mode 100644
index 0000000..65ab515
--- /dev/null
+++ b/SlnkDWFCom/slnksymbol.h
@@ -0,0 +1,74 @@
+// SLNKSymbol.h : Declaration of the CSLNKSymbol
+
+#pragma once
+#include "resource.h" // main symbols
+
+#include "SLNKDWF.h"
+#include "SLNKSymbolDefImpl.h"
+#include "SLNKSymbolImpl.h"
+
+#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
+#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
+#endif
+
+
+
+// CSLNKSymbol
+
+class ATL_NO_VTABLE CSLNKSymbol :
+ public CComObjectRootEx,
+ public CComCoClass,
+ public IDispatchImpl
+{
+public:
+ CSLNKSymbol()
+ {
+ }
+
+//REMOVED DECLARE_REGISTRY_RESOURCEID(IDR_SLNKSYMBOL)
+
+
+BEGIN_COM_MAP(CSLNKSymbol)
+ COM_INTERFACE_ENTRY(ISLNKSymbol)
+ COM_INTERFACE_ENTRY(IDispatch)
+END_COM_MAP()
+
+// ISupportsErrorInfo
+ STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+
+ HRESULT FinalConstruct()
+ {
+ return S_OK;
+ }
+
+ void FinalRelease()
+ {
+ }
+
+ // Deze SLNKSymbol wijst naar een CSLNKSymbolImpl in een WhipFile object. We moeten voorkomen
+ // dat deze te snel uit de scope wegvalt. Dat doen we mbv SetParent
+ // Omgekeerd is geen probleem: de WhipFile verwijst niet(!) naar de CSLNKSymbol en heeft er dus
+ // geen last van dat die wegvalt (van zijn SLNKSymbolImpl objecten is hij gewoon eigenaar)
+
+ void SetParent(IWhipFile *pParent)
+ {
+ HRESULT hr = pParent->QueryInterface(IID_IWhipFile, (void **)&m_parent_iWhipFile);
+ };
+ void SetImpl(CSLNKSymbolImpl * pSLNKSymbol);
+
+private:
+ CSLNKSymbolImpl * m_SLNKSymbol;
+ CComQIPtr m_parent_iWhipFile; // Om scope levend te houden
+
+public:
+
+ STDMETHOD(get_Scale)(DOUBLE* pVal);
+ STDMETHOD(put_Scale)(DOUBLE newVal);
+ STDMETHOD(get_Rotation)(LONG* pVal);
+ STDMETHOD(put_Rotation)(LONG newVal);
+ STDMETHOD(get_Contour)(IUnknown** pVal);
+};
+
+//REMOVED OBJECT_ENTRY_AUTO(__uuidof(SLNKSymbol), CSLNKSymbol)
diff --git a/SlnkDWFCom/stdafx.cpp b/SlnkDWFCom/stdafx.cpp
new file mode 100644
index 0000000..67ecdda
--- /dev/null
+++ b/SlnkDWFCom/stdafx.cpp
@@ -0,0 +1,5 @@
+// stdafx.cpp : source file that includes just the standard includes
+// SLNKDWF.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
diff --git a/SlnkDWFCom/stdafx.h b/SlnkDWFCom/stdafx.h
new file mode 100644
index 0000000..6800469
--- /dev/null
+++ b/SlnkDWFCom/stdafx.h
@@ -0,0 +1,77 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef STRICT
+#define STRICT
+#endif
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Allow use of features specific to Windows XP or later.
+#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
+#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
+#endif
+
+#define _ATL_APARTMENT_THREADED
+#define _ATL_NO_AUTOMATIC_NAMESPACE
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+// turns off ATL's hiding of some common and often safely ignored warning messages
+#define _ATL_ALL_WARNINGS
+
+#ifdef _DEBUG
+//#define _ATL_DEBUG_INTERFACES
+#endif
+
+#include "resource.h"
+#include
+#include
+
+using namespace ATL;
+
+// [JGL] added manually
+#include
+#include "atlstr.h"
+#include "atlrx.h"
+#include "../SLNKDwfImpl/jglutil.h"
+
+#include "Options.h"
+
+#include "SLNKDWFStaticRW.h"
+
+#include "dwfcore/File.h"
+#include "dwfcore/String.h"
+
+#include "dwf/package/Constants.h"
+#include "dwf/package/Manifest.h"
+#include "dwf/package/EPlotSection.h"
+#include "dwf/package/reader/PackageReader.h"
+//#include "dwf/package/writer/PackageWriter.h"
+#include "dwf/package/xml.h"
+#include "dwf/package/reader/DuplicateAttributeFilter.h"
+
+using namespace DWFCore;
+using namespace DWFToolkit;
+//using namespace DWFManifest;
+//using namespace DWFXmlObjects;
+//using namespace DWFEPlot;
+//using DWF::DwfResult;
+
+#ifdef _DEBUG
+#include "MemLeakDetect.h"
+#endif
\ No newline at end of file
diff --git a/SlnkDWFCom/unloadIIS.bat b/SlnkDWFCom/unloadIIS.bat
new file mode 100644
index 0000000..d37a33d
--- /dev/null
+++ b/SlnkDWFCom/unloadIIS.bat
@@ -0,0 +1,4 @@
+C:\Inetpub\AdminScripts\adsutil.vbs APPUNLOAD W3SVC/1/Root/SLNKDWF
+C:\Inetpub\AdminScripts\adsutil.vbs APPUNLOAD W3SVC/1/Root/Vigor
+C:\Inetpub\AdminScripts\adsutil.vbs APPUNLOAD W3SVC/1/Root/FacilitorWork
+C:\Inetpub\AdminScripts\adsutil.vbs START_SERVER W3SVC/1
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/.gitignore b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.cpp b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.cpp
new file mode 100644
index 0000000..a4e844c
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.cpp
@@ -0,0 +1,13 @@
+// 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;
+}
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.dsp b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.dsp
new file mode 100644
index 0000000..bda9795
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.dsp
@@ -0,0 +1,346 @@
+# 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 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 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "CxImageCrtDll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "CxImageCrtDll - Win32 Debug" (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 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" /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 0x409 /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 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" /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 0x409 /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
+
+!ENDIF
+
+# Begin Target
+
+# Name "CxImageCrtDll - Win32 Release"
+# Name "CxImageCrtDll - Win32 Debug"
+# 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=..\ximaj2k.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# 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=..\ximasel.cpp
+# SUBTRACT CPP /YX /Yc /Yu
+# 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=.\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=..\ximaj2k.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=..\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
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.rc b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.rc
new file mode 100644
index 0000000..7f8902b
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.rc
@@ -0,0 +1,123 @@
+//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 5,9,9,3
+ PRODUCTVERSION 5,9,9,3
+ 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 5.99c CRT DLL\0"
+ VALUE "CompanyName", "Pizzolato Davide - www.xdp.it\0"
+ VALUE "FileDescription", "cximage\0"
+ VALUE "FileVersion", "5, 9, 9, c\0"
+ VALUE "InternalName", "cximage\0"
+ VALUE "LegalCopyright", "Copyright © 2001 - 2004\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "cximagecrt.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "cximage\0"
+ VALUE "ProductVersion", "5, 9, 9, c\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
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.vcproj b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.vcproj
new file mode 100644
index 0000000..00a320f
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.vcproj
@@ -0,0 +1,1017 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.vcproj.DIJKORAAD.jgl.user b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.vcproj.DIJKORAAD.jgl.user
new file mode 100644
index 0000000..f57b253
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageCrtDll.vcproj.DIJKORAAD.jgl.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageDll.dsw b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageDll.dsw
new file mode 100644
index 0000000..afdd4ba
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageDll.dsw
@@ -0,0 +1,152 @@
+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>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.clw b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.clw
new file mode 100644
index 0000000..349133d
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.clw
@@ -0,0 +1,16 @@
+; 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
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.cpp b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.cpp
new file mode 100644
index 0000000..ff4e12e
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.cpp
@@ -0,0 +1,62 @@
+// 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;
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.h b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.h
new file mode 100644
index 0000000..43d62cf
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.h
@@ -0,0 +1,45 @@
+// 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_)
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.rc b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.rc
new file mode 100644
index 0000000..79f8064
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/CxImageMfcDll.rc
@@ -0,0 +1,123 @@
+//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 5,9,9,3
+ PRODUCTVERSION 5,9,9,3
+ 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 5.99c MFC DLL\0"
+ VALUE "CompanyName", "Pizzolato Davide - www.xdp.it\0"
+ VALUE "FileDescription", "cximage\0"
+ VALUE "FileVersion", "5, 9, 9, c\0"
+ VALUE "InternalName", "cximage\0"
+ VALUE "LegalCopyright", "Copyright © 2001 - 2004\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "cximage.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "cximage\0"
+ VALUE "ProductVersion", "5, 9, 9, c\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
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/StdAfx.cpp b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/StdAfx.cpp
new file mode 100644
index 0000000..a5e4a08
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/StdAfx.cpp
@@ -0,0 +1,8 @@
+// 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"
+
+
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/StdAfx.h b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/StdAfx.h
new file mode 100644
index 0000000..c8b1b0c
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/StdAfx.h
@@ -0,0 +1,42 @@
+// 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
+
+#include // MFC core and standard components
+#include // MFC extensions
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include // MFC OLE classes
+#include // MFC OLE dialog classes
+#include // MFC Automation classes
+#endif // _AFX_NO_OLE_SUPPORT
+
+
+#ifndef _AFX_NO_DB_SUPPORT
+#include // MFC ODBC database classes
+#endif // _AFX_NO_DB_SUPPORT
+
+#ifndef _AFX_NO_DAO_SUPPORT
+#include // MFC DAO database classes
+#endif // _AFX_NO_DAO_SUPPORT
+
+#include // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include // 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_)
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/StdCrt.h b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/StdCrt.h
new file mode 100644
index 0000000..60e3632
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/StdCrt.h
@@ -0,0 +1,24 @@
+// 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
+
+// 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_)
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/cximagemfcdll.dsp b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/cximagemfcdll.dsp
new file mode 100644
index 0000000..80cbd3c
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/cximagemfcdll.dsp
@@ -0,0 +1,330 @@
+# 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 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 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "CxImageMfcDll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "CxImageMfcDll - Win32 Debug" (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 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" /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 0x410 /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 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" /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 0x410 /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
+
+!ENDIF
+
+# Begin Target
+
+# Name "CxImageMfcDll - Win32 Release"
+# Name "CxImageMfcDll - Win32 Debug"
+# 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=..\ximaj2k.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=..\ximasel.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=..\ximaj2k.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=..\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
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/cximagemfcdll.vcproj b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/cximagemfcdll.vcproj
new file mode 100644
index 0000000..58099be
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/cximagemfcdll.vcproj
@@ -0,0 +1,1050 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/cximagemfcdll.vcproj.DIJKORAAD.jgl.user b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/cximagemfcdll.vcproj.DIJKORAAD.jgl.user
new file mode 100644
index 0000000..f57b253
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/cximagemfcdll.vcproj.DIJKORAAD.jgl.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/resource.h b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/resource.h
new file mode 100644
index 0000000..cc1626b
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/resource.h
@@ -0,0 +1,15 @@
+//{{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
diff --git a/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/resrc1.h b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/resrc1.h
new file mode 100644
index 0000000..39ff26e
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/CxImageDLL/resrc1.h
@@ -0,0 +1,15 @@
+//{{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
diff --git a/SlnkDWFImpl/CxImage/CxImage/_ximacfg.h b/SlnkDWFImpl/CxImage/CxImage/_ximacfg.h
new file mode 100644
index 0000000..20168d9
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/_ximacfg.h
@@ -0,0 +1,52 @@
+#if !defined(__ximaCFG_h)
+#define __ximaCFG_h
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported features
+#define CXIMAGE_SUPPORT_ALPHA 1
+#define CXIMAGE_SUPPORT_SELECTION 1
+#define CXIMAGE_SUPPORT_TRANSFORMATION 1
+#define CXIMAGE_SUPPORT_DSP 1
+#define CXIMAGE_SUPPORT_LAYERS 1
+#define CXIMAGE_SUPPORT_INTERPOLATION 1
+
+#define CXIMAGE_SUPPORT_DECODE 1
+#define CXIMAGE_SUPPORT_ENCODE 1 //
+#define CXIMAGE_SUPPORT_WINDOWS 1
+#define CXIMAGE_SUPPORT_WINCE 0 //
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported formats
+#define CXIMAGE_SUPPORT_BMP 1
+#define CXIMAGE_SUPPORT_GIF 1
+#define CXIMAGE_SUPPORT_JPG 1
+#define CXIMAGE_SUPPORT_PNG 1
+#define CXIMAGE_SUPPORT_MNG 0
+#define CXIMAGE_SUPPORT_ICO 1
+#define CXIMAGE_SUPPORT_TIF 1
+#define CXIMAGE_SUPPORT_TGA 1
+#define CXIMAGE_SUPPORT_PCX 1
+#define CXIMAGE_SUPPORT_WBMP 1
+#define CXIMAGE_SUPPORT_WMF 1
+#define CXIMAGE_SUPPORT_J2K 0 // Beta, use JP2
+#define CXIMAGE_SUPPORT_JBG 0 // GPL'd see ../jbig/copying.txt & ../jbig/patents.htm
+
+#define CXIMAGE_SUPPORT_JP2 1
+#define CXIMAGE_SUPPORT_JPC 1
+#define CXIMAGE_SUPPORT_PGX 1
+#define CXIMAGE_SUPPORT_PNM 1
+#define CXIMAGE_SUPPORT_RAS 1
+
+
+/////////////////////////////////////////////////////////////////////////////
+#define CXIMAGE_MAX_MEMORY 256000000
+
+#define CXIMAGE_ERR_NOFILE "null file handler"
+#define CXIMAGE_ERR_NOIMAGE "null image!!!"
+
+/////////////////////////////////////////////////////////////////////////////
+//color to grey mapping
+//#define RGB2GRAY(r,g,b) (((b)*114 + (g)*587 + (r)*299)/1000)
+#define RGB2GRAY(r,g,b) (((b)*117 + (g)*601 + (r)*306) >> 10)
+
+#endif
diff --git a/SlnkDWFImpl/CxImage/CxImage/cximage.dsp b/SlnkDWFImpl/CxImage/CxImage/cximage.dsp
new file mode 100644
index 0000000..7908b85
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/cximage.dsp
@@ -0,0 +1,302 @@
+# 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 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 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "CxImage - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "CxImage - Win32 Debug" (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 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 "_MBCS" /D "_LIB" /D "_AFXDLL" /D "JAS_WIN_MSVC_BUILD" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x410 /d "NDEBUG"
+# ADD RSC /l 0x410 /d "NDEBUG" /d "_AFXDLL"
+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 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 "_MBCS" /D "_LIB" /D "_AFXDLL" /D "JAS_WIN_MSVC_BUILD" /FD /GZ /c
+# SUBTRACT CPP /Fr /YX
+# ADD BASE RSC /l 0x410 /d "_DEBUG"
+# ADD RSC /l 0x410 /d "_DEBUG" /d "_AFXDLL"
+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 Release"
+# Name "CxImage - Win32 Debug"
+# 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=.\ximaj2k.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=.\ximasel.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=.\ximaj2k.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=.\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
diff --git a/SlnkDWFImpl/CxImage/CxImage/cximage.dsw b/SlnkDWFImpl/CxImage/CxImage/cximage.dsw
new file mode 100644
index 0000000..d855b5f
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/cximage.dsw
@@ -0,0 +1,29 @@
+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>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/cximage.sln b/SlnkDWFImpl/CxImage/CxImage/cximage.sln
new file mode 100644
index 0000000..13614ee
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/cximage.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 7.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CxImage", "CxImage.vcproj", "{E6F8F128-84D9-48D6-81D6-C427EAFE738D}"
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ ConfigName.0 = Debug
+ ConfigName.1 = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {E6F8F128-84D9-48D6-81D6-C427EAFE738D}.Debug.ActiveCfg = Debug|Win32
+ {E6F8F128-84D9-48D6-81D6-C427EAFE738D}.Debug.Build.0 = Debug|Win32
+ {E6F8F128-84D9-48D6-81D6-C427EAFE738D}.Release.ActiveCfg = Release|Win32
+ {E6F8F128-84D9-48D6-81D6-C427EAFE738D}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/SlnkDWFImpl/CxImage/CxImage/cximage.vcproj b/SlnkDWFImpl/CxImage/CxImage/cximage.vcproj
new file mode 100644
index 0000000..6ea85b7
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/cximage.vcproj
@@ -0,0 +1,932 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/cximage.vcproj.DIJKORAAD.jgl.user b/SlnkDWFImpl/CxImage/CxImage/cximage.vcproj.DIJKORAAD.jgl.user
new file mode 100644
index 0000000..2bdefdc
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/cximage.vcproj.DIJKORAAD.jgl.user
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/cximage2003.vcproj b/SlnkDWFImpl/CxImage/CxImage/cximage2003.vcproj
new file mode 100644
index 0000000..e8d81c3
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/cximage2003.vcproj
@@ -0,0 +1,272 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/license.txt b/SlnkDWFImpl/CxImage/CxImage/license.txt
new file mode 100644
index 0000000..b5db06b
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/license.txt
@@ -0,0 +1,48 @@
+This copy of the CxImage notices is provided for your convenience. In case of
+any discrepancy between this copy and the notices in the file ximage.h that is
+included in the CxImage distribution, the latter shall prevail.
+
+If you modify CxImage you may insert additional notices immediately following
+this sentence.
+
+--------------------------------------------------------------------------------
+
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+CxImage version 5.99c 17/Oct/2004
+
+CxImage : Copyright (C) 2001 - 2004, Davide Pizzolato
+
+Original CImage and CImageIterator implementation are:
+Copyright (C) 1995, Alejandro Aguilar Sierra (asierra(at)servidor(dot)unam(dot)mx)
+
+Covered code is provided under this license on an "as is" basis, without warranty
+of any kind, either expressed or implied, including, without limitation, warranties
+that the covered code is free of defects, merchantable, fit for a particular purpose
+or non-infringing. The entire risk as to the quality and performance of the covered
+code is with you. Should any covered code prove defective in any respect, you (not
+the initial developer or any other contributor) assume the cost of any necessary
+servicing, repair or correction. This disclaimer of warranty constitutes an essential
+part of this license. No use of any covered code is authorized hereunder except under
+this disclaimer.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, including commercial applications,
+freely and without fee, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+--------------------------------------------------------------------------------
+
+Other information: about CxImage, and the latest version, can be found at the
+CxImage home page: http://www.xdp.it
+
+--------------------------------------------------------------------------------
diff --git a/SlnkDWFImpl/CxImage/CxImage/tif_xfile.cpp b/SlnkDWFImpl/CxImage/CxImage/tif_xfile.cpp
new file mode 100644
index 0000000..6f72475
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/tif_xfile.cpp
@@ -0,0 +1,208 @@
+/*
+ * TIFF file IO, using CxFile.
+ */
+
+#ifdef WIN32
+ #include
+#endif
+#include
+
+#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 ((CxFile*)fd)->Read(buf, 1, size);
+}
+
+static tsize_t
+_tiffWriteProcEx(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return ((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
+ return 0;
+}
+
+#include
+
+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(int 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((int)stream, "TIFF IMAGE", mode));
+}
+
+#ifdef __GNUC__
+extern char* malloc();
+extern char* realloc();
+#else
+#include
+#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));
+}
+
+static void
+Win32WarningHandler(const char* module, const char* fmt, va_list ap)
+{
+#ifdef _DEBUG
+#if (!defined(_CONSOLE) && defined(WIN32))
+ LPTSTR szTitle;
+ LPTSTR szTmp;
+ LPCTSTR szTitleText = "%s Warning";
+ LPCTSTR szDefaultModule = "TIFFLIB";
+ szTmp = (module == NULL) ? (LPTSTR)szDefaultModule : (LPTSTR)module;
+ if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (lstrlen(szTmp) +
+ lstrlen(szTitleText) + lstrlen(fmt) + 128)*sizeof(TCHAR))) == NULL)
+ return;
+ wsprintf(szTitle, szTitleText, szTmp);
+ szTmp = szTitle + (lstrlen(szTitle)+2)*sizeof(TCHAR);
+ wvsprintf(szTmp, fmt, ap);
+ MessageBox(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))
+ LPTSTR szTitle;
+ LPTSTR szTmp;
+ LPCTSTR szTitleText = "%s Error";
+ LPCTSTR szDefaultModule = "TIFFLIB";
+ szTmp = (module == NULL) ? (LPTSTR)szDefaultModule : (LPTSTR)module;
+ if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (lstrlen(szTmp) +
+ lstrlen(szTitleText) + lstrlen(fmt) + 128)*sizeof(TCHAR))) == NULL)
+ return;
+ wsprintf(szTitle, szTitleText, szTmp);
+ szTmp = szTitle + (lstrlen(szTitle)+2)*sizeof(TCHAR);
+ wvsprintf(szTmp, fmt, ap);
+ MessageBox(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION);
+ LocalFree(szTitle);
+ return;
+#else
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+#endif
+#endif
+}
+TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
+
+#endif
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/xfile.h b/SlnkDWFImpl/CxImage/CxImage/xfile.h
new file mode 100644
index 0000000..268c9aa
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/xfile.h
@@ -0,0 +1,76 @@
+/*
+ * 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
+
+ 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
+
+#ifdef WIN32
+ #include
+#endif
+
+#include
+#include
+
+#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;
+};
+
+#endif //__xfile_h
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximabmp.cpp b/SlnkDWFImpl/CxImage/CxImage/ximabmp.cpp
new file mode 100644
index 0000000..80ac102
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximabmp.cpp
@@ -0,0 +1,361 @@
+/*
+ * File: ximabmp.cpp
+ * Purpose: Platform Independent BMP Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#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();
+
+ //copy attributes
+ memcpy(pDib,&head,sizeof(BITMAPINFOHEADER));
+ // Write the file header
+ hFile->Write(&hdr,min(14,sizeof(BITMAPFILEHEADER)),1);
+ // Write the DIB header and the pixels
+ hFile->Write(pDib,GetSize(),1);
+ 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(); //
+ try {
+ if (hFile->Read(&bf,min(14,sizeof(bf)),1)==0) throw "Not a BMP";
+ 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)) throw "Error reading BMP info";
+ DWORD dwCompression=bmpHeader.biCompression;
+ DWORD dwBitCount=bmpHeader.biBitCount; //preserve for BI_BITFIELDS compression
+ bool bIsOldBmp = bmpHeader.biSize == sizeof(BITMAPCOREHEADER);
+
+ bool bTopDownDib = bmpHeader.biHeight<0; // 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;
+ throw "output dimensions returned";
+ }
+
+ if (!Create(bmpHeader.biWidth,bmpHeader.biHeight,bmpHeader.biBitCount,CXIMAGE_FORMAT_BMP))
+ throw "Can't allocate memory";
+
+ head.biXPelsPerMeter = bmpHeader.biXPelsPerMeter;
+ head.biYPelsPerMeter = bmpHeader.biYPelsPerMeter;
+ info.xDPI = (long) floor(bmpHeader.biXPelsPerMeter * 254.0 / 10000.0 + 0.5);
+ info.yDPI = (long) floor(bmpHeader.biYPelsPerMeter * 254.0 / 10000.0 + 0.5);
+
+ if (info.nEscape) throw "Cancelled"; // - 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 - cancel decoding
+
+ switch (dwBitCount) {
+ case 32 :
+ 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
+ Bitfield2RGB(buff32,0,0,0,32);
+ free(buff32);
+ } else throw "can't allocate memory";
+ } else 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 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
+ 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,(WORD)bfmask[0],(WORD)bfmask[1],(WORD)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 (low_nibble) {
+ if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){
+ *(sline + bits) |= (second_byte & 0x0F);
+ }
+ if (i != status_byte - 1)
+ hFile->Read(&second_byte, sizeof(BYTE), 1);
+ bits++;
+ } else {
+ if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){
+ *(sline + bits) = (BYTE)(second_byte & 0xF0);
+ }
+ }
+ 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 (low_nibble) {
+ if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){
+ *(sline + bits) |= (second_byte & 0x0F);
+ }
+ bits++;
+ } else {
+ if ((DWORD)(sline+bits) < (DWORD)(info.pImage+head.biSizeImage)){
+ *(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
+
+ } catch (char *message) {
+ strncpy(info.szLastError,message,255);
+ if (info.nEscape==-1) 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;
+
+ BITMAPCOREHEADER bc;
+
+ 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):
+ 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->biCompression==BI_RGB)&&(pdib->biClrUsed==0))
+ {
+ fh->Seek((long)(pdib->biSize - sizeof(BITMAPINFOHEADER)),SEEK_CUR);
+ break;
+ }
+ return false;
+ }
+
+ FixBitmapInfo(pdib);
+
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_BMP
+////////////////////////////////////////////////////////////////////////////////
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximabmp.h b/SlnkDWFImpl/CxImage/CxImage/ximabmp.h
new file mode 100644
index 0000000..3b794d9
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximabmp.h
@@ -0,0 +1,79 @@
+/*
+ * File: ximabmp.h
+ * Purpose: BMP Image Class Loader and Writer
+ */
+/* ==========================================================
+ * CxImageBMP (c) 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * For conditions of distribution and use, see copyright notice in ximage.h
+ *
+ * Special thanks to Troels Knakkergaard for new features, enhancements and bugfixes
+ *
+ * original CImageBMP and CImageIterator implementation are:
+ * Copyright: (c) 1995, Alejandro Aguilar Sierra
+ *
+ * ==========================================================
+ */
+
+#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
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximacfg.h b/SlnkDWFImpl/CxImage/CxImage/ximacfg.h
new file mode 100644
index 0000000..17dd221
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximacfg.h
@@ -0,0 +1,52 @@
+#if !defined(__ximaCFG_h)
+#define __ximaCFG_h
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported features
+#define CXIMAGE_SUPPORT_ALPHA 1
+#define CXIMAGE_SUPPORT_SELECTION 0
+#define CXIMAGE_SUPPORT_TRANSFORMATION 1
+#define CXIMAGE_SUPPORT_DSP 0
+#define CXIMAGE_SUPPORT_LAYERS 0
+#define CXIMAGE_SUPPORT_INTERPOLATION 0
+
+#define CXIMAGE_SUPPORT_DECODE 1
+#define CXIMAGE_SUPPORT_ENCODE 1 //
+#define CXIMAGE_SUPPORT_WINDOWS 1
+#define CXIMAGE_SUPPORT_WINCE 0 //
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage supported formats
+#define CXIMAGE_SUPPORT_BMP 0
+#define CXIMAGE_SUPPORT_GIF 1
+#define CXIMAGE_SUPPORT_JPG 1
+#define CXIMAGE_SUPPORT_PNG 1
+#define CXIMAGE_SUPPORT_MNG 0
+#define CXIMAGE_SUPPORT_ICO 0
+#define CXIMAGE_SUPPORT_TIF 1
+#define CXIMAGE_SUPPORT_TGA 0
+#define CXIMAGE_SUPPORT_PCX 0
+#define CXIMAGE_SUPPORT_WBMP 0
+#define CXIMAGE_SUPPORT_WMF 0
+#define CXIMAGE_SUPPORT_J2K 0 // Beta, use JP2
+#define CXIMAGE_SUPPORT_JBG 0 // GPL'd see ../jbig/copying.txt & ../jbig/patents.htm
+
+#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_MAX_MEMORY 256000000
+
+#define CXIMAGE_ERR_NOFILE "null file handler"
+#define CXIMAGE_ERR_NOIMAGE "null image!!!"
+
+/////////////////////////////////////////////////////////////////////////////
+//color to grey mapping
+//#define RGB2GRAY(r,g,b) (((b)*114 + (g)*587 + (r)*299)/1000)
+#define RGB2GRAY(r,g,b) (((b)*117 + (g)*601 + (r)*306) >> 10)
+
+#endif
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximadef.h b/SlnkDWFImpl/CxImage/CxImage/ximadef.h
new file mode 100644
index 0000000..54c4c94
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximadef.h
@@ -0,0 +1,197 @@
+#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_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 CXIMAGE_SUPPORT_WINCE
+ #undef CXIMAGE_SUPPORT_WMF
+ #define CXIMAGE_SUPPORT_WMF 0
+ #undef CXIMAGE_SUPPORT_WINDOWS
+ #define CXIMAGE_SUPPORT_WINDOWS 0
+#endif
+
+#ifndef WIN32
+ #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
+
+
+#ifdef WIN32
+#include
+#include
+#endif
+
+#include
+#include
+
+
+#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
+
+
+#ifndef WIN32
+
+#include
+#include
+#include
+
+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
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximadsp.cpp b/SlnkDWFImpl/CxImage/CxImage/ximadsp.cpp
new file mode 100644
index 0000000..11bca60
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximadsp.cpp
@@ -0,0 +1,2370 @@
+// xImaDsp.cpp : DSP functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#include "ximage.h"
+
+#include "ximaiter.h"
+
+#if CXIMAGE_SUPPORT_DSP
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Converts the image to B&W.
+ * The Mean() 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()) return false;
+
+ for (long y=0;ylevel)
+ tmp.SetPixelIndex(x,y,1);
+ else
+ tmp.SetPixelIndex(x,y,0);
+ }
+ }
+ tmp.SetPaletteColor(0,0,0,0);
+ tmp.SetPaletteColor(1,255,255,255);
+ Transfer(tmp);
+ 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; yTransfer(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; yyTransfer(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; yyTransfer(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; yyTransfer(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; yyTransfer(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; yTransfer(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)
+{
+ // 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)
+{
+ // 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 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>8);
+ color.rgbBlue = (BYTE)((hsl.rgbBlue * a0 + color.rgbBlue * a1)>>8);
+ color.rgbGreen = (BYTE)((hsl.rgbGreen * a0 + color.rgbGreen * a1)>>8);
+ SetPixelColor(x,y,color);
+ }
+ }
+ }
+ }
+ } else {
+ for(DWORD j=0; j
+ for (int i=0;i<256;i++) {
+ cTable[i] = (BYTE)max(0,min(255,(int)((i-128)*c + brightness)));
+ }
+
+ 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()) 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
+
+ for(long y=ymin; y
+ for(long x=xmin; x 0 && (y+kmax-1) < head.biHeight && x-k2 > 0 && (x+kmax-1) < head.biWidth)
+ {
+ b=0;
+ iCount = 0;
+ iY2 = ((y-k2)*info.dwEffWidth);
+ for(long j=-k2;j 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.SetPixelColor(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,pSelection!=0,true,true);
+ if (!tmp.IsValid()) 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 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 = 255-abs(r-rr);
+ c.rgbGreen = 255-abs(g-gg);
+ c.rgbBlue = 255-abs(b-bb);
+ tmp.SetPixelColor(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 rgbBackgrnd = GetTransColor();
+ RGBQUAD rgb1, rgb2, rgbDest;
+
+ for(long lY=0;lY>8);
+ } 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)>>8);
+ rgbDest.rgbGreen = (BYTE)((rgb1.rgbGreen*a1+rgb2.rgbGreen*a)>>8);
+ rgbDest.rgbRed = (BYTE)((rgb1.rgbRed*a1+rgb2.rgbRed*a)>>8);
+ }
+
+ if (bEditAlpha) rgbDest.rgbReserved = (BYTE)(((1+rgb1.rgbReserved)*a)>>8);
+ }
+ break;
+ case OpSrcBlend:
+ if(memcmp(&rgb1,&rgbBackgrnd,sizeof(RGBQUAD))==0)
+ rgbDest = rgb2;
+ else
+ {
+ long lBDiff = abs(rgb1.rgbBlue - rgbBackgrnd.rgbBlue);
+ long lGDiff = abs(rgb1.rgbGreen - rgbBackgrnd.rgbGreen);
+ long lRDiff = abs(rgb1.rgbRed - rgbBackgrnd.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)
+{
+ RGBQUAD rgbBackgrnd = imagesrc2.GetTransColor();
+ RGBQUAD rgb1;
+
+ long width = imagesrc2.GetWidth();
+ long height = imagesrc2.GetHeight();
+
+ int x, y;
+
+ for(x = 0; x < width; x++)
+ {
+ for(y = 0; y < height; y++)
+ {
+ rgb1 = imagesrc2.GetPixelColor(x, y);
+ if(memcmp(&rgb1, &rgbBackgrnd, sizeof(RGBQUAD)) != 0)
+ SetPixelColor(x + lXOffset, y + lYOffset, rgb1);
+ }
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * 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
+ for (int i=0;i<256;i++) {
+ cTable[i] = (BYTE)max(0,min(255,(int)( pow((double)i, dinvgamma) / dMax)));
+ }
+
+ return Lut(cTable);
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_WINCE == 0
+/**
+ * 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,pSelection!=0,true,true);
+ if (!tmp.IsValid()) 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
+ for(long x=xmin; xGetWidth();
+ 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< 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;kGetPixelIndex(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<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> 1;
+ j = 0;
+ for (i=0;i>= 1;
+ }
+ j += k;
+ }
+
+ /* Compute the FFT */
+ c1 = -1.0;
+ c2 = 0.0;
+ l2 = 1;
+ for (l=0;lGetWidth();
+ 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
+ for (long x=0;xGetPixelIndex(x,y);
+ c.rgbGreen=g->GetPixelIndex(x,y);
+ c.rgbBlue=b->GetPixelIndex(x,y);
+ switch (colorspace){
+ case 1:
+ SetPixelColor(x,y,HSLtoRGB(c));
+ break;
+ case 2:
+ SetPixelColor(x,y,YUVtoRGB(c));
+ break;
+ case 3:
+ SetPixelColor(x,y,YIQtoRGB(c));
+ break;
+ case 4:
+ SetPixelColor(x,y,XYZtoRGB(c));
+ break;
+ default:
+ SetPixelColor(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; iGetWidth()-1;
+ long h = ch->GetHeight()-1;
+
+ double correction,ix,iy,ixx,ixy,iyy,den,num;
+ int x,y,xy0,xp1,xm1,yp1,ym1;
+ for(x=1; xGetPixelIndex(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;
+
+ num= (1.0+iy*iy)*ixx - ix*iy*ixy + (1.0+ix*ix)*iyy;
+ den= 1.0+ix*ix+iy*iy;
+ correction = num/den;
+
+ tmp.SetPixelIndex(x,y,(BYTE)min(255,max(0,(xy0 + radius * correction))));
+ }
+ }
+
+ for (x=0;x<=w;x++){
+ tmp.SetPixelIndex(x,0,ch->GetPixelIndex(x,0));
+ tmp.SetPixelIndex(x,h,ch->GetPixelIndex(x,h));
+ }
+ for (y=0;y<=h;y++){
+ tmp.SetPixelIndex(0,y,ch->GetPixelIndex(0,y));
+ tmp.SetPixelIndex(w,y,ch->GetPixelIndex(w,y));
+ }
+ 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,pSelection!=0,true,true);
+ if (!tmp.IsValid()) 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; ymaxb) 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.SetPixelColor(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,pSelection!=0,true,true);
+ if (!tmp.IsValid()) 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 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_length/2 - row >= 0) &&
+ (j + cmatrix_length/2 - row < cmatrix_length))
+ scale += cmatrix[j + cmatrix_length/2 - row];
+ }
+ for (i = 0; i= row - cmatrix_length/2) &&
+ (j <= row + cmatrix_length/2))
+ 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; j0; 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 255) dest_row[u*3+v] = 255;
+ else dest_row[u*3+v] = value;
+ }
+ }
+ }
+
+ Transfer(tmp);
+
+ 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;
+ }
+
+ dbScaler = 100.0/ymax;
+
+ for(long y=ymin; y
+ for(long x=xmin; x
+ if (!pDib) return false;
+ FloodFill2(x,y,GetPixelColor(x,y),FillColor);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+void CxImage::FloodFill2(int x, int y, RGBQUAD old_color, RGBQUAD new_color)
+{
+ // Fill in the actual pixels.
+ // Function steps recursively until it finds borders (color that is not old_color)
+ if (!IsInside(x,y)) return;
+
+ RGBQUAD r = GetPixelColor(x,y);
+ COLORREF cr = RGB(r.rgbRed,r.rgbGreen,r.rgbBlue);
+
+ if(cr == RGB(old_color.rgbRed,old_color.rgbGreen,old_color.rgbBlue)
+ && cr != RGB(new_color.rgbRed,new_color.rgbGreen,new_color.rgbBlue) ) {
+
+ // the above if statement, after && is there to prevent
+ // stack overflows. The program will continue to find
+ // colors if you flood-fill an entire region (entire picture)
+
+ SetPixelColor(x,y,new_color);
+
+ FloodFill2((x+1),y,old_color,new_color);
+ FloodFill2((x-1),y,old_color,new_color);
+ FloodFill2(x,(y+1),old_color,new_color);
+ FloodFill2(x,(y-1),old_color,new_color);
+ }
+}*/
+///////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DSP
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximaenc.cpp b/SlnkDWFImpl/CxImage/CxImage/ximaenc.cpp
new file mode 100644
index 0000000..277ee85
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximaenc.cpp
@@ -0,0 +1,920 @@
+// xImaCodec.cpp : Encode Decode functions
+/* 07/08/2001 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#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" // - WMF/EMF support
+#endif
+
+#if CXIMAGE_SUPPORT_J2K
+#include "ximaj2k.h"
+#endif
+
+#if CXIMAGE_SUPPORT_JBG
+#include "ximajbg.h"
+#endif
+
+#if CXIMAGE_SUPPORT_JASPER
+#include "ximajas.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 (implemented using CxMemFile or CxIOFile),
+ * open and enabled for writing.
+ * \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 // - 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_J2K
+ if (imagetype==CXIMAGE_FORMAT_J2K){
+ CxImageJ2K 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
+
+ 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 (implemented using CxMemFile or CxIOFile).
+ * \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(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
+ 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.
+ * \return true if everything is ok
+ */
+bool CxImage::Encode2RGBA(BYTE * &buffer, long &size)
+{
+ if (buffer!=NULL){
+ strcpy(info.szLastError,"the buffer must be empty");
+ return false;
+ }
+ CxMemFile file;
+ file.Open();
+ if(Encode2RGBA(&file)){
+ 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 (implemented using CxMemFile or CxIOFile).
+ * \return true if everything is ok
+ */
+bool CxImage::Encode2RGBA(CxFile *hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ for (DWORD y = 0; yPutC(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 ( imagetype > 0 && imagetype < CMAX_IMAGE_FORMATS ){
+ 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 ( imagetype > 0 && imagetype < CMAX_IMAGE_FORMATS ){
+// 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 (implemented using 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 (implemented using 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 (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_J2K
+ { CxImageJ2K 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_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); //
+ 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_J2K
+ if (imagetype==CXIMAGE_FORMAT_J2K){
+ CxImageJ2K 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
+
+ strcpy(info.szLastError,"Decode: Unknown or wrong format");
+ return false;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif //CXIMAGE_SUPPORT_DECODE
+////////////////////////////////////////////////////////////////////////////////
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximaexif.cpp b/SlnkDWFImpl/CxImage/CxImage/ximaexif.cpp
new file mode 100644
index 0000000..480252c
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximaexif.cpp
@@ -0,0 +1,873 @@
+/*
+ * File: ximaexif.cpp
+ * Purpose: EXIF reader
+ * 18/Aug/2002 Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ * based on jhead-1.8 by Matthias Wandel
+ */
+
+#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;iGetC();
+
+ 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);
+ /*
+ 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;
+
+ /* 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 de;
+ int a;
+ int NumDirEntries;
+ unsigned ThumbnailOffset = 0;
+ unsigned ThumbnailSize = 0;
+
+ NumDirEntries = Get16u(DirStart);
+
+ if ((DirStart+2+NumDirEntries*12) > (OffsetBase+ExifLength)){
+ strcpy(m_szLastError,"Illegally sized directory");
+ return false;
+ }
+
+ for (de=0;de= 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
+
+ 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);
+ }
+ 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);
+ }
+ }
+
+
+ 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;aComments,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;aPutC(0xff);
+ hFile->PutC(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 Use it before Create()
+ */
+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
+ 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)>>8) > CXIMAGE_MAX_MEMORY){
+ strcpy(info.szLastError,"CXIMAGE_MAX_MEMORY exceeded");
+ return NULL;
+ }
+
+ // set the correct bpp value
+ switch (wBpp){
+ case 1:
+ head.biClrUsed = 2; break;
+ case 4:
+ head.biClrUsed = 16; break;
+ case 8:
+ head.biClrUsed = 256; break;
+ default:
+ head.biClrUsed = 0;
+ }
+
+ //set the common image informations
+ info.dwEffWidth = ((((wBpp * dwWidth) + 31) / 32) * 4);
+ info.dwType = imagetype;
+
+ // initialize BITMAPINFOHEADER
+ head.biSize = sizeof(BITMAPINFOHEADER); //
+ 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;
+
+ 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. USE CAREFULLY
+ */
+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 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)
+{
+ 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;
+ pLayers = from.pLayers;
+
+ memset(&from.head,0,sizeof(BITMAPINFOHEADER));
+ memset(&from.info,0,sizeof(CXIMAGEINFO));
+ from.pDib = from.pSelection = from.pAlpha = NULL;
+ from.pLayers = 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. Use carefully !!!
+ */
+void CxImage::Ghost(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;
+ pLayers = from->pLayers;
+ info.pGhost=from;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * turns a 16 or 32 bit bitfield image into a RGB image
+ */
+void CxImage::Bitfield2RGB(BYTE *src, WORD redmask, WORD greenmask, WORD 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[1]);
+ p[2+x3]=(BYTE)((w & redmask)>>ns[2]);
+ }
+ }
+ break;
+ }
+ case 32:
+ {
+ // 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[ x4];
+ p[1+x3]=src[1+x4];
+ p[2+x3]=src[2+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; yrgbRed,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.
+ */
+void CxImage::FreeMemory(void* memblock)
+{
+ if (memblock)
+ free(memblock);
+}
+////////////////////////////////////////////////////////////////////////////////
+//EOF
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximage.h b/SlnkDWFImpl/CxImage/CxImage/ximage.h
new file mode 100644
index 0000000..0ebadcf
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximage.h
@@ -0,0 +1,648 @@
+/*
+ * File: ximage.h
+ * Purpose: General Purpose Image Class
+ */
+/*
+ --------------------------------------------------------------------------------
+
+ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+ CxImage version 5.99c 17/Oct/2004
+
+ CxImage : Copyright (C) 2001 - 2004, 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
+
+ --------------------------------------------------------------------------------
+ */
+#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" // adjust some #define
+
+/* see "ximacfg.h" for CxImage configuration options */
+
+/////////////////////////////////////////////////////////////////////////////
+// CxImage formats enumerator
+enum ENUM_CXIMAGE_FORMATS{
+CXIMAGE_FORMAT_UNKNOWN,
+#if CXIMAGE_SUPPORT_BMP
+CXIMAGE_FORMAT_BMP,
+#endif
+#if CXIMAGE_SUPPORT_GIF
+CXIMAGE_FORMAT_GIF,
+#endif
+#if CXIMAGE_SUPPORT_JPG
+CXIMAGE_FORMAT_JPG,
+#endif
+#if CXIMAGE_SUPPORT_PNG
+CXIMAGE_FORMAT_PNG,
+#endif
+#if CXIMAGE_SUPPORT_MNG
+CXIMAGE_FORMAT_MNG,
+#endif
+#if CXIMAGE_SUPPORT_ICO
+CXIMAGE_FORMAT_ICO,
+#endif
+#if CXIMAGE_SUPPORT_TIF
+CXIMAGE_FORMAT_TIF,
+#endif
+#if CXIMAGE_SUPPORT_TGA
+CXIMAGE_FORMAT_TGA,
+#endif
+#if CXIMAGE_SUPPORT_PCX
+CXIMAGE_FORMAT_PCX,
+#endif
+#if CXIMAGE_SUPPORT_WBMP
+CXIMAGE_FORMAT_WBMP,
+#endif
+#if CXIMAGE_SUPPORT_WMF
+CXIMAGE_FORMAT_WMF,
+#endif
+#if CXIMAGE_SUPPORT_J2K
+CXIMAGE_FORMAT_J2K,
+#endif
+#if CXIMAGE_SUPPORT_JBG
+CXIMAGE_FORMAT_JBG,
+#endif
+#if CXIMAGE_SUPPORT_JP2
+CXIMAGE_FORMAT_JP2,
+#endif
+#if CXIMAGE_SUPPORT_JPC
+CXIMAGE_FORMAT_JPC,
+#endif
+#if CXIMAGE_SUPPORT_PGX
+CXIMAGE_FORMAT_PGX,
+#endif
+#if CXIMAGE_SUPPORT_PNM
+CXIMAGE_FORMAT_PNM,
+#endif
+#if CXIMAGE_SUPPORT_RAS
+CXIMAGE_FORMAT_RAS,
+#endif
+CMAX_IMAGE_FORMATS
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// 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
+ BYTE nQuality; ///< used for JPEG
+ 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
+
+} CXIMAGEINFO;
+
+public:
+ //public structures
+struct rgb_color { BYTE r,g,b; };
+
+#if CXIMAGE_SUPPORT_WINDOWS
+// text placement data
+// members must be initialized with the InitTextInfo(&this) function.
+typedef struct tagCxTextInfo
+{
+ TCHAR text[4096]; ///< text (char -> TCHAR for UNICODE [Cesar M])
+ LOGFONT lfont; ///< font and codepage data
+ COLORREF fcolor; ///< foreground color
+ long align; ///< DT_CENTER, DT_RIGHT, DT_LEFT aligment for multiline text
+ 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() { Destroy(); };
+ CxImage& operator = (const CxImage&);
+//@}
+
+/** \addtogroup Initialization */ //@{
+ void* Create(DWORD dwWidth, DWORD dwHeight, DWORD wBpp, DWORD imagetype = 0);
+ bool Destroy();
+ void Clear(BYTE bval=0);
+ void Copy(const CxImage &src, bool copypixels = true, bool copyselection = true, bool copyalpha = true);
+ bool Transfer(CxImage &from);
+ 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);
+//@}
+
+/** \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();
+ const TCHAR* GetVersion();
+ 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);
+
+ 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);
+
+ //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 SetStdPalette();
+//@}
+
+/** \addtogroup Pixel */ //@{
+ bool IsInside(long x, long y);
+ bool IsTransparent(long x,long y);
+ 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);
+ void *BlindGetPixelPointer(const long x,const long y);
+//@}
+
+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
+ };
+ 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);
+//@}
+#endif //CXIMAGE_SUPPORT_INTERPOLATION
+
+/** \addtogroup Painting */ //@{
+#if CXIMAGE_SUPPORT_WINCE
+ long Blt(HDC pDC, long x=0, long y=0);
+#endif
+#if CXIMAGE_SUPPORT_WINDOWS
+ 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);
+ // 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);
+//@}
+#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 Encode2RGBA(BYTE * &buffer, long &size);
+//@}
+#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 Mirror();
+ 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();
+ bool QIShrink(long newx, long newy, CxImage* const iDst = NULL);
+//@}
+#endif //CXIMAGE_SUPPORT_TRANSFORMATION
+
+#if CXIMAGE_SUPPORT_DSP
+/** \addtogroup DSP */ //@{
+ bool Contour();
+ bool HistogramStretch(long method = 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 ShiftRGB(long r, long g, long b);
+ bool Threshold(BYTE level);
+ 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 };
+ 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.0, float amount = 0.5, int threshold = 0);
+ bool Lut(BYTE* pLut);
+ bool Lut(BYTE* pLutR, BYTE* pLutG, BYTE* pLutB, BYTE* pLutA = 0);
+//@}
+
+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);
+ //
+ 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);
+//@}
+
+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();
+ bool SelectionCreate();
+ bool SelectionDelete();
+ bool SelectionInvert();
+ bool SelectionAddRect(RECT r);
+ bool SelectionAddEllipse(RECT r);
+ bool SelectionAddPolygon(POINT *points, long npoints);
+ bool SelectionAddColor(RGBQUAD c);
+ bool SelectionAddPixel(int x, int y);
+ bool SelectionCopy(CxImage &from);
+ bool SelectionIsInside(long x, long y);
+ bool SelectionIsValid();
+ void SelectionGetBox(RECT& r);
+ bool SelectionToHRGN(HRGN& region);
+ bool SelectionSplit(CxImage *dest);
+//@}
+#endif //CXIMAGE_SUPPORT_SELECTION
+
+#if CXIMAGE_SUPPORT_ALPHA
+/** \addtogroup Alpha */ //@{
+ void AlphaClear();
+ void 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);
+
+ 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;
+//@}
+#endif //CXIMAGE_SUPPORT_LAYERS
+
+protected:
+/** \addtogroup Protected */ //@{
+ void Startup(DWORD imagetype = 0);
+ void CopyInfo(const CxImage &src);
+ void Ghost(CxImage *src);
+ void RGBtoBGR(BYTE *buffer, int length);
+ static float HueToRGB(float n1,float n2, float hue);
+ void Bitfield2RGB(BYTE *src, WORD redmask, WORD greenmask, WORD bluemask, BYTE bpp);
+ static int CompareColors(const void *elem1, const void *elem2);
+
+ 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** pLayers; //generic layers
+//@}
+};
+
+////////////////////////////////////////////////////////////////////////////
+#endif // !defined(__CXIMAGE_H)
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximagif.cpp b/SlnkDWFImpl/CxImage/CxImage/ximagif.cpp
new file mode 100644
index 0000000..bd2f32c
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximagif.cpp
@@ -0,0 +1,1564 @@
+/*
+ * File: ximagif.cpp
+ * Purpose: Platform Independent GIF Image Class Loader and Writer
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#include "ximagif.h"
+
+#if CXIMAGE_SUPPORT_GIF
+
+#include "ximaiter.h"
+
+#if CXIMAGE_SUPPORT_WINCE
+ #define assert(s)
+#else
+ #include
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+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;
+
+ if (info.nEscape == -1) {
+ // Return output dimensions only
+ head.biWidth = dscgif.scrwidth;
+ head.biHeight = dscgif.scrheight;
+ return true;
+ }
+
+ /* AD - for interlace */
+ TabCol.sogct = (short)(1 << ((dscgif.pflds & 0x07)+1));
+ TabCol.colres = (short)(((dscgif.pflds & 0x70) >> 3) + 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;
+
+ 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;
+
+ for (BOOL bContinue = TRUE; bContinue; )
+ {
+ if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;}
+
+ if (info.nEscape > 0) return false; // - 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
+ BYTE *byteData = (BYTE *) & image;
+ image.l = byteData[0]+byteData[1]*256;
+ image.t = byteData[2]+byteData[3]*256;
+ image.w = byteData[4]+byteData[5]*256;
+ image.h = byteData[6]+byteData[7]*256;
+
+ 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++;
+
+ // Local colour map?
+ if (image.pf & 0x80) {
+ TabCol.sogct = (short)(1 << ((image.pf & 0x07) +1));
+ assert(3 == sizeof(struct rgb_color));
+ fp->Read(TabCol.paleta,sizeof(struct rgb_color)*TabCol.sogct,1);
+ //log << "Local colour map" << endl;
+ }
+
+ int bpp; // select the correct bit per pixel value
+ if (TabCol.sogct <= 2) bpp = 1;
+ else if (TabCol.sogct <= 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);
+ } 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);
+ }
+ }
+
+ //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 < TabCol.sogct; i++) {
+ r[i] = TabCol.paleta[i].r;
+ g[i] = TabCol.paleta[i].g;
+ b[i] = TabCol.paleta[i].b;
+
+ if (RGB(r[i],g[i],b[i]) == 0xFFFFFF) has_white = 1;
+ }
+
+ // Force transparency colour white...
+ //if (0) if (info.nBkgndIndex != -1)
+ // r[info.nBkgndIndex] = g[info.nBkgndIndex] = b[info.nBkgndIndex] = 255;
+ // Fill in with white // AD
+ if (info.nBkgndIndex != -1) {
+ while (i < 256) {
+ has_white = 1;
+ r[i] = g[i] = b[i] = 255;
+ i++;
+ }
+ }
+
+ // Force last colour to white... // AD
+ //if ((info.nBkgndIndex != -1) && !has_white) {
+ // r[255] = g[255] = b[255] = 255;
+ //}
+
+ SetPalette((info.nBkgndIndex != -1 ? 256 : TabCol.sogct), 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; // - 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);
+ } 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;ySetPixelColor(x+image.l,dscgif.scrheight-1-image.t-y,GetPixelColor(x,image.h-y-1));
+ }
+ }
+ }
+
+ prevdispmeth = gifgce.dispmeth;
+
+ //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.nFrame==iImage) bContinue=false; else iImage++;
+
+ break;
+ }
+ case ';': //terminator
+ bContinue=false;
+ break;
+ default:
+ bPreviousWasNull = (ch==0);
+ break;
+ }
+ }
+ }
+
+ if (bTrueColor>=2 && imaRGB){
+ if (gifgce.transpcolflag){
+ imaRGB->SetTransColor(GetPaletteColor((BYTE)info.nBkgndIndex));
+ imaRGB->SetTransIndex(0);
+ }
+ Transfer(*imaRGB);
+ }
+ delete imaRGB;
+
+ 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)));
+ if (bContinue) {
+ if (gifgce.transpcolflag) info.nBkgndIndex = gifgce.transpcolindex;
+ info.dwFrameDelay = gifgce.delaytime;
+ m_dispmeth = gifgce.dispmeth;
+ } } }
+
+ if (fc == 0xFE) { // 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) { // 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;
+
+}
+
+
+// - 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 = file->Read( buf , 1 , GIFBUFTAM) ;
+ if( ibfmax < GIFBUFTAM ) buf[ ibfmax ] = 255 ;
+ // FW 06/02/98 <<<
+ ibf = 0;
+ }
+ if (ibf>=ibfmax) return -1; // 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)
+{
+ // for 1 & 4 bpp images, the pixels are compressed
+ if (head.biBitCount < 8){
+ for(long x=0;x> 3);
+ if (head.biBitCount==4){
+ pos = (BYTE)(4*(1-x%2));
+ *iDst &= ~(0x0F<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);
+ }
+
+ 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)
+{
+ try{
+ if (fp==NULL) throw "invalid file pointer";
+ if (pImages==NULL || pagecount==0 || pImages[0]==NULL) throw "multipage GIF, no images!";
+
+ 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);
+ }
+
+ ghost.SetDisposalMethod(GetDisposalMethod());
+ ghost.EncodeExtension(fp);
+
+ EncodeComment(fp);
+
+ ghost.EncodeBody(fp);
+
+ for (int i=2; i<=pagecount; i++){
+ if (pImages[i-1]==NULL) throw "Bad image pointer";
+ ghost.Ghost(pImages[i-1]);
+
+ ghost.SetDisposalMethod(GetDisposalMethod());
+ ghost.EncodeExtension(fp);
+
+ ghost.EncodeBody(fp,bLocalColorMap);
+ }
+
+ fp->PutC(';'); // Write the GIF file terminator
+
+ } catch (char *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; iPutC(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.transpcolflag = (info.nBkgndIndex != -1) ? 1 : 0;
+ gifgce.userinputflag = 0;
+ gifgce.dispmeth = m_dispmeth;
+ gifgce.res = 0;
+ gifgce.delaytime = (WORD)info.dwFrameDelay;
+ gifgce.transpcolindex = (BYTE)info.nBkgndIndex;
+ fp->PutC(sizeof(gifgce));
+ fp->Write(&gifgce, sizeof(gifgce), 1);
+ 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; iPutC(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;yPutC(';'); // Write the GIF file terminator
+
+ return true; // done!
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+// Return the next pixel from the image
+// 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 / 256) & 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(register 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 ((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) {
+ 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++ = 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 ((ret = (short)out_line(iter, buf, linewidth)) < 0) {
+ delete[] buf;
+ return(ret);
+ }
+ bufptr = buf;
+ bufcnt = linewidth;
+ }
+ }
+ }
+ }
+ ret = 0;
+ if (bufcnt != linewidth)
+ 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
+ BYTE *byteData = (BYTE *) & image;
+ image.l = byteData[0]+byteData[1]*256;
+ image.t = byteData[2]+byteData[3]*256;
+ image.w = byteData[4]+byteData[5]*256;
+ image.h = byteData[6]+byteData[7]*256;
+
+ 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 bpp; // select the correct bit per pixel value
+ if (TempTabCol.sogct <= 2) bpp = 1;
+ else if (TempTabCol.sogct <= 16) bpp = 4;
+ else bpp = 8;
+
+ Create(image.w, image.h, bpp, CXIMAGE_FORMAT_GIF);
+
+ 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 (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::SetDisposalMethod(int dm)
+{ m_dispmeth=dm; }
+////////////////////////////////////////////////////////////////////////////////
+long CxImageGIF::GetDisposalMethod()
+{ return m_dispmeth; }
+////////////////////////////////////////////////////////////////////////////////
+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) ;
+ while (1){
+ 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(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(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;
+ while (1){
+ c = GifNextPixel();
+ if ((rle.rl_count > 0) && (c != rle.rl_pixel)) rle_flush(&rle);
+ if (c == EOF) break;
+ if (rle.rl_pixel == c){
+ rle.rl_count++;
+ } else {
+ rle.rl_pixel = c;
+ rle.rl_count = 1;
+ }
+ }
+ rle_output(rle.code_eof,&rle);
+ rle_output_flush(&rle);
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_GIF
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximagif.h b/SlnkDWFImpl/CxImage/CxImage/ximagif.h
new file mode 100644
index 0000000..c7b7af6
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximagif.h
@@ -0,0 +1,248 @@
+/*
+ * 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
+ *
+ * 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 transpcolflag:1;
+ BYTE userinputflag:1;
+ BYTE dispmeth:3;
+ BYTE res:3;
+ 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; m_dispmeth=0; m_comment[0]='\0';}
+
+// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_GIF);}
+// bool Save(const char * 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 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);
+ void SetDisposalMethod(int dm);
+ long GetDisposalMethod();
+
+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;
+ int m_dispmeth;
+
+//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
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximahist.cpp b/SlnkDWFImpl/CxImage/CxImage/ximahist.cpp
new file mode 100644
index 0000000..2b2a2e8
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximahist.cpp
@@ -0,0 +1,649 @@
+// xImaHist.cpp : histogram functions
+/* 28/01/2004 v1.00 - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#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; yn) 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.
+ * \return true if everything is ok
+ * \author [dave] and [nipper]
+ */
+bool CxImage::HistogramStretch(long method)
+{
+ if (!pDib) return false;
+
+ if ((head.biBitCount==8) && IsGrayScale()){
+ // get min/max info
+ BYTE minc = 255, maxc = 0;
+ BYTE gray;
+ long y;
+
+ double dbScaler = 50.0/head.biHeight;
+
+ for (y=0; y maxc) maxc = gray;
+ }
+ }
+
+ if (minc == 0 && maxc == 255) return true;
+
+ // calculate LUT
+ BYTE lut[256];
+ BYTE range = maxc - minc;
+ if (range != 0){
+ for (long x = minc; x <= maxc; x++){
+ lut[x] = (BYTE)(255 * (x - minc) / range);
+ }
+ } else lut[minc] = minc;
+
+ for (y=0; y
+ // get min/max info
+ BYTE minc = 255, maxc = 0;
+ RGBQUAD color;
+ long y;
+
+ for (y=0; y maxc) maxc = color.rgbRed;
+ if (color.rgbBlue > maxc) maxc = color.rgbBlue;
+ if (color.rgbGreen > maxc) maxc = color.rgbGreen;
+ }
+ }
+
+ if (minc == 0 && maxc == 255)
+ return true;
+
+ // calculate LUT
+ BYTE lut[256];
+ BYTE range = maxc - minc;
+
+ if (range != 0){
+ for (long x = minc; x <= maxc; x++){
+ lut[x] = (BYTE)(255 * (x - minc) / range);
+ }
+ } else lut[minc] = minc;
+
+ // normalize image
+ double dbScaler = 100.0/head.biHeight;
+
+ for (y=0; y
+ // get min/max info
+ BYTE minR = 255, maxR = 0;
+ BYTE minG = 255, maxG = 0;
+ BYTE minB = 255, maxB = 0;
+ RGBQUAD color;
+ long y;
+
+ for (y=0; y maxR) maxR = color.rgbRed;
+ if (color.rgbBlue > maxB) maxB = color.rgbBlue;
+ if (color.rgbGreen > maxG) maxG = color.rgbGreen;
+ }
+ }
+
+ 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 (long x = minR; x <= maxR; x++){
+ lutR[x] = (BYTE)(255 * (x - minR) / range);
+ }
+ } else lutR[minR] = minR;
+
+ BYTE lutG[256];
+ range = maxG - minG;
+ if (range != 0) {
+ for (long x = minG; x <= maxG; x++){
+ lutG[x] = (BYTE)(255 * (x - minG) / range);
+ }
+ } else lutG[minG] = minG;
+
+ BYTE lutB[256];
+ range = maxB - minB;
+ if (range != 0) {
+ for (long x = minB; x <= maxB; x++){
+ lutB[x] = (BYTE)(255 * (x - minB) / range);
+ }
+ } else lutB[minB] = minB;
+
+ // normalize image
+ double dbScaler = 100.0/head.biHeight;
+
+ for (y=0; y
+ // S = ( R - C ) ( B - A / D - C )
+ double alimit = 0.0;
+ double blimit = 255.0;
+ double lowerc = 255.0;
+ double upperd = 0.0;
+ double tmpGray;
+
+ RGBQUAD color;
+ RGBQUAD yuvClr;
+ double stretcheds;
+
+ if ( head.biClrUsed == 0 ){
+ long x, y, xmin, xmax, ymin, ymax;
+ xmin = ymin = 0;
+ xmax = head.biWidth;
+ ymax = head.biHeight;
+
+ for( y = ymin; y < ymax; y++ ){
+ info.nProgress = (long)(50*y/ymax);
+ if (info.nEscape) break;
+ for( x = xmin; x < xmax; x++ ){
+ color = GetPixelColor( x, y );
+ tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+ if ( tmpGray < lowerc ) lowerc = tmpGray;
+ if ( tmpGray > upperd ) upperd = tmpGray;
+ }
+ }
+ if (upperd==lowerc) return false;
+
+ for( y = ymin; y < ymax; y++ ){
+ info.nProgress = (long)(50+50*y/ymax);
+ if (info.nEscape) break;
+ for( x = xmin; x < xmax; x++ ){
+
+ color = GetPixelColor( x, y );
+ yuvClr = RGBtoYUV(color);
+
+ // Stretch Luminance
+ tmpGray = (double)yuvClr.rgbRed;
+ stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit;
+ if ( stretcheds < 0.0 ) stretcheds = 0.0;
+ else if ( stretcheds > 255.0 ) stretcheds = 255.0;
+ yuvClr.rgbRed = (BYTE)stretcheds;
+
+ color = YUVtoRGB(yuvClr);
+ SetPixelColor( x, y, color );
+ }
+ }
+ } else {
+ DWORD j;
+ for( j = 0; j < head.biClrUsed; j++ ){
+ color = GetPaletteColor( (BYTE)j );
+ tmpGray = RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);
+ if ( tmpGray < lowerc ) lowerc = tmpGray;
+ if ( tmpGray > upperd ) upperd = tmpGray;
+ }
+ if (upperd==lowerc) return false;
+
+ for( j = 0; j < head.biClrUsed; j++ ){
+
+ color = GetPaletteColor( (BYTE)j );
+ yuvClr = RGBtoYUV( color );
+
+ // Stretch Luminance
+ tmpGray = (double)yuvClr.rgbRed;
+ stretcheds = (double)(tmpGray - lowerc) * ( (blimit - alimit) / (upperd - lowerc) ); // + alimit;
+ if ( stretcheds < 0.0 ) stretcheds = 0.0;
+ else if ( stretcheds > 255.0 ) stretcheds = 255.0;
+ yuvClr.rgbRed = (BYTE)stretcheds;
+
+ color = YUVtoRGB(yuvClr);
+ SetPaletteColor( (BYTE)j, color );
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+// HistogramEqualize function by : 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 = GetPixelColor( 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 = GetPixelColor( x, y );
+ yuvClr = RGBtoYUV(color);
+
+ yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed];
+
+ color = YUVtoRGB(yuvClr);
+ SetPixelColor( 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(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 = GetPixelColor( 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 = GetPixelColor( x, y );
+ yuvClr = RGBtoYUV( color );
+
+ yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed];
+
+ color = YUVtoRGB( yuvClr );
+ SetPixelColor( 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(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 = GetPixelColor( 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 = GetPixelColor( x, y );
+ yuvClr = RGBtoYUV( color );
+
+ yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) );
+
+ color = YUVtoRGB( yuvClr );
+ SetPixelColor( 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(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 = GetPixelColor( 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 = GetPixelColor( 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 );
+ SetPixelColor( 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
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximaico.cpp b/SlnkDWFImpl/CxImage/CxImage/ximaico.cpp
new file mode 100644
index 0000000..8650c39
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximaico.cpp
@@ -0,0 +1,299 @@
+/*
+ * File: ximaico.cpp
+ * Purpose: Platform Independent ICON Image Class Loader and Writer (MS version)
+ * 07/Aug/2001 Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#include "ximaico.h"
+
+#if CXIMAGE_SUPPORT_ICO
+
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageICO::Decode(CxFile *hFile)
+{
+ if (hFile==NULL) return false;
+
+ DWORD off = hFile->Tell(); //
+ 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);
+ // 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);
+
+ if ((page>=0)&&(page
+ BITMAPINFOHEADER bih;
+ hFile->Seek(off + icon_list[page].dwImageOffset, SEEK_SET);
+ hFile->Read(&bih,sizeof(BITMAPINFOHEADER),1);
+ 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];
+ 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* dst = info.pImage;
+ 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++) {
+ for(long x=0;xRead(mask, masksize, 1)){
+
+ bool bGoodMask=false;
+ for (int im=0;im>3)]>>(7-x%8))&0x01)){
+ AlphaSet(x,y,0);
+ bNeedAlpha=true;
+ }
+ }
+ }
+ if (!bNeedAlpha) AlphaDelete();
+#endif //CXIMAGE_SUPPORT_ALPHA
+
+ if (c==24){ //check if there is only one transparent color
+ RGBQUAD cc,ct;
+ long* pcc = (long*)&cc;
+ long* pct = (long*)&ct;
+ int nTransColors=0;
+ for (int y = 0; y < head.biHeight; y++){
+ for (int x = 0; x < head.biWidth; x++){
+ if (((mask[y*maskwdt+(x>>3)] >> (7-x%8)) & 0x01)){
+ cc = GetPixelColor(x,y,false);
+ if (nTransColors==0){
+ nTransColors++;
+ ct = cc;
+ } else {
+ if (*pct!=*pcc){
+ nTransColors++;
+ }
+ }
+ }
+ }
+ }
+ if (nTransColors==1){
+ SetTransColor(ct);
+ SetTransIndex(0);
+#if CXIMAGE_SUPPORT_ALPHA
+ AlphaDelete(); //because we have a unique transparent color in the image
+#endif //CXIMAGE_SUPPORT_ALPHA
+ }
+ }
+
+ // - 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 (int y = 0; y < head.biHeight; y++){
+ for (int x = 0; x < head.biWidth; x++){
+ colorsUsed[GetPixelIndex(x,y)] = 1;
+ }
+ }
+
+ int iTransIdx = -1;
+ for (int x = 0; x < (int)head.biClrUsed; 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 (int y = 0; y < head.biHeight; y++){
+ for (int 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, 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;
+}
+////////////////////////////////////////////////////////////////////////////////
+#if CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+bool CxImageICO::Encode(CxFile * hFile)
+{
+ if (EncodeSafeCheck(hFile)) return false;
+
+ //check format limits
+ if ((head.biWidth>255)||(head.biHeight>255)){
+ strcpy(info.szLastError,"Can't save this image as icon");
+ return false;
+ }
+
+ //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
+ ICONHEADER icon_header={0,1,1};
+ ICONDIRENTRY icon_list={(BYTE)head.biWidth,(BYTE)head.biHeight,(BYTE)head.biClrUsed ,0,0,(WORD)bitcount,
+ sizeof(BITMAPINFOHEADER)+head.biClrUsed*sizeof(RGBQUAD)+
+ imagesize+masksize,
+ sizeof(ICONHEADER)+sizeof(ICONDIRENTRY)};
+ BITMAPINFOHEADER bi={sizeof(BITMAPINFOHEADER),head.biWidth,2*head.biHeight,1,(WORD)bitcount,
+ 0,imagesize,0,0,0,0};
+
+ hFile->Write(&icon_header,sizeof(ICONHEADER),1); //write the headers
+ hFile->Write(&icon_list,sizeof(ICONDIRENTRY),1);
+ hFile->Write(&bi,sizeof(BITMAPINFOHEADER),1);
+ if (pal) hFile->Write(pal,head.biClrUsed*sizeof(RGBQUAD),1); //write palette
+
+#if CXIMAGE_SUPPORT_ALPHA
+ if (AlphaIsValid() && head.biClrUsed==0){
+ BYTE* src = info.pImage;
+ BYTE* buf=(BYTE*)malloc(imagesize);
+ BYTE* dst = buf;
+ for (long y = 0; y < head.biHeight; y++) {
+ for(long x=0;xWrite(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};
+ RGBQUAD ct = GetTransColor();
+ long* pc = (long*)&c;
+ long* pct= (long*)&ct;
+ bool bTransparent = info.nBkgndIndex != -1;
+#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 && GetPixelColor(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<Write(mask,masksize,1);
+ free(mask);
+ return true;
+}
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ENCODE
+////////////////////////////////////////////////////////////////////////////////
+#endif // CXIMAGE_SUPPORT_ICO
+
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximaico.h b/SlnkDWFImpl/CxImage/CxImage/ximaico.h
new file mode 100644
index 0000000..5698d70
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximaico.h
@@ -0,0 +1,52 @@
+/*
+ * 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) {}
+
+// bool Load(const char * imageFileName){ return CxImage::Load(imageFileName,CXIMAGE_FORMAT_ICO);}
+// bool Save(const char * imageFileName){ return CxImage::Save(imageFileName,CXIMAGE_FORMAT_ICO);}
+ bool Decode(CxFile * hFile);
+ bool Decode(FILE *hFile) { CxIOFile file(hFile); return Decode(&file); }
+
+#if CXIMAGE_SUPPORT_ENCODE
+ bool Encode(CxFile * hFile);
+ bool Encode(FILE *hFile) { CxIOFile file(hFile); return Encode(&file); }
+#endif // CXIMAGE_SUPPORT_ENCODE
+};
+
+#endif
+
+#endif
diff --git a/SlnkDWFImpl/CxImage/CxImage/ximainfo.cpp b/SlnkDWFImpl/CxImage/CxImage/ximainfo.cpp
new file mode 100644
index 0000000..76bf495
--- /dev/null
+++ b/SlnkDWFImpl/CxImage/CxImage/ximainfo.cpp
@@ -0,0 +1,388 @@
+// ximainfo.cpp : main attributes
+/* 03/10/2004 v1.00 - Davide Pizzolato - www.xdp.it
+ * CxImage version 5.99c 17/Oct/2004
+ */
+
+#include "ximage.h"
+
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \return the color used for transparency, and/or for background color
+ */
+RGBQUAD CxImage::GetTransColor()
+{
+ if (head.biBitCount<24 && info.nBkgndIndex != -1) 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)
+{
+ info.nBkgndIndex = idx;
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * 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; //
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * 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=96;
+ info.xDPI = dpi;
+ head.biXPelsPerMeter = (long) floor(dpi * 10000.0 / 254.0 + 0.5);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * Set resolution for TIFF, JPEG, PNG and BMP formats.
+ */
+void CxImage::SetYDPI(long dpi)
+{
+ if (dpi<=0) dpi=96;
+ info.yDPI = dpi;
+ head.biYPelsPerMeter = (long) floor(dpi * 10000.0 / 254.0 + 0.5);
+}
+////////////////////////////////////////////////////////////////////////////////
+/**
+ * \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)
+{
+ if (imagetype=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